scdTree.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. <template>
  2. <div>
  3. <div class="btnBox">
  4. <div @click="checkNow">
  5. <img :src="addPng" alt="" />
  6. <span>新的比对</span>
  7. </div>
  8. <div @click="reloadCheck">
  9. <img :src="againPng" alt="" />
  10. <span>重新比对</span>
  11. </div>
  12. <div @click="excelPort">
  13. <img :src="dervicePng" alt="" />
  14. <span>导出所有结果</span>
  15. </div>
  16. </div>
  17. <div class="tableBox">
  18. <el-table
  19. ref="multipleTable"
  20. :data="tableList"
  21. style="width: 100%; height: calc(100vh - 320px)"
  22. stripe
  23. @select="select"
  24. :header-cell-style="{
  25. background: '#F7F8FB !important',
  26. color: '#7484AB',
  27. borderBottom: '1px solid #A3ADE0 !important',
  28. fontWeight: '400',
  29. }"
  30. >
  31. <el-table-column width="55" type="selection" />
  32. <el-table-column
  33. label="对比scd"
  34. width="190"
  35. :show-overflow-tooltip="true"
  36. >
  37. <template #default="scope">{{ scope.row.name }}</template>
  38. </el-table-column>
  39. <el-table-column
  40. property="CREATED_TIME"
  41. label="时间"
  42. width="auto"
  43. :show-overflow-tooltip="true"
  44. />
  45. <el-table-column fixed="right" label="操作" width="120">
  46. <template #default="scope">
  47. <el-button
  48. link
  49. type="primary"
  50. size="small"
  51. @click="searchScdCheck(scope.row)"
  52. ><el-icon> <View /> </el-icon>查看</el-button
  53. >
  54. </template>
  55. </el-table-column>
  56. </el-table>
  57. </div>
  58. <!-- <div>新的对比
  59. <LookScd
  60. v-if="lookScdModal"
  61. :lookScdModal="lookScdModal"
  62. :aktType="aktType"
  63. @lookScdBack="lookScdBack"
  64. >
  65. </LookScd>
  66. </div> -->
  67. <!-- 新的对比弹窗 -->
  68. <el-dialog
  69. @close="cancelClick"
  70. v-model="lookScdModal"
  71. width="30vw"
  72. style="height: 400px"
  73. append-to-body
  74. draggable
  75. >
  76. <template #header>
  77. <div class="my-header">
  78. <div class="title">请选择对比的SCD文件</div>
  79. </div>
  80. </template>
  81. <div
  82. class="uploda-file"
  83. v-loading="loadingAdd"
  84. element-loading-text="上传文件中..."
  85. >
  86. <span class="file-title">选择文件</span>
  87. <el-input
  88. v-model="chooseFile"
  89. class="w-50 m-2"
  90. placeholder="点击右侧按钮上传文件"
  91. clearable
  92. @clear="clearFile"
  93. >
  94. <template #suffix>
  95. <img
  96. v-if="chooseFile"
  97. :src="uploadSPng"
  98. alt=""
  99. style="width: 20px; height: 20px"
  100. />
  101. <img
  102. v-if="loadingAddError"
  103. :src="uploadEPng"
  104. alt=""
  105. style="width: 20px; height: 20px"
  106. />
  107. </template>
  108. </el-input>
  109. <el-upload
  110. v-model:file-list="fileList"
  111. :limit="1"
  112. class="upload-demo"
  113. :http-request="uploadFile"
  114. :on-exceed="exceed"
  115. :show-file-list="false"
  116. >
  117. <template #trigger>
  118. <div class="upload-title">
  119. <img :src="uploadPng" alt="" />
  120. <span>上传文件</span>
  121. </div>
  122. </template>
  123. </el-upload>
  124. </div>
  125. <div class="sure-file">
  126. <div v-if="!isAnalysis && AnalysisProcess" class="analysis success">
  127. 文件解析完成
  128. </div>
  129. <div v-else-if="isAnalysis && AnalysisProcess" class="analysis fail">
  130. 文件解析失败
  131. </div>
  132. <div v-if="chooseFile && !AnalysisProcess" class="analysis">
  133. 文件正在解析中,请等待...
  134. </div>
  135. <!-- <div
  136. class="sures"
  137. :class="{ 'sures-success': !isAnalysis && AnalysisProcess }"
  138. >
  139. 确认上传
  140. </div> -->
  141. <div
  142. class="sures sures-success"
  143. v-if="!isAnalysis && AnalysisProcess"
  144. @click="yesAnalysisClick"
  145. >
  146. 开始对比
  147. </div>
  148. <div class="sures" v-else @click="noAnalysisClick">开始对比</div>
  149. </div>
  150. </el-dialog>
  151. <!-- 导出所有结果 -->
  152. <el-dialog
  153. v-model="exportModal"
  154. width="25vw"
  155. style="height: 200px"
  156. append-to-body
  157. draggable
  158. >
  159. <template #header>
  160. <div class="my-header">
  161. <div class="title">数据导出</div>
  162. </div>
  163. </template>
  164. <div v-if="!exportLink" class="export-ink">正在导出数据中...</div>
  165. <div v-else class="export-ink">
  166. 数据文件已生成完成,
  167. <el-link :href="exportLink" type="primary" class="load">点击立即下载</el-link>
  168. </div>
  169. </el-dialog>
  170. </div>
  171. </template>
  172. <script setup>
  173. import {
  174. ref,
  175. onMounted,
  176. toRefs,
  177. watch,
  178. nextTick,
  179. defineEmits,
  180. onUnmounted,
  181. } from "vue";
  182. import scdCheck from "@/api/scdCheck/scdCheck";
  183. import {
  184. uploadfile,
  185. tmpParse,
  186. compStart,
  187. compstatView,
  188. scdExpTableData,
  189. } from "@/api/scdCheck/scdCheck2";
  190. import scd from "@/api/scd";
  191. import systemRow from "@/api/systemRow";
  192. import {
  193. ElMessage,
  194. ElLoading,
  195. ElMessageBox,
  196. ElNotification,
  197. } from "element-plus";
  198. import LookScd from "../modalCom/LookScd.vue";
  199. import dervicePng from "@/assets/image/scdcheck/derive.png";
  200. import againPng from "@/assets/image/scdcheck/again.png";
  201. import addPng from "@/assets/image/scdcheck/add.png";
  202. import uploadPng from "@/assets/image/scdcheck/upload.png";
  203. import uploadSPng from "@/assets/image/scdcheck/upload_success.png";
  204. import uploadEPng from "@/assets/image/scdcheck/upload_error.png";
  205. import { useRoute } from "vue-router";
  206. import createds from "@/utils/scdMqtt.js";
  207. const route = useRoute();
  208. const emit = defineEmits(["scdTreeBack", "scdView", "scdJpadList"]);
  209. let tableList = ref([]);
  210. let multipleTable = ref();
  211. let alreadyTriggered = ref(false);
  212. let scdid = ref([]);
  213. const loading = ref(false);
  214. let lookScdArr = ref([]);
  215. let lookScdModal = ref(false);
  216. const fileList = ref([]); //上传的文件
  217. const loadingAdd = ref(false); //文件上传的加载状态
  218. const loadingAddError = ref(false); //文件上传的加载状态
  219. const chooseFile = ref("");
  220. const chooseContrast = ref(null);
  221. const checkNow = (e) => {
  222. //scd比对
  223. results();
  224. };
  225. const results = () => {
  226. lookScdModal.value = true;
  227. contrast.value = false;
  228. chooseContrast.value = null;
  229. AnalysisProcess.value = false;
  230. isAnalysis.value = false;
  231. chooseFile.value = "";
  232. exportLink.value = "";
  233. };
  234. const exportModal = ref(false);
  235. const exportLink = ref("");
  236. const excelPort = () => {
  237. exportLink.value = "";
  238. if (!chooseContrast.value) {
  239. return ElMessage({
  240. type: "warning",
  241. message: "请选择一条历史校验记录或创建新一致性校验!",
  242. });
  243. }
  244. exportModal.value = true;
  245. //导出excel
  246. scdExpTableData({
  247. code: "scd-comp-result",
  248. caption: "SCD一致性对比结果",
  249. expcols:
  250. "source_scd_name,target_scd_name,ied_name,ied_desc,opt,diff_object_type,diff_object_name,desc",
  251. expcolnames:
  252. "基准SCD,目标比对SCD,装置名称,装置描述,操作,比对内容类型,差异项,差异内容",
  253. comp_id: chooseContrast.value.id,
  254. }).then((res) => {
  255. if (res.data) {
  256. exportLink.value = window.ApiServer + '/' + res.data;
  257. } else {
  258. ElMessage({
  259. message: res.msg,
  260. type: "info",
  261. });
  262. }
  263. });
  264. };
  265. const contrast = ref(false); //是否是重新对比
  266. const reloadCheck = async () => {
  267. contrast.value = true;
  268. mesg.value = null;
  269. //重新比对
  270. if (!chooseContrast.value) {
  271. ElMessage({
  272. type: "warning",
  273. message: "请选择一条历史校验记录或创建新一致性校验!",
  274. });
  275. } else {
  276. yesAnalysisClick();
  277. }
  278. };
  279. const exceed = (files) => {
  280. if (fileList.value.length > 0) {
  281. ElMessage({
  282. type: "warning",
  283. message: "请清除选择文件后重新选择!",
  284. });
  285. }
  286. };
  287. const uploadFile = async (e) => {
  288. fileList.value = [];
  289. chooseFile.value = "";
  290. loadingAddError.value = false;
  291. loadingAdd.value = true;
  292. const fileRes = await uploadfile({
  293. file: e.file,
  294. station_id: route.query.stationId,
  295. is_checkin: 0,
  296. data_type: "a_scd",
  297. });
  298. if (fileRes.code == 0) {
  299. fileList.value.push(fileRes.data);
  300. chooseFile.value = fileRes.data.filename;
  301. loadingAdd.value = false;
  302. ElMessage({
  303. type: "success",
  304. message: "上传成功!",
  305. });
  306. const resParse = await tmpParse({
  307. station_id: route.query.stationId,
  308. scd_name: fileRes.data.filename,
  309. scd_path: fileRes.data.path,
  310. });
  311. startMqtt(`/jujutong/scd_check_tools/parse/#`);
  312. } else {
  313. loadingAdd.value = false;
  314. loadingAddError.value = true;
  315. ElMessage({
  316. type: "error",
  317. message: "上传失败!",
  318. });
  319. }
  320. };
  321. //查看scd对比
  322. let data = {};
  323. const searchScdCheck = async (row) => {
  324. data = {};
  325. data = row;
  326. emit("scdView", data);
  327. const loading = ElLoading.service({
  328. lock: true,
  329. text: "正在查询数据",
  330. background: "rgba(0, 0, 0, 0.7)",
  331. });
  332. const res = await compstatView({
  333. comp_id: row.id,
  334. });
  335. if (res.code == 0) {
  336. emit("scdJpadList", res.data);
  337. loading.close();
  338. }
  339. };
  340. const lookScdBack = (data, row) => {
  341. //选择scd文件模态框返回数据
  342. lookScdModal.value = data;
  343. lookScdArr.value = row;
  344. emit("scdTreeBack", lookScdArr.value);
  345. };
  346. const aktType = () => {
  347. //初始化数据
  348. scdCheck
  349. .flashStationDui({ station_id: route.query.stationId })
  350. .then((res) => {
  351. //获取差异纪录列表
  352. tableList.value = res.data;
  353. });
  354. };
  355. // mqtt=======
  356. const PublicMqtt = ref(null);
  357. const mesg = ref(null); //订阅成功的消息
  358. const isAnalysis = ref(false); //解析是否成功
  359. const AnalysisProcess = ref(false); //解析是否完成
  360. const startMqtt = (val) => {
  361. //val = 订阅地址
  362. //设置订阅地址checkNo
  363. PublicMqtt.value = new createds(val);
  364. //初始化mqtt
  365. PublicMqtt.value.init();
  366. //链接mqtt
  367. PublicMqtt.value.link();
  368. getMessage();
  369. };
  370. //获取订阅数据
  371. const getMessage = () => {
  372. PublicMqtt.value.client.on("message", (topic, message) => {
  373. // topic包含error就表示解析错误,message此时就是错误信息
  374. AnalysisProcess.value = true;
  375. mesg.value = JSON.parse(message.toString());
  376. if (topic.includes("error")) {
  377. isAnalysis.value = true;
  378. ElMessage({
  379. type: "error",
  380. message: mesg.value,
  381. });
  382. } else {
  383. isAnalysis.value = false;
  384. contrast.value = false;
  385. }
  386. console.log(mesg.value, "返回的数据", topic);
  387. });
  388. };
  389. //取消MQTT订阅
  390. const unsubscribe = () => {
  391. //如果页面并没有初始化MQTT,无需取消订阅
  392. if (PublicMqtt.value) {
  393. PublicMqtt.unsubscribes();
  394. }
  395. };
  396. onUnmounted(() => {
  397. //页面销毁结束订阅
  398. if (PublicMqtt.value) {
  399. PublicMqtt.value.unsubscribes();
  400. PublicMqtt.value.over();
  401. }
  402. });
  403. // mqtt=======
  404. // 取消弹窗
  405. const cancelClick = () => {
  406. loadingAddError.value = false;
  407. loadingAdd.value = false;
  408. };
  409. //点击输入框中的清除按钮
  410. const clearFile = () => {
  411. fileList.value = [];
  412. };
  413. watch(
  414. () => chooseFile.value,
  415. (newValue) => {
  416. if (!newValue) {
  417. fileList.value = [];
  418. }
  419. }
  420. );
  421. const referenceData = ref(null);
  422. //解析完成开始对比的点击
  423. const yesAnalysisClick = () => {
  424. ElMessageBox.confirm(
  425. "该操作耗时较长,校验开始后将清除原有校验结果且无法中止,确定开始吗?",
  426. "Warning",
  427. {
  428. confirmButtonText: "确定",
  429. cancelButtonText: "取消",
  430. type: "warning",
  431. }
  432. )
  433. .then(async () => {
  434. ElNotification({
  435. title: "信息",
  436. message: "正在进行SCD的一致性比对...请稍候",
  437. duration: 0,
  438. });
  439. let anRes;
  440. if (mesg.value && !contrast.value) {
  441. anRes = await compStart({
  442. type: "SCD",
  443. station_id: route.query.stationId,
  444. source_scd_id: route.query.id,
  445. target_scd_id: mesg.value.rootid,
  446. comp_id: 0,
  447. });
  448. } else if (chooseContrast.value) {
  449. anRes = await compStart({
  450. type: "SCD",
  451. station_id: route.query.stationId,
  452. source_scd_id: chooseContrast.value.source_id,
  453. target_scd_id: chooseContrast.value.target_id,
  454. comp_id: chooseContrast.value.id,
  455. });
  456. }
  457. if (anRes.code == 0) {
  458. loadingAdd.value = false;
  459. aktType();
  460. ElMessage({
  461. type: "success",
  462. message: "对比完成!",
  463. });
  464. ElNotification.closeAll();
  465. lookScdModal.value = false;
  466. } else {
  467. ElMessage({
  468. type: "error",
  469. message: err.msg,
  470. });
  471. }
  472. })
  473. .catch((err) => {});
  474. };
  475. //解析失败或未完成开始对比的点击
  476. const noAnalysisClick = () => {
  477. ElMessage({
  478. type: "warning",
  479. message: "请上传文件并等待文件解析完成!",
  480. });
  481. };
  482. const parentData = ref(null);
  483. const isDelete = ref(true);
  484. // 表格单选操作
  485. const select = (selection, row) => {
  486. multipleTable.value.clearSelection();
  487. // 主要用于将当前勾选的表格状态清除;
  488. // 当表格数据都没有被勾选的时候就返回;
  489. if (selection.length == 0) {
  490. isDelete.value = true;
  491. return;
  492. }
  493. chooseContrast.value = row;
  494. multipleTable.value.toggleRowSelection(row, true);
  495. isDelete.value = false;
  496. };
  497. onMounted(async () => {
  498. parentData.value = JSON.parse(route.query.parentData);
  499. aktType();
  500. });
  501. </script>
  502. <style scoped lang="scss">
  503. .btnBox > div,
  504. .upload-title {
  505. height: 50px;
  506. display: flex;
  507. align-items: center;
  508. justify-content: center;
  509. margin-right: 8px;
  510. cursor: pointer;
  511. background: url("~@/assets/image/scdcheck/bgscd.png") no-repeat center;
  512. border-radius: 2px;
  513. font-size: 14px;
  514. color: #255ce7;
  515. img {
  516. width: 20px;
  517. height: 20px;
  518. margin: 0 4px 0 0;
  519. }
  520. }
  521. .upload-title {
  522. width: 102px;
  523. background-size: 103px 50px;
  524. margin-top: 4px;
  525. }
  526. .btnBox {
  527. display: flex;
  528. margin-bottom: 12px;
  529. & > div:first-child,
  530. & > div:nth-child(2) {
  531. width: 102px;
  532. background-size: 102px 45px;
  533. }
  534. & > div:last-child {
  535. width: 128px;
  536. background-size: 128px 45px;
  537. }
  538. }
  539. .my-header {
  540. border-bottom: 1px solid #a3ade0;
  541. font-size: 16px;
  542. color: #1a2447;
  543. .title {
  544. padding-bottom: 15px;
  545. }
  546. }
  547. .uploda-file {
  548. display: flex;
  549. align-items: center;
  550. }
  551. .upload-demo {
  552. display: flex;
  553. }
  554. .sure-file {
  555. display: flex;
  556. flex-direction: column;
  557. justify-content: center;
  558. align-items: center;
  559. }
  560. .sures {
  561. background: #dfe8ff;
  562. margin-left: 60px;
  563. color: #fff;
  564. width: 124px;
  565. height: 32px;
  566. margin-top: 60px;
  567. line-height: 32px;
  568. text-align: center;
  569. cursor: pointer;
  570. }
  571. .sures-success {
  572. background: #255ce7;
  573. }
  574. .export-ink {
  575. display: flex;
  576. text-align: center;
  577. justify-content: center;
  578. .load{
  579. margin-left: 10px;
  580. border-bottom: 1px solid #409eff;
  581. }
  582. }
  583. .file-title {
  584. width: 90px;
  585. color: #1a2447;
  586. font-size: 14px;
  587. margin-right: 8px;
  588. }
  589. :deep(.el-input__wrapper) {
  590. height: 38px;
  591. border: 1px solid #a3ade0;
  592. }
  593. .analysis {
  594. margin-left: 67px;
  595. margin-top: 10px;
  596. color: #255ce7;
  597. }
  598. .analysis.success {
  599. color: #3be078;
  600. }
  601. .analysis.fail {
  602. color: #e50505;
  603. }
  604. :deep(.el-message-box) {
  605. vertical-align: inherit !important;
  606. } // 取消多选第一列的展示(即:将多选变成单选的第一步); 取消该样式后,就不会出现多选的情况;但由此可知还有其他的方法来实现单选;
  607. ::v-deep(.el-table th.el-table__cell:nth-child(1) .cell) {
  608. visibility: hidden;
  609. }
  610. </style>