create2.vue 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. <!-- -->
  2. <template>
  3. <div >
  4. <el-breadcrumb class="divi2" separator-class="el-icon-arrow-right">
  5. <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  6. <el-breadcrumb-item :to="{ path: '/visi-dataset'}">数据集管理</el-breadcrumb-item>
  7. <el-breadcrumb-item>动态数据集</el-breadcrumb-item>
  8. </el-breadcrumb>
  9. <el-divider class="divi"></el-divider>
  10. <div class="title_score">
  11. <!-- el-form 中添加 status-icon 可检测状态-->
  12. <el-form :inline="true" ref = "dataInfo" :model="dataInfo" :rules="datarules" class="demo-form-inline">
  13. <el-form-item label="数据集名称" prop="datasetName">
  14. <el-input v-model="dataInfo.datasetName" placeholder="请输入数据集内容"></el-input>
  15. </el-form-item>
  16. <el-form-item label="抽取周期" prop="extractionPeriod">
  17. <el-input v-model="dataInfo.extractionPeriod" placeholder="请输入抽取周期" clearable
  18. @focus="dialogVisible = true">
  19. </el-input>
  20. </el-form-item>
  21. <!-- <el-form-item label="抽取次数">-->
  22. <!-- <el-input-->
  23. <!-- placeholder="请输入抽取次数"-->
  24. <!-- v-model="dataInfo.extractioNumber"-->
  25. <!-- maxlength = '10'-->
  26. <!-- minlength = ‘1’-->
  27. <!-- oninput="value=value.replace(/[^\d]/g, '')"-->
  28. <!-- clearable>-->
  29. <!-- </el-input>-->
  30. <!-- </el-form-item>-->
  31. <el-form-item label="类别" prop="classificationtag">
  32. <el-select v-model="dataInfo.classificationtag"
  33. filterable
  34. allow-create
  35. ref = 'classfi'
  36. @change="demo1()">
  37. <el-option v-for="data in classification" :key="data.categoryId" :label="data.categoryName" :value="data.categoryId">
  38. </el-option>
  39. </el-select>
  40. </el-form-item>
  41. <el-form-item label="备注" prop="remarks" >
  42. <el-input v-model = "dataInfo.remarks" ref = 'remarks' clearable placeholder="备注" ></el-input>
  43. </el-form-item>
  44. <!-- 测试一下获得python-kafka模板 -->
  45. <el-form-item>
  46. <el-button type="primary" @click="getPythonKafkaTmp()">获得代码模板</el-button>
  47. </el-form-item>
  48. </el-form>
  49. </div>
  50. <div class="body"> <!-- 数据框整体大小 -->
  51. <div class="allDiv"> <!-- 初始界面 -->
  52. <div class="leftDiv"> <!-- 控制左边树形区域的div -->
  53. <div class="leftDivTitle"><!-- 控制左边树形区域的上方的div -->
  54. <el-tag style=" width: 100%;text-align: center;">系统数据</el-tag>
  55. </div>
  56. <div class="leftDivTree" > <!-- 控制左边树形区域的下方的div -->
  57. <el-tree
  58. v-if="showTree"
  59. id = 'tree'
  60. node-key="subEquipmentid"
  61. :props="treeDefaultProps"
  62. ref="tree"
  63. :load="loadTreeNode"
  64. lazy
  65. draggable
  66. :allow-drag="allowdrag"
  67. :allow-drop="allowDrop"
  68. @node-drag-end = "treeNodeDragEnd">
  69. <!-- @node-click="treeNodeClick">-->
  70. <span class="custom-tree-node" slot-scope="{ node, data }">
  71. <span>
  72. <i :class="data.icon" style="margin-right: 4px"></i>{{ node.label }}
  73. </span>
  74. </span>
  75. </el-tree>
  76. </div>
  77. </div>
  78. <div class="midDiv"> <!-- 控制中间区域的div -->
  79. <div class="midDivTop">
  80. <div class="midDivTopImg">
  81. <el-tooltip content="运行" placement="bottom-end" effect="dark">
  82. <i @mouseover="yunXingMouseOver"
  83. @mouseleave="yunXingMouseLeave" id='yunXing' @click="yunXingClick"
  84. style="height: 50px;width: 50px; margin: 10px 5px 10px 10px ;font-size: 23px;"
  85. class="iconfont icon-yunXang"></i>
  86. </el-tooltip>
  87. <el-tooltip content="预览" placement="bottom-end" effect="dark">
  88. <i @mouseover="yuLanMouseOver"
  89. @mouseleave="yuLanMouseLeave" id="yuLan" @click="preview"
  90. style="height: 25px;width: 25px; margin: 10px 5px 10px 10px;font-size: 23px;"
  91. class = 'iconfont icon-preview'>
  92. </i>
  93. </el-tooltip>
  94. <el-tooltip content="日志" effect="dark">
  95. <i @mouseover="riZhiMouseOver"
  96. @mouseleave="riZhiMouseLeave" id="riZhi" @click=shourizhi()
  97. style="height: 25px;width: 25px; margin: 10px 5px 10px 10px;font-size: 23px;"
  98. class = 'iconfont icon-tishi'>
  99. </i>
  100. </el-tooltip>
  101. </div>
  102. </div> <!-- 控制中间区域的上方div -->
  103. <div class="midDivData">
  104. <div class="datasourceDiv" id="drag" @dragover="dragDragOver" @dragleave="dragDragLeave">
  105. <el-divider><i class=" icon iconfont icon-xitong2"></i></el-divider>
  106. <div v-for="subEquipment in subEquipments" :key="subEquipment.key" style="display: inline-block">
  107. <div style="margin-left: 10px; margin-top:10px" @mouseover="subEquipment.quXiao = true" @mouseleave="subEquipment.quXiao = false">
  108. <i draggable="true" v-if="subEquipment.table"
  109. style="margin: 5px 10px 10px 15px;vertical-align: middle"
  110. :class=subEquipment.icon
  111. @click="handleClick(subEquipment.id)"
  112. @dblclick="dblClick(subEquipment.id)">
  113. </i>
  114. <i style="position: absolute;" :id = subEquipment.id v-if="subEquipment.quXiao"
  115. @mouseover="quXiaoMouseOver(subEquipment.id)"
  116. @mouseleave="quXiaoMouseLeave(subEquipment.id)"
  117. @click="quXiao(subEquipment.id)"
  118. class="iconfont icon-quxiao"></i>
  119. <span class="demonstration" style="vertical-align: middle;display: block;font-size: 1px; margin-top: 5px;text-align: center">{{ subEquipment.imageTable.tableName }}</span>
  120. </div>
  121. </div>
  122. </div>
  123. <div class="rizhiDiv" v-if="showRiZhi">
  124. <el-tag>日志</el-tag>
  125. <div class="rizhiDivtext">
  126. <span v-text="soutRizhi"></span>
  127. </div>
  128. </div>
  129. </div><!-- 控制中间区域的数据输入区的div -->
  130. </div>
  131. <div class="rightDiv" v-if="true"> <!-- 控制右侧属性区域的div -->
  132. <el-tag style=" width: 100%;text-align: center;border-bottom: 0.2px solid #000000;" >{{detailTitle.worldName}}</el-tag>
  133. <el-table
  134. :data="tableData"
  135. :row-style="{height:'0'}"
  136. :cell-style="{padding:'0'}"
  137. v-loading="dataListLoading"
  138. size="100%"
  139. height=95%
  140. border
  141. >
  142. <el-table-column v-for="tablelist in tablelists" :key="tablelist.id"
  143. :prop='tablelist.prop'
  144. :label="tablelist.label">
  145. </el-table-column>
  146. </el-table>
  147. <!-- <el-tabs type="border-card" >-->
  148. <!-- <el-tab-pane label="表数据预览" >-->
  149. <!-- <el-tag style=" width: 100%;text-align: center;" >{{detailTitle.worldName}}</el-tag>-->
  150. <!-- <el-table-->
  151. <!-- :data="tableData"-->
  152. <!-- :row-style="{height:'0'}"-->
  153. <!-- :cell-style="{padding:'0'}"-->
  154. <!-- size="100%"-->
  155. <!-- height="428"-->
  156. <!-- border-->
  157. <!-- >-->
  158. <!-- <el-table-column v-for="tablelist in tablelists" :key="tablelist.id"-->
  159. <!-- :prop='tablelist.prop'-->
  160. <!-- :label="tablelist.label">-->
  161. <!-- </el-table-column>-->
  162. <!-- </el-table>-->
  163. <!-- </el-tab-pane>-->
  164. <!-- <el-tab-pane label="word"></el-tab-pane>-->
  165. <!-- <el-tab-pane label="图片"></el-tab-pane>-->
  166. <!-- </el-tabs>-->
  167. </div>
  168. </div>
  169. <div class="pop"><!-- 各种弹窗 -->
  170. <!-- 子设备字段选择弹窗 -->
  171. <el-dialog title="子设备配置"
  172. :close-on-click-modal="false"
  173. :visible.sync="showEqumField"
  174. width="40%"
  175. @mouseover.native="showChooseAddTitle"
  176. append-to-body>
  177. <div style="text-align: center;margin-top: -20px;">
  178. <span style="width: 10%">子设备名称 : </span>
  179. <el-input v-model="detailTitle.worldName" style="margin-left: 20px; height:10%;width: 40%"></el-input>
  180. </div>
  181. <div style="margin-top: 10px;margin-left: 25px;">
  182. <el-transfer
  183. filterable
  184. :titles="['待选字段', '已选字段']"
  185. @change="changeMeasurepoint"
  186. v-model="sureSelect"
  187. :data="selectData"
  188. />
  189. </div>
  190. <span slot="footer" class="dialog-footer">
  191. <el-button @click="showEqumField = false">取 消</el-button>
  192. <el-button type="primary" @click="closeEqupField">确 定</el-button>
  193. </span>
  194. </el-dialog>
  195. <!-- 字段预览弹窗 -->
  196. <el-dialog title="预览"
  197. :visible.sync="showPreview"
  198. width="40%"
  199. append-to-body>
  200. <el-tabs type="border-card">
  201. <el-tab-pane>
  202. <span slot="label">{{predatasetName}}</span>
  203. <!-- <i class="iconfont icon-xitong4"></i>-->
  204. <el-divider class="tableDivider"></el-divider>
  205. <el-table
  206. :data="preTableDate"
  207. height="250"
  208. v-loading ='prewListLoading'
  209. border
  210. style="width: 100%">
  211. <el-table-column v-for="preTalblelist in preTalbelists" :key="preTalblelist.id"
  212. :prop="preTalblelist.prop"
  213. :label="preTalblelist.label"
  214. width="180">
  215. </el-table-column>
  216. </el-table>
  217. </el-tab-pane>
  218. <!-- <el-tab-pane label="word"></el-tab-pane>-->
  219. <!-- <el-tab-pane label="图片"></el-tab-pane>-->
  220. </el-tabs>
  221. <span slot="footer" class="dialog-footer">
  222. <el-button @click="showPreview = false">取 消</el-button>
  223. <el-button type="primary" @click="showPreview = false">确 定</el-button>
  224. </span>
  225. </el-dialog>
  226. <el-dialog custom-class="cron-box-dialog-first" :visible.sync="dialogVisible" v-if="dialogVisible">
  227. <mycron v-bind:extractionPeriod.sync="dataInfo.extractionPeriod"></mycron>
  228. </el-dialog>
  229. </div>
  230. </div>
  231. <div style="text-align: right;margin-top: -135px;margin-right: 80px;position:relative;z-index: 999" >
  232. <el-button >取消</el-button>
  233. <el-button type="primary" @click="dySubmit(dataInfo) " >确定</el-button>
  234. </div>
  235. <PythonKafkaTmp v-if="pythonKafkaVisible" ref="pythonKafkaTmp" @refreshDataList="getDataList"></PythonKafkaTmp>
  236. </div>
  237. </template>
  238. <script>
  239. // 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
  240. // 例如:import 《组件名称》 from '《组件路径》';
  241. import mycron from './quartz/mycron'
  242. import PythonKafkaTmp from '../alg/python-kafka-tmp.vue'
  243. import { MessageBox } from 'element-ui'
  244. import { Message } from "element-ui"
  245. export default {
  246. // import引入的组件需要注入到对象中才能使用
  247. components: {
  248. mycron,
  249. PythonKafkaTmp
  250. },
  251. data () {
  252. var checkExtractionPeriod = (rule, value, callback) => {
  253. if (!value) {
  254. return callback(new Error('抽取周期不能为空'))
  255. } else {
  256. return callback()
  257. }
  258. }
  259. // 这里存放数据
  260. return {
  261. dataInfo: {
  262. datasetName: '', // 数据集名称
  263. extractionPeriod: '', // 抽取周期
  264. extractioNumber: '', // 抽取次数
  265. classificationtag: 1,
  266. remarks: ''
  267. },
  268. measurepoint: [], // 你要的数据在这儿
  269. pythonKafkaVisible: false,
  270. dataListLoading: false,
  271. prewListLoading: false,
  272. classification: [],
  273. predatasetName: '数据集预览', // 预览是时候显示的表头信息
  274. // base_url: 'http://localhost:8086/',
  275. showTree: true, // 获取树的数据后 更新数据
  276. showInfo: false, // 属性数据预览
  277. showRiZhi: false, // 控制日志的显隐
  278. soutRizhi: '运行过程,将会显示在这儿 。再次点击日志图标,将关闭窗口', // 输出日志内容
  279. showPreview: false, // 控制预览窗口的显隐
  280. showTable: false,
  281. // userID: '666', // 用户编号
  282. userID: this.$store.state.user.id,
  283. userName: this.$store.state.user.name,
  284. ildName: '', // 制作数据集时,之后留下的文件名称 方便改为用户指定的名字。
  285. subEquipments: [], // 存储拖拽的子设备
  286. yunXingUid: 0, // 点击运行后,命名产生的文件名
  287. dragFlg: 0, // 判断是否拖拽至指定区域
  288. subEquipmentId: 0, // 拖拽子设备的id 从0开始
  289. selectData: [], // 存储子设备字段
  290. sureSelect: [], // 存储已经选择的子设备字段
  291. showEqumField: false, // 控制子设备段显隐
  292. imsql: [], // 向后台提交是数据 包括:所属煤矿、系统、子系统、设备等 以及选择的字段,hbase的地址
  293. sign: 0, // 标记双击图标选择的ID 用于记录选择的字段数据
  294. clicktime: null, // 用于解决双击会触发两次单击事件
  295. dialogVisible: false,
  296. detailTitle: { // 右侧属性框表头
  297. worldName: '属性信息'
  298. },
  299. tablelists: [], // 子设备字段名
  300. tableData: [], // 子设备数据
  301. preTalbelists: [{
  302. prop: 'ziduan',
  303. label: '字段'
  304. }], // 选择的子设备字段
  305. preTableDate: [], // 选择的子设备字段对应的数据
  306. treeDefaultProps: {
  307. children: 'children',
  308. label: 'name',
  309. isLeaf: 'leaf'
  310. },
  311. datarules: {
  312. datasetName: [
  313. { required: true, message: '请输入数据集名称', trigger: 'blur' },
  314. { min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
  315. ],
  316. extractionPeriod: [
  317. { validator: checkExtractionPeriod, trigger: 'blur' }
  318. ]
  319. }
  320. }
  321. },
  322. // 监听属性 类似于data概念
  323. computed: {},
  324. // 监控data中的数据变化
  325. watch: {
  326. 'dataInfo.datasetName' (oldval, newval) {
  327. this.predatasetName = newval + '预览'
  328. },
  329. 'dataInfo.extractionPeriod' () {
  330. this.$refs['dataInfo'].validateField('extractionPeriod')
  331. }
  332. },
  333. // 方法集合
  334. methods: {
  335. // 手动给穿梭框内容添加title
  336. showChooseAddTitle (e) {
  337. // let dom = e.target;
  338. // if (dom.title) return;
  339. // dom.title = dom.innerText;
  340. },
  341. changeMeasurepoint (value, direction, movedKeys) {
  342. let measurepointID
  343. for (let i = 0; i < movedKeys.length; i++) {
  344. const sign = movedKeys[i]
  345. measurepointID = this.selectData[sign].measurepointId
  346. if (direction === 'right') {
  347. this.measurepoint.push(measurepointID)
  348. } else {
  349. this.measurepoint.splice(this.measurepoint.indexOf(measurepointID), 1)
  350. }
  351. }
  352. },
  353. demo1 () {
  354. if (typeof this.dataInfo.classificationtag !== 'number') {
  355. MessageBox.confirm(
  356. `确定新增分类[${this.dataInfo.classificationtag}]?`,
  357. '提示',
  358. {
  359. confirmButtonText: '确定',
  360. cancelButtonText: '取消',
  361. type: 'warning'
  362. }
  363. ).then(() => {
  364. this.$http({
  365. url: this.$http.adornUrl(`/category/save`),
  366. method: 'post',
  367. data: this.$http.adornData({
  368. 'categoryId': undefined,
  369. 'categoryName': this.dataInfo.classificationtag
  370. })
  371. }).then(({data}) => {
  372. if (data && data.code === 0) {
  373. // 更新this.dataInfo.classificationtag 为最新的分类ID
  374. this.classificationList()
  375. this.$refs.classfi.blur()
  376. this.$refs.remarks.focus()
  377. // = this.dataInfo.classificationtag
  378. }
  379. })
  380. }).catch(() => {
  381. this.dataInfo.classificationtag = ''
  382. })
  383. }
  384. },
  385. // 新增 / 修改
  386. addOrUpdateHandle (id) {
  387. this.addOrUpdateVisible = true
  388. this.$nextTick(() => {
  389. this.$refs.addOrUpdate.init(id)
  390. })
  391. },
  392. yunXingMouseOver () {
  393. document.getElementById('yunXing').className = 'iconfont icon-yunXang1'
  394. },
  395. yunXingMouseLeave () {
  396. document.getElementById('yunXing').className = 'iconfont icon-yunXang'
  397. },
  398. async yunXingClick () {
  399. this.showRiZhi = true
  400. this.soutRizhi = '检测设备状态完毕,开始抽取数据....' + '\n' + '....' // 输出日志内容
  401. this.yunXingUid = new Date().getTime()
  402. for (let i = 0; i < this.imsql.length; i++) {
  403. if (i === 0) {
  404. this.imsql[i].oldFileName = this.userID + '_' + this.imsql[i].subEquipmentID + '_' + this.imsql[i].id
  405. this.imsql[i].newFileName = this.imsql[i].oldFileName
  406. if (this.imsql.length === 1) {
  407. this.imsql[i].oldFileName = this.userID + '_' + this.yunXingUid
  408. this.imsql[i].newFileName = this.userID + '_' + this.yunXingUid
  409. }
  410. } else if (i === this.imsql.length - 1) {
  411. this.imsql[i].oldFileName = this.imsql[i - 1].newFileName
  412. this.imsql[i].newFileName = this.userID + '_' + this.yunXingUid
  413. } else {
  414. this.imsql[i].oldFileName = this.imsql[i - 1].newFileName
  415. this.imsql[i].newFileName = this.userID + '_' + this.imsql[i].subEquipmentID + '_' + this.imsql[i].id
  416. }
  417. }
  418. for (let j = 0; j < this.imsql.length; j++) {
  419. await this.$http({
  420. url: this.$http.adornUrl('/dataset/dynamic/makeDyDataSet'),
  421. method: 'post',
  422. data: this.$http.adornData(this.imsql[j], false)
  423. }).then(subresult => {
  424. var context = subresult.data
  425. this.soutRizhi = this.soutRizhi + '\n' + context.info
  426. })
  427. }
  428. this.soutRizhi = this.soutRizhi + '\n' + '动态数据测试抽取完成,点击确定制作数据集'
  429. },
  430. yuLanMouseOver () {
  431. document.getElementById('yuLan').className = 'iconfont icon-preview1'
  432. },
  433. yuLanMouseLeave () {
  434. document.getElementById('yuLan').className = 'iconfont icon-preview'
  435. },
  436. preview () {
  437. this.preTalbelists = true
  438. this.prewListLoading = true // 打开预览等待
  439. this.preTalbelists = [] // 将原始默认数据清空
  440. for (let i = 0; i < this.imsql.length; i++) {
  441. for (let j = 0; j < this.imsql[i].chosedata.length; j++) {
  442. this.preTalbelists.push({
  443. prop: this.imsql[i].subEquipmentID + '_' + this.imsql[i].chosedata[j],
  444. label: this.imsql[i].subEquipment + '.' + this.imsql[i].chosedataZh[j]
  445. })
  446. }
  447. }
  448. // 获取数据
  449. this.$http({
  450. url: this.$http.adornUrl('/dataset/dynamic/getprecontent'),
  451. method: 'post',
  452. data: this.$http.adornData(this.imsql, false)
  453. }).then(preDatas => {
  454. const Content = preDatas.data.preContent
  455. this.preTableDate = [] // 清空之前是数据
  456. for (var c = 0; c < Content.length; c++) {
  457. this.preTableDate.push(Content[c])
  458. this.prewListLoading = false
  459. }
  460. })
  461. this.showPreview = true
  462. },
  463. riZhiMouseOver () {
  464. document.getElementById('riZhi').className = 'iconfont icon-tishi1'
  465. },
  466. riZhiMouseLeave () {
  467. document.getElementById('riZhi').className = 'iconfont icon-tishi'
  468. },
  469. shourizhi () {
  470. this.showRiZhi = !this.showRiZhi
  471. },
  472. quXiaoMouseOver (id) {
  473. document.getElementById(id).className = 'iconfont icon-quxiao1'
  474. },
  475. quXiaoMouseLeave (id) {
  476. document.getElementById(id).className = 'iconfont icon-quxiao'
  477. },
  478. quXiao (id) {
  479. this.dataListLoading = false
  480. for (let i = 0; i < this.subEquipments.length; i++) {
  481. // 找到对应的设备 删除
  482. if (id === this.subEquipments[i].id) {
  483. this.$refs.tree.getNode(this.subEquipments[i].sql.subEquipmentID).data.icon = 'iconfont icon-xitong3'
  484. this.$refs.tree.getNode(this.subEquipments[i].sql.subEquipmentID).data.limit = 'children'
  485. // 看当前左侧属性栏显示的数据 ,是否为该设备 ,如果是,进行清除
  486. if (this.detailTitle.worldName === this.subEquipments[i].imageTable.tableName) {
  487. this.detailTitle.worldName = '属性信息'
  488. this.tablelists = []
  489. this.tableData = []
  490. }
  491. // 删除对应的测量点ID
  492. this.subEquipments[i].filedList.forEach((info) => {
  493. var number = this.measurepoint.indexOf(info)
  494. if (number === -1) {
  495. this.measurepoint.splice(number, 1)
  496. }
  497. })
  498. // 删除
  499. this.subEquipments.splice(i, 1)
  500. }
  501. }
  502. for (let j = 0; j < this.imsql.length; j++) {
  503. if (id === this.imsql[j].id) {
  504. this.imsql.splice(j, 1)
  505. }
  506. }
  507. },
  508. allowdrag (node) {
  509. if (node.data.limit === 'children') { return true }
  510. },
  511. allowDrop () {
  512. return false // 设置树节点内不可拖拽
  513. },
  514. dragDragOver (e) {
  515. this.dragFlg = 1
  516. e.preventDefault()
  517. },
  518. dragDragLeave (e) {
  519. this.dragFlg = 0
  520. },
  521. treeNodeDragEnd (node) {
  522. if (this.dragFlg === 1 && node.data.limit === 'children') {
  523. // 修改属性值,表示该节点已经拖拽过
  524. node.data.limit = 'children-1'
  525. node.data.icon = 'iconfont icon-xitong4'
  526. // this.$set(node.data, 'icon', 'iconfont icon-xitong4')
  527. const subEquipment = {
  528. id: this.subEquipmentId,
  529. table: false, // 子设备图标显隐显隐
  530. nodeId: node.id,
  531. quXiao: false, // 子设备上方取消图标的显隐
  532. indexContent: '', // 图片上方的内容
  533. selectList: [], // 数据库中子设备字段名
  534. sureSelectList: [], // 选择的子设备字段名
  535. filedList: [], // 数据库的字段名
  536. icon: 'icon iconfont icon-xitong1', // 图标
  537. sql: {
  538. id: '', // 记录对应的节点id
  539. coal: '', // 所属煤矿
  540. system: '', // 所属系统
  541. subsystem: '', // 所属子系统
  542. equipment: '', // 所属设备
  543. subEquipment: '', // 子设备名称
  544. subEquipmentID: '', // 子设备名称id
  545. hbaseTableName: '', // 子设备对应的数据存放地址
  546. userID: this.userID, // 执行操作的用户id
  547. chosedata: []// 选择子设备的字段
  548. },
  549. imageTable: {
  550. tableName: '',
  551. tableDB: ''
  552. }
  553. }
  554. subEquipment.imageTable.tableName = node.data.name
  555. subEquipment.imageTable.tableDB = node.parent.data.name
  556. subEquipment.sql.hbaseTableName = node.data.hbaseTableName
  557. subEquipment.sql.subEquipmentID = node.data.subEquipmentid
  558. // 获取hbase 表头信息
  559. this.$http({
  560. url: this.$http.adornUrl('/dataset/dynamic/getheads'),
  561. method: 'post',
  562. data: this.$http.adornData(subEquipment.sql, false)
  563. }).then(tablists => {
  564. var headers = tablists.data.hbaseTableHeaders
  565. if (headers) {
  566. for (let i = 0; i < headers.length; i++) {
  567. var list = {
  568. key: i,
  569. measurepointId: headers[i].measurepointId,
  570. prop: headers[i].name_en,
  571. label: headers[i].name_zh
  572. }
  573. subEquipment.filedList.push(list)
  574. }
  575. }
  576. })
  577. //
  578. // // 拖拽结束后,如果属性区域没显示数据,自动显示拖拽的设备
  579. // if (this.tablelists.length === 0) {
  580. // this.detailTitle.worldName = node.data.name
  581. // this.tablelists = subEquipment.filedList
  582. // }
  583. this.subEquipments.push(subEquipment)
  584. this.subEquipmentId = this.subEquipmentId + 1
  585. for (let i = 0; i < this.subEquipments.length; i++) {
  586. if (node.id === this.subEquipments[i].nodeId) {
  587. this.subEquipments[i].table = true
  588. this.subEquipments[i].indexContent = this.subEquipments[i].imageTable.tableDB + '.' + this.subEquipments[i].imageTable.tableName
  589. this.subEquipments[i].quXiao = false
  590. }
  591. }
  592. this.dragFlg = 0
  593. }
  594. },
  595. treeNodeClick (data, node) {
  596. if (node.data.limit === 'children') {
  597. this.detailTitle.worldName = node.data.name
  598. this.equimentClick()
  599. }
  600. },
  601. handleClick (id) {
  602. clearTimeout(this.clicktime) // 首先清除计时器
  603. this.clicktime = setTimeout(() => {
  604. // 这里执行你自己的方法或者业务逻辑
  605. this.equimentClick(id)
  606. }, 300)
  607. },
  608. // 双击事件
  609. dblClick (id) {
  610. clearTimeout(this.clicktime) // 清除
  611. // 这里可以添加你自己双击事件的方法或者逻辑
  612. this.equimentDoubleClick(id)
  613. },
  614. equimentClick (id) {
  615. this.dataListLoading = true
  616. for (let i = 0; i < this.subEquipments.length; i++) {
  617. if (id === this.subEquipments[i].id) {
  618. // 处理两次单击同一个设备
  619. if (this.detailTitle.worldName !== this.subEquipments[i].imageTable.tableName) {
  620. this.tablelists = this.subEquipments[i].filedList
  621. this.detailTitle.worldName = this.subEquipments[i].imageTable.tableName
  622. this.tableData = []
  623. // 获取右侧表格数据
  624. this.$http({
  625. url: this.$http.adornUrl('/dataset/dynamic/getContent'),
  626. method: 'post',
  627. data: this.$http.adornData(this.subEquipments[i].sql, false)
  628. }).then(contextResponse => {
  629. if (contextResponse.data.code === 500) {
  630. this.tableData = []
  631. } else {
  632. const subeqpmContent = JSON.parse(JSON.stringify(contextResponse.data.equmentAll))
  633. this.tableData = subeqpmContent
  634. }
  635. this.dataListLoading = false
  636. })
  637. }
  638. this.showInfo = true
  639. break
  640. }
  641. }
  642. if (this.tableData.length > 0) {
  643. this.dataListLoading = false
  644. }
  645. },
  646. equimentDoubleClick (id) {
  647. this.showEqumField = true
  648. for (let i = 0; i < this.subEquipments.length; i++) {
  649. if (id === this.subEquipments[i].id) {
  650. // 构造向后台传输的数据
  651. this.subEquipments[i].sql.id = this.subEquipments[i].id
  652. this.subEquipments[i].sql.equipment = this.subEquipments[i].imageTable.tableDB
  653. this.subEquipments[i].sql.subEquipment = this.subEquipments[i].imageTable.tableName
  654. this.sign = id
  655. this.selectData = [] // 将原始字段置空
  656. this.sureSelect = this.subEquipments[i].sureSelectList
  657. this.selectData = this.subEquipments[i].filedList
  658. // if (this.subEquipments[i].selectList.length === 0) { // 判断是否已有字段数据
  659. // this.axios.post(this.base_url + 'getcolumns', this.subEquipments[i].sql).then(response => {
  660. // for (let j = 0; j < response.data.length; j++) {
  661. // this.selectData.push({
  662. // key: j,
  663. // label: response.data[j].name
  664. // })
  665. // }
  666. // })
  667. // this.subEquipments[i].selectList = this.selectData
  668. // } else {
  669. // this.selectData = this.subEquipments[i].selectList
  670. // }
  671. break
  672. }
  673. }
  674. },
  675. closeEqupField () {
  676. this.showEqumField = false
  677. // 根据选择的ID 找出对应的字段名 存储在sql 中
  678. const chooseFiledEn = []
  679. const chooseFiledZh = []
  680. for (let i = 0; i < this.sureSelect.length; i++) {
  681. const sign = this.sureSelect[i]
  682. chooseFiledEn.push(this.selectData[sign].prop)
  683. chooseFiledZh.push(this.selectData[sign].label)
  684. }
  685. // 保存已经选择的字段
  686. for (let i = 0; i < this.subEquipments.length; i++) {
  687. if (this.sign === this.subEquipments[i].id) {
  688. this.subEquipments[i].sureSelectList = this.sureSelect
  689. this.subEquipments[i].sql.chosedata = chooseFiledEn
  690. this.subEquipments[i].sql.chosedataZh = chooseFiledZh
  691. var imsign = true
  692. for (let j = 0; j < this.imsql.length; j++) {
  693. if (this.imsql[j].id === this.subEquipments[i].sql.id) { // 判断设备数据是否已添加到列表中
  694. this.imsql[j] = this.subEquipments[i].sql // 更新数据
  695. imsign = false
  696. }
  697. }
  698. if (this.subEquipments[i].sureSelectList.length > 0) {
  699. this.subEquipments[i].icon = 'icon iconfont icon-xitong1_1'
  700. } else {
  701. this.subEquipments[i].icon = 'icon iconfont icon-xitong1'
  702. }
  703. if (imsign) {
  704. this.imsql.push(this.subEquipments[i].sql)
  705. }
  706. break
  707. }
  708. }
  709. },
  710. dySubmit (dataInfo) {
  711. if (this.yunXingUid === 0) {
  712. Message.info('请先点击运行')
  713. return
  714. }
  715. this.$refs['dataInfo'].validate((valid) => {
  716. if (!valid) {
  717. return false
  718. } else {
  719. if (typeof this.dataInfo.classificationtag !== 'number') {
  720. for (let clss of this.classification) {
  721. if (clss.categoryName === this.dataInfo.classificationtag) {
  722. this.dataInfo.classificationtag = clss.categoryId
  723. break
  724. }
  725. }
  726. }
  727. var info = {
  728. oldname: this.userID + '_' + this.yunXingUid, // 制作数据集使用的原始名字 便于后台用于将原数据集 重命名
  729. datasetName: this.dataInfo.datasetName, // 数据集名称
  730. extractionPeriod: this.dataInfo.extractionPeriod, // 抽取周期
  731. // extractioNumber: this.dataInfo.extractioNumber, // 抽取次数
  732. remarks: this.dataInfo.remarks,
  733. classification: this.dataInfo.classificationtag,
  734. imsql: this.imsql,
  735. userID: this.userID,
  736. sign: 1
  737. }
  738. MessageBox.confirm(`是否新建动态数据集?`, '提示', {
  739. confirmButtonText: '确定',
  740. cancelButtonText: '取消',
  741. type: 'warning'
  742. }).then(() => {
  743. this.$http({
  744. url: this.$http.adornUrl('/dataset/dynamic/dySubmit'),
  745. method: 'post',
  746. data: this.$http.adornData(info, false)
  747. }).then(res => {
  748. var resContent = res.data
  749. if (resContent && resContent.code === 0) {
  750. Message({
  751. message: '数据集' + this.dataInfo.datasetName + '创建成功',
  752. type: 'success'
  753. })
  754. this.$router.replace({path: '/visi-dataset', query: {'status': '2'}})
  755. this.$destroy()
  756. } else {
  757. Message({
  758. message: '数据集' + this.dataInfo.datasetName + '创建失败',
  759. type: 'error'
  760. })
  761. }
  762. })
  763. }).catch(() => {})
  764. }
  765. })
  766. },
  767. classificationList () {
  768. this.classification = []
  769. this.$http({
  770. url: this.$http.adornUrl('/category/select'),
  771. method: 'get'
  772. }).then(({ data }) => {
  773. var ss = []
  774. for (var i = 0; i < data.list.length; i++) {
  775. ss[i] = data.list[i]
  776. }
  777. this.classification = Array.from(new Set(ss))
  778. })
  779. },
  780. // 获取代码模板
  781. getPythonKafkaTmp () {
  782. this.pythonKafkaVisible = true
  783. this.$nextTick(() => {
  784. this.$refs.pythonKafkaTmp.init(this.measurepoint.join())
  785. })
  786. },
  787. getSubSystem (resolve) {
  788. this.$http({
  789. url: this.$http.adornUrl('/dataset/tree/getsubSystem'),
  790. method: 'post'
  791. }).then(subrespond => {
  792. let subSystemAll = []
  793. let subSystemContent = subrespond.data
  794. if (subSystemContent.length === 0) {
  795. Message.error(subrespond.msg)
  796. } else {
  797. for (let j = 0; j < subSystemContent.length; j++) {
  798. var subSystem = {
  799. name: subSystemContent[j].name,
  800. subSustemid: subSystemContent[j].id,
  801. limit: 'subSystem',
  802. icon: 'iconfont icon-xitongfuwu',
  803. leaf: false
  804. }
  805. subSystemAll.push(subSystem)
  806. }
  807. }
  808. return resolve(subSystemAll)
  809. })
  810. },
  811. getEquipment (subSustemid, resolve) {
  812. const subSystemData = {
  813. subSystemid: subSustemid
  814. }
  815. this.$http({
  816. url: this.$http.adornUrl('/dataset/tree/getequipment'),
  817. method: 'post',
  818. data: this.$http.adornData(subSystemData, false)
  819. }).then(eqprespond => {
  820. let equipmentAll = []
  821. const eqpSystemContent = eqprespond.data
  822. if (eqpSystemContent.length === 0) {
  823. Message.error(eqprespond.msg)
  824. } else {
  825. for (let k = 0; k < eqpSystemContent.length; k++) {
  826. var equipment = {
  827. name: eqpSystemContent[k].name,
  828. equipmentid: eqpSystemContent[k].id,
  829. limit: 'equipment',
  830. hbaseTableName: '',
  831. icon: 'iconfont icon-xitongfuwu',
  832. leaf: false
  833. }
  834. equipmentAll.push(equipment)
  835. }
  836. }
  837. return resolve(equipmentAll)
  838. })
  839. },
  840. getSubEquipment (equipmentid, resolve) {
  841. const equimentData = {
  842. equipment: equipmentid
  843. }
  844. this.$http({
  845. url: this.$http.adornUrl('/dataset/tree/getsubequipment'),
  846. method: 'post',
  847. data: this.$http.adornData(equimentData, false)
  848. }).then(subEqpRespond => {
  849. let subEquimentAll = []
  850. const subEqpSystemContent = subEqpRespond.data
  851. if (subEqpSystemContent.length === 0) {
  852. Message.error(subEqpRespond.msg)
  853. } else {
  854. for (let m = 0; m < subEqpSystemContent.length; m++) {
  855. var subEquiment = {
  856. name: subEqpSystemContent[m].name,
  857. subEquipmentid: subEqpSystemContent[m].id,
  858. hbaseTableName: subEqpSystemContent[m].hbaseTableName,
  859. limit: 'children',
  860. icon: 'iconfont icon-xitong3',
  861. leaf: true
  862. }
  863. subEquimentAll.push(subEquiment)
  864. }
  865. }
  866. return resolve(subEquimentAll)
  867. })
  868. },
  869. // 左侧树的懒加载
  870. loadTreeNode (node, resolve) {
  871. if (node.level === 0) {
  872. this.getSubSystem(resolve)
  873. } else if (node.level === 1) {
  874. this.getEquipment(node.data.subSustemid, resolve)
  875. } else {
  876. this.getSubEquipment(node.data.equipmentid, resolve)
  877. }
  878. }
  879. },
  880. // 生命周期 - 创建完成(可以访问当前this实例)
  881. mounted () {
  882. this.classificationList()
  883. },
  884. // 生命周期 - 挂载完成(可以访问DOM元素)
  885. created () {},
  886. beforeCreate () {}, // 生命周期 - 创建之前
  887. beforeMount () {}, // 生命周期 - 挂载之前
  888. beforeUpdate () {}, // 生命周期 - 更新之前
  889. updated () {}, // 生命周期 - 更新之后
  890. beforeDestroy () {}, // 生命周期 - 销毁之前
  891. destroyed () {}, // 生命周期 - 销毁完成
  892. activated () {} // 如果页面有keep-alive缓存功能,这个函数会触发
  893. }
  894. </script>
  895. <style scoped>
  896. .divi2 {
  897. display: block;
  898. height: 1px;
  899. width: 100%;
  900. position: relative;
  901. }
  902. .divi {
  903. display: block;
  904. height: 1px;
  905. width: 100%;
  906. margin: 24px 0;
  907. background-color: #dcdfe6;
  908. }
  909. .title_score{
  910. margin-top: 30px;
  911. margin-left: 180px;
  912. }
  913. .body {
  914. min-width: 1250px;
  915. height: 800px;
  916. position: relative;
  917. margin: 1px 25px 0px 100px;
  918. }
  919. .allDiv{
  920. width: 100%;
  921. height: 80%;
  922. border-left: 0.2px solid #000;
  923. }
  924. .leftDiv{
  925. width: 20%;
  926. height: 100%;
  927. float: left;
  928. border-bottom:0.2px solid #000;
  929. border-top:0.2px solid #000;
  930. /*//overflow-y: auto;*/
  931. }
  932. .leftDivTree{
  933. width: 100%;
  934. height: 93.7%;
  935. overflow: scroll;
  936. }
  937. .el-tree {
  938. display: inline-block;
  939. min-width: 100%;
  940. }
  941. .custom-tree-node {
  942. flex: 1;
  943. display: flex;
  944. align-items: center;
  945. justify-content: space-between;
  946. font-size: 14px;
  947. padding-right: 8px;
  948. }
  949. .midDiv{
  950. width: 49.5%;
  951. height: 100%;
  952. float: left;
  953. border-top:0.2px solid #000;
  954. border-bottom:0.2px solid #000;
  955. border-left:0.2px solid #000;
  956. overflow-y: scroll;
  957. }
  958. .midDivTop{
  959. height:6.3%;
  960. width: 100%;
  961. }
  962. .midDivTopImg{
  963. /*padding-top: 5px;*/
  964. }
  965. .midDivData{
  966. width: 100%;
  967. height: 93.7%;
  968. margin-top: -10px;
  969. background: url("../../../assets/datasetImg/background.png");
  970. }
  971. .datasourceDiv {
  972. width: 100%;
  973. height: 100%;
  974. }
  975. .datasourceDiv .el-divider--horizontal
  976. {
  977. margin: 0;
  978. }
  979. .rizhiDiv{
  980. width: 49.3%;
  981. height:15%;
  982. position: absolute;
  983. margin-top: -8.8%;
  984. margin-left: 2px;
  985. /*overflow:auto*/
  986. /*bottom: 12.6px;*/
  987. }
  988. .rizhiDivtext{
  989. width: 100%;
  990. height: 75.5%;
  991. font-size: 1px;
  992. /*border: 0.2px solid #000;*/
  993. overflow: auto;
  994. margin-top: 10px;
  995. /*background: #ffff;*/
  996. white-space: pre-wrap;
  997. }
  998. .rightDiv{
  999. width: 30%;
  1000. height: 100%;
  1001. float: left;
  1002. overflow: auto;
  1003. border:0.5px solid #000;
  1004. }
  1005. .icon {
  1006. width: 1em; height: 1em;
  1007. vertical-align: -0.15em;
  1008. fill: currentColor;
  1009. overflow: hidden;
  1010. }
  1011. .el-tree.iconfont{
  1012. margin-right: 100px;
  1013. }
  1014. </style>