Просмотр исходного кода

Merge branch 'master' of http://94.191.59.107:3000/houwenfeng/scd_tools_ui into liling

liling 1 год назад
Родитель
Сommit
a1b926938c

+ 157 - 1
package-lock.json

@@ -32,7 +32,8 @@
         "uuid": "^9.0.1",
         "vue": "^3.2.13",
         "vue-draggable-next": "^2.2.1",
-        "vue-router": "^4.2.5"
+        "vue-router": "^4.2.5",
+        "xlsx": "^0.18.5"
       },
       "devDependencies": {
         "@babel/core": "^7.12.16",
@@ -3160,6 +3161,14 @@
         "node": ">= 10.0.0"
       }
     },
+    "node_modules/adler-32": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
+      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/agent-base": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -3962,6 +3971,18 @@
         "node": ">=4"
       }
     },
+    "node_modules/cfb": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
+      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+      "dependencies": {
+        "adler-32": "~1.3.0",
+        "crc-32": "~1.2.0"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
@@ -4274,6 +4295,14 @@
         "node": ">= 0.12.0"
       }
     },
+    "node_modules/codepage": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
+      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/collect-v8-coverage": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
@@ -4579,6 +4608,17 @@
         "node": ">=10"
       }
     },
+    "node_modules/crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+      "bin": {
+        "crc32": "bin/crc32.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -6240,6 +6280,14 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/fraction.js": {
       "version": "4.3.6",
       "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.6.tgz",
@@ -13241,6 +13289,17 @@
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
       "license": "BSD-3-Clause"
     },
+    "node_modules/ssf": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
+      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+      "dependencies": {
+        "frac": "~1.1.2"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/ssri": {
       "version": "8.0.1",
       "resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz",
@@ -14715,6 +14774,22 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/wmf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
+      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/word": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
+      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/worker-timers": {
       "version": "7.1.0",
       "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.0.tgz",
@@ -14835,6 +14910,26 @@
         }
       }
     },
+    "node_modules/xlsx": {
+      "version": "0.18.5",
+      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
+      "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+      "dependencies": {
+        "adler-32": "~1.3.0",
+        "cfb": "~1.2.1",
+        "codepage": "~1.15.0",
+        "crc-32": "~1.2.1",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      },
+      "bin": {
+        "xlsx": "bin/xlsx.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
     "node_modules/xml-name-validator": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
@@ -17250,6 +17345,11 @@
       "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==",
       "dev": true
     },
+    "adler-32": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
+      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
+    },
     "agent-base": {
       "version": "6.0.2",
       "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -17775,6 +17875,15 @@
       "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==",
       "dev": true
     },
+    "cfb": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
+      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+      "requires": {
+        "adler-32": "~1.3.0",
+        "crc-32": "~1.2.0"
+      }
+    },
     "chalk": {
       "version": "2.4.2",
       "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
@@ -17978,6 +18087,11 @@
       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
       "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ=="
     },
+    "codepage": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
+      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
+    },
     "collect-v8-coverage": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
@@ -18206,6 +18320,11 @@
         "yaml": "^1.10.0"
       }
     },
+    "crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
+    },
     "cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz",
@@ -19360,6 +19479,11 @@
       "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
       "dev": true
     },
+    "frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
+    },
     "fraction.js": {
       "version": "4.3.6",
       "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.6.tgz",
@@ -24060,6 +24184,14 @@
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
       "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
     },
+    "ssf": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
+      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+      "requires": {
+        "frac": "~1.1.2"
+      }
+    },
     "ssri": {
       "version": "8.0.1",
       "resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz",
@@ -25057,6 +25189,16 @@
       "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
       "dev": true
     },
+    "wmf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
+      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
+    },
+    "word": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
+      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
+    },
     "worker-timers": {
       "version": "7.1.0",
       "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.0.tgz",
@@ -25143,6 +25285,20 @@
       "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
       "requires": {}
     },
+    "xlsx": {
+      "version": "0.18.5",
+      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
+      "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+      "requires": {
+        "adler-32": "~1.3.0",
+        "cfb": "~1.2.1",
+        "codepage": "~1.15.0",
+        "crc-32": "~1.2.1",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      }
+    },
     "xml-name-validator": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",

+ 2 - 1
package.json

@@ -32,7 +32,8 @@
     "uuid": "^9.0.1",
     "vue": "^3.2.13",
     "vue-draggable-next": "^2.2.1",
-    "vue-router": "^4.2.5"
+    "vue-router": "^4.2.5",
+    "xlsx": "^0.18.5"
   },
   "devDependencies": {
     "@babel/core": "^7.12.16",

+ 16 - 1
src/api/iedNetwork/index.js

@@ -180,6 +180,21 @@ export function getiedInputs(query) {
     params: query
   })
 }
-
+//虚端子关系表格表间隔
+export function checkArea(query) {
+  return request({
+    url: '/admin/get/check_area',
+    method: 'get',
+    params: query
+  })
+}
+//虚端子关系表格列表
+export function fcdaList(query) {
+  return request({
+    url: '/admin/scd/fcda/list',
+    method: 'get',
+    params: query
+  })
+}
 
 

+ 19 - 5
src/pages/mission/components/HistoryMis.vue

@@ -30,6 +30,12 @@
                     </template>
                 </el-table-column>
                 <el-table-column prop="ct" label="创建时间" width="200" />
+                <el-table-column prop="start_time" label="开始检测时间" sortable width="200">
+                    <template #default="scoped">
+                        <span>{{ scoped.row.start_time == '1970-01-01 00:00:00' ? '暂无检测时间' : scoped.row.start_time
+                            }}</span>
+                    </template>
+                </el-table-column>
                 <el-table-column prop="scd_name" label="SCD名称" width="auto" />
                 <el-table-column prop="station_name" label="变电站" width="120" />
                 <el-table-column prop="username" label="创建人" width="120" />
@@ -38,14 +44,22 @@
                     <template #default="scoped">
                         <!-- <el-popconfirm title="你确定删除吗?" @confirm="sureDelMis">
                             <template #reference> -->
-                        <el-button v-if="scoped.row.state=='2'||scoped.row.state=='3'" link type="primary" size="small" @click="relady(scoped.row)">重新检测</el-button>
-                        <el-button v-if="scoped.row.state!='1'" link type="danger" size="small" @click="delMis(scoped.row)">删除</el-button>
+                        <el-button v-if="scoped.row.state == '2' || scoped.row.state == '3'" link type="primary" size="small"
+                            @click="relady(scoped.row)">重新检测</el-button>
+                        <el-button v-if="scoped.row.state != '1'" link type="danger" size="small"
+                            @click="delMis(scoped.row)">删除</el-button>
+                        <!-- <el-button v-if="scoped.row.state == '2'" link type="primary" size="small"
+                            @click="relady(scoped.row)">重新检测</el-button>
+                        <el-button v-if="scoped.row.state != '1'" link type="danger" size="small"
+                            @click="delMis(scoped.row)">删除</el-button> -->
                         <!-- </template>
-                        </el-popconfirm> -->
+    </el-popconfirm> -->
                     </template>
                 </el-table-column>
             </el-table>
-            <PageNation :totals="totals" :pageNum="pageNum" :pageSize="pageSize" @pageBack="pageBack" @currentBack="currentBack"></PageNation>
+            <PageNation :totals="totals" :pageNum="pageNum" :pageSize="pageSize" @pageBack="pageBack"
+                @currentBack="currentBack">
+            </PageNation>
         </div>
         <DelHistory v-if="delModal" :delModal="delModal" :delId="delId" :reload="reload" @delBack="delBack">
         </DelHistory>
@@ -157,7 +171,7 @@ export default {
         function delBack(data) {
             delModal.value = data
         }
-        function currentBack(data){
+        function currentBack(data) {
             pageNum.value = data
         }
         onMounted(() => {

+ 12 - 1
src/pages/netStructPicture/components/CidTree.vue

@@ -53,7 +53,7 @@
               node.label
             }}</span
             ><span
-              :class="{ 'tree-label': clickItemcode == data.itemcode }"
+              :class="{ 'tree-label': clickItemcode == data.itemcode&&!node.expanded}"
               style="position: absolute; right: 10px"
               ><span v-if="OpensclTrue">{{ data.num }}</span
               ><span v-else>{{ data.num }}</span></span
@@ -357,6 +357,7 @@ watch(
     if (newValue == false) {
       results();
       //关闭展开的节点
+      clickItemcode.value = "";
       const nodes = trees.value.store._getAllNodes();
       nodes.forEach((item) => {
         item.expanded = false;
@@ -555,6 +556,7 @@ h3 {
   }
   :deep(
       .el-tree--highlight-current
+      .el-tree-node__children
         .el-tree-node.is-current
         > .el-tree-node__content
         .label
@@ -563,6 +565,15 @@ h3 {
     border: 1px solid #255ce7;
     background: #f6f9ff;
   }
+  :deep(
+      .el-tree--highlight-current
+        .el-tree-node.is-expanded
+        > .el-tree-node__content
+        .label
+    ) {
+    color: #134bea;
+    background: #f6f9ff;
+  }
 }
 .titles {
   display: flex;

+ 3 - 2
src/pages/netStructPicture/components/Gsix.vue

@@ -47,7 +47,7 @@ const props = defineProps({
 });
 
 const clickRow = ref(props.clickRowDatas);
-let tagList = ref(props.iedRelation?Object.values(props.iedRelation)[0]:''); //左侧更改的设备列表
+let tagList = ref(props.clickList?props.clickList:''); //左侧更改的设备列表
 
 //CID数据,点击差异的每一条数据
 const CodeInfoCid = ref(props.clickCodeInfoCid);
@@ -180,6 +180,7 @@ const getData = async () => {
   if (res.data && cClickCode.value != "scd.ied") {
     res.data.forEach((item) => {
       let text;
+      if(!item.diff_desc) return;
       text = item.diff_desc.replace(/[\r|\n|\t]/g, ""); //处理返回的数据中换行等,整理好规整数据
       item.diff_desc = JSON.parse(text);
       commonGetData(item);
@@ -1479,7 +1480,7 @@ onMounted(() => {
       height: 20px;
       position: absolute;
       top: 24px;
-      right: 21px;
+      right: 15px;
     }
   }
 }

+ 1 - 3
src/pages/netStructPicture/components/SclUpdate.vue

@@ -76,16 +76,14 @@ const cancelClick = () => {
 const clickList = ref(null);
 const treeBack = (data, val) => {
   clickList.value = data;
-  console.log('data11111111111', data)
 };
 const treeBackDefalut = (data) => {
   // clickList.value = data;
 };
 //点击差异项的code
 const clickCodeValue = ref(null);
-const clickCode = (code) => {
+const clickCode = (code,data) => {
   clickCodeValue.value = code;
-  console.log('clickCodeValue.value', clickCodeValue.value)
 };
 const result = (newData) => {
   checkData.value = newData;

+ 271 - 0
src/pages/netStructPicture/components/VirtualTable.vue

@@ -0,0 +1,271 @@
+<!-- 虚端子关系表 -->
+<template>
+  <div class="bigBox">
+    <div class="header">
+      <div v-if="needFlashName">
+        {{ needFlashName + " — " + needScdName + " — 虚端子关系表" }}
+      </div>
+      <div v-else>虚端子关系表</div>
+      <span class="closeX" @click="closeX">×</span>
+    </div>
+    <div class="antherHeader">
+      <el-form
+        :model="queryParams"
+        ref="queryRef"
+        :inline="true"
+        label-width="68px"
+      >
+        <el-form-item label="间隔" prop="area_id">
+          <el-select
+            ref="levelRef"
+            v-model="queryParams.area_id"
+            placeholder="请选择间隔"
+            multiple
+            collapse-tags
+            @change="changeLevel"
+            @visible-change="visibleChange"
+            clearable
+          >
+            <el-option
+              v-for="dict in areaData"
+              :key="dict.area_id"
+              :label="dict.area_name"
+              :value="dict.area_id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="装置名称">
+          <el-input v-model="queryParams.ied_name" clearable></el-input>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit">搜索</el-button>
+          <el-button @click="reset">重置</el-button>
+          <el-button @click="exportAll" class="daochu">导出全部</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="table-data">
+      <el-table
+        :data="tableList"
+        stripe
+        height="90%"
+        ref="tables"
+        style="width: 100%; overflow-y: auto"
+        :cell-style="{ color: '#1A2447', border: 'none', height: '40px' }"
+        :header-cell-style="{
+          color: '#7484AB',
+          borderBottom: '1px solid #A3ADE0',
+        }"
+      >
+        <el-table-column width="80" label="序号">
+          <template #default="scope">
+            {{ scope.$index + 1 }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="ied_name" label="装置名称" />
+        <el-table-column
+          prop="attr_desc"
+          label="装置描述"
+          :show-overflow-tooltip="true"
+        />
+        <el-table-column prop="doi_addr" label="端子地址" />
+        <el-table-column prop="doi_desc" label="端子描述" />
+        <el-table-column prop="gooseorsv" label="信号类型" />
+        <el-table-column prop="in_doi_addr" label="输入端子地址" />
+        <el-table-column prop="in_doi_desc" label="输入端子描述" />
+        <el-table-column prop="in_ied_name" label="输入装置名字" />
+        <el-table-column prop="in_ied_desc" label="输入装置描述" />
+      </el-table>
+    </div>
+  </div>
+</template>
+  
+  <script setup>
+import { ref, onMounted, watch, reactive, toRefs, nextTick } from "vue";
+import { utils, writeFile } from "xlsx";
+import { checkArea, fcdaList } from "@/api/iedNetwork";
+import { ElMessage, ElLoading } from "element-plus";
+import { useRoute } from "vue-router";
+const route = useRoute();
+const scdIdValue = route.query.id;
+const props = defineProps({});
+
+const data = reactive({
+  queryParams: {
+    scd_id: scdIdValue,
+  },
+});
+const { queryParams } = toRefs(data);
+// 表单重置
+const reset = () => {
+  queryParams.value = {
+    scd_id: scdIdValue,
+    area_id: null, //间隔
+    ied_name: null, //装置名称
+  };
+  chooseInterval.value = null;
+  getData();
+};
+const all = [{ area_name: "全部", id: "alls" }];
+const areaData = ref([]); //获取间隔
+const getArea = async () => {
+  const areaRes = await checkArea({ scd_id: scdIdValue });
+  if (!areaRes || !areaRes.data) return;
+  areaData.value = [...all, ...areaRes.data]; //搜索处的间隔
+};
+const emit = defineEmits(["sclBack"]);
+let needScdName = ref(""); //需要的scd名称
+let needFlashName = ref(""); //需要的变电站名称
+let tableList = ref([]); //crc效验结果表格数据
+const getData = async () => {
+  tableList.value = [];
+  let loading = ElLoading.service({
+    lock: true,
+    text: "正在查询数据",
+    background: "rgba(0, 0, 0, 0.7)",
+  });
+  const data = await fcdaList({
+    scd_id: scdIdValue,
+    area_ids: chooseInterval.value,
+    ied_name: queryParams.value.ied_name,
+  });
+  if (!data) return;
+  data.data.forEach(item=>{
+    if(item.doi_addr) tableList.value.push(item);
+  })
+  loading.close();
+};
+const chooseInterval = ref(null); //间隔下拉框选中的数据
+const changeLevel = (e) => {
+  chooseInterval.value = null;
+  chooseInterval.value = e ? e.join() : null;
+};
+//间隔下拉框关闭时触发
+const visibleChange = (visible) => {
+  if (visible == false) {
+    console.log("queryParams.area_id", visible, chooseInterval.value);
+  }
+};
+const tables = ref(null);
+const onSubmit = () => {
+  nextTick(() => {
+    if(!tables.value) return
+    tables.value.setScrollTop(0);
+  });
+  getData();
+};
+const closeX = () => {
+  emit("sclBack", 2);
+};
+
+// 导出全部
+const exportAll = () => {
+  const array = [
+    [
+      "装置名称",
+      "装置描述",
+      "端子地址",
+      "端子描述",
+      "信号类型",
+      "输入端子地址",
+      "输入端子描述",
+      "输入装置名称",
+      "输入装置描述",
+    ],
+  ];
+  tableList.value.forEach((d) => {
+    array.push([
+      d.ied_name,
+      d.attr_desc,
+      d.doi_addr,
+      d.doi_desc,
+      d.gooseorsv,
+      d.in_doi_addr,
+      d.in_doi_desc,
+      d.in_ied_name,
+      d.in_ied_desc,
+    ]);
+  });
+  const sheetName = "Sheet1";
+  const workbook = {
+    SheetNames: [sheetName],
+    Sheets: {},
+  };
+  const sheet = utils.aoa_to_sheet(array);
+  workbook.Sheets[sheetName] = sheet;
+  // 设置列宽
+  sheet["!cols"] = [
+    { wch: 10 },
+    { wch: 30 },
+    { wch: 30 },
+    { wch: 30 },
+    { wch: 20 },
+    { wch: 30 },
+    { wch: 30 },
+    { wch: 10 },
+    { wch: 25 },
+  ];
+  writeFile(workbook, "虚端子关系.xlsx");
+};
+onMounted(() => {
+  getArea();
+  getData();
+  const parentData = JSON.parse(route.query.parentData);
+  needFlashName.value = parentData ? parentData.station_name : null;
+  needScdName.value = parentData ? parentData.scd_name : null;
+});
+</script>
+  
+  <style scoped lang="scss">
+em {
+  list-style: none;
+  font-style: normal;
+}
+.bigBox {
+  width: 97%;
+  height: calc(100vh - 230px);
+  margin-left: 32px;
+  overflow: hidden;
+}
+
+.header {
+  width: 100%;
+  height: auto;
+  text-align: center;
+}
+
+.antherHeader {
+  width: 100%;
+  height: auto;
+  color: #1a2447;
+  font-size: 16px;
+  margin: 16px 0;
+}
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 16px;
+  width: 100%;
+  height: auto;
+  padding: 12px 0 20px 0;
+  border-bottom: 1px solid #a3ade0;
+  color: #1a2447;
+}
+.closeX {
+  font-size: 24px;
+  color: #7484ab;
+  cursor: pointer;
+}
+
+.table-data {
+  height: 100%;
+  margin-left: 16px;
+  overflow-y: auto;
+}
+.daochu {
+  border: 1px solid #255ce7;
+  color: #255ce7;
+  background: #f6f9ff;
+}
+</style>

+ 8 - 1
src/pages/netStructPicture/components/scdTree.vue

@@ -27,6 +27,7 @@
           borderBottom: '1px solid #A3ADE0 !important',
           fontWeight: '400',
         }"
+        highlight-current-row
       >
         <el-table-column width="55" type="selection" />
         <el-table-column
@@ -116,7 +117,7 @@
           :disabled="isLoadingNew"
         >
           <template #trigger>
-            <div class="upload-title">
+            <div class="upload-title" :class="{ 'disabled': isLoadingNew}">
               <img :src="uploadPng" alt="" />
               <span>上传文件</span>
             </div>
@@ -511,6 +512,7 @@ const select = (selection, row) => {
   multipleTable.value.clearSelection();
   // 主要用于将当前勾选的表格状态清除;
   // 当表格数据都没有被勾选的时候就返回;
+  chooseContrast.value = null;
   if (selection.length == 0) {
     isDelete.value = true;
     return;
@@ -652,4 +654,9 @@ onMounted(async () => {
 ::v-deep(.el-table th.el-table__cell:nth-child(1) .cell) {
   visibility: hidden;
 }
+
+.disabled {
+  pointer-events: none;
+  opacity: 0.3;
+}
 </style>

+ 1 - 1
src/pages/netStructPicture/components/virtualRelation.vue

@@ -419,7 +419,7 @@ watch(
   }
 );
 </script>
-<style lang="scss"  scoped>
+<style lang="scss" scoped>
 @mixin img-size {
   width: 48px;
   height: 48px;

+ 3 - 7
src/pages/netStructPicture/index.vue

@@ -150,12 +150,7 @@
       ></SlcCheck>
       <!-- 虚端子关系图 -->
       <div v-if="clickNavCode == 'virtual'">
-        <!-- <virtual-relation 
-            :checkData="checkData"
-            :isOpen="isOpen"
-            :iedRelation="iedRelation"
-            @result="result">
-          </virtual-relation> -->
+        <virtual-table  @sclBack="sclBack"></virtual-table>
       </div>
     </div>
   </div>
@@ -170,6 +165,7 @@ import CidTree from "./components/CidTree.vue";
 import Gsix from "./components/Gsix.vue";
 import scdTree from "./components/scdTree.vue";
 import scdMap from "./components/scdMap.vue";
+import VirtualTable from "./components/VirtualTable.vue";
 import CrcCheck from "./newTitle/CrcCheck";
 import SlcCheck from "./newTitle/SlcCheck.vue";
 import { useRoute } from "vue-router";
@@ -188,7 +184,7 @@ const navtopData = ref([
   { name: "SCD文件一致性校核", code: "SCD" },
   { name: "SCL文件校核", code: "SCL" },
   { name: "CRC校核", code: "CRC" },
-  { name: "虚端子关系", code: "virtual" },
+  { name: "虚端子关系", code: "virtual" },
 ]);
 const activeNav = ref(null);
 const upload = ref(null); //上传按钮的ref

+ 4 - 0
src/pages/netStructPicture/newTitle/CrcCheck.vue

@@ -42,6 +42,7 @@
         :data="tableList"
         stripe
         height="90%"
+        ref="tables"
         style="width: 100%;overflow-y: auto;"
         :cell-style="{ color: '#1A2447', border: 'none', height: '40px' }"
         :header-cell-style="{
@@ -164,7 +165,9 @@ const reload = () => {
   });
 };
 //选择全部还是不一致等
+const tables = ref(null);
 const selectClick = (value) => {
+  tables.value.setScrollTop(0);
   // 备份最初的数据
   if (value == "3") { // 一致
     tableList.value = originalData.value.filter(
@@ -195,6 +198,7 @@ em {
   width: 97%;
   height: calc(100vh - 230px);
   margin-left: 32px;
+  overflow: hidden;
 }
 
 .header {

+ 67 - 6
src/pages/system/modalComp/CopyLoad.vue

@@ -6,6 +6,20 @@
                     <el-form-item label="名称" prop="name">
                         <el-input v-model="copyForm.name" />
                     </el-form-item>
+                    <el-form-item label="电压等级" prop="flashLevel">
+                        <el-select @change="flashChange" v-model="copyForm.flashLevel" placeholder="不选择默认当前电压等级"
+                            size="mini" style="width: 240px">
+                            <el-option v-for="item in flashList" :key="item.value" :label="item.label"
+                                :value="item.value" />
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item label="接线方式" prop="flashLevel">
+                        <el-select @change="lineChange" v-model="copyForm.lineType" placeholder="不选择默认当前接线方式"
+                            size="mini" style="width: 240px">
+                            <el-option v-for="item in lineList" :key="item.value" :label="item.label"
+                                :value="item.value" />
+                        </el-select>
+                    </el-form-item>
                 </el-form>
             </div>
             <template #footer>
@@ -23,6 +37,8 @@
 <script>
 import { ref, watch, onMounted, onBeforeUnmount, reactive } from 'vue'
 import flow from '@/api/flow/flow';
+import litLine from '@/api/litLine';
+import systemRow from '@/api/systemRow';
 import { ElLoading, ElMessage } from 'element-plus';
 export default {
     props: {
@@ -38,41 +54,74 @@ export default {
     setup(props, { emit }) {
         let dialogVisible = ref(false)//模态框打开或关闭
         let copyForm = ref({
-            name: ""
+            name: "",
+            flashLevel: "",
+            lineType: "",
         })//表单内容项
         let copyRules = reactive({
             name: [{ required: true, message: '请输入名称', trigger: 'blur' },]
         })//表单验证
         let copyRef = ref(null)//表单ref
-        let receive = ref({})//接收insidemodule传过来的模型数据
+        let receive = ref({})//接收insidemodule传过来的模型数据l
+        let flashList = ref([])//电压等级列表
+        let lineList = ref([])//接线方式列表
         // 初始化本组件函数
         function reload() {
-            dialogVisible.value = props.copyType
-            receive.value = props.coolObj
+            dialogVisible.value = props.copyType//变为true打开模态框
+            receive.value = props.coolObj//接受的接线方式信息,为对象
+            // 获取所有接线方式
+            litLine.getAllLine({ pageno: 1, pagesize: 999999 }).then(res => {
+                if (res.data) {
+                    lineList.value = res.data.map(item => {
+                        return {
+                            label: item.name,
+                            value: item.id
+                        }
+                    })
+                }
+            })
+            // 获取所有电压等级
+            systemRow.getChildren({ code: "voltage_level" }).then(res => {
+                if (res.data) {
+                    flashList.value = res.data.map(item => {
+                        return {
+                            label: item.name,
+                            value: item.id
+                        }
+                    })
+                }
+            })
         }
         // 模态框关闭
         function modalClose() {
             dialogVisible.value = false
             emit("copyBack", dialogVisible.value)
-        }//模态框确认
+        }
+        //模态框确认
         function modalSure() {
             copyRef.value.validate((val) => {
                 if (val) {
+                    // 打开加载动画
                     const loading = ElLoading.service({
                         lock: true,
                         text: '复制中',
                         background: 'rgba(0, 0, 0, 0.7)',
                     })
+                    // 调用后台接口
                     flow.copyNowMap({
                         id: receive.value.id - 0,
-                        newname: copyForm.value.name
+                        newname: copyForm.value.name,
+                        vol_id: copyForm.value.flashLevel - 0,
+                        link_style_id: copyForm.value.lineType - 0,
                     }).then(res => {
                         if (res.code == 0) {
                             ElMessage({
                                 message: "复制成功!",
                                 type: "success"
                             })
+                            // 关闭加载动画
                             loading.close()
+                            // 关闭模态框
                             dialogVisible.value = false
                             emit("copyBack", dialogVisible.value)
                         } else {
@@ -90,6 +139,14 @@ export default {
                 }
             })
         }
+        // 电压等级的选择器change方法
+        function flashChange(e) {
+            copyForm.value.flashLevel = e
+        }
+        // 接线方式的选择器的change方法
+        function lineChange(e) {
+            copyForm.value.lineType = e
+        }
         // 生命周期函数
         onMounted(() => {
             reload()//初始化
@@ -104,6 +161,10 @@ export default {
             copyRef,//表单ref
             copyRules,//表单验证项
             receive,//接收穿过来的模型数据
+            flashList,//电压等级列表
+            lineList,//接线方式列表
+            flashChange,// 电压等级的选择器change方法
+            lineChange,// 接线方式的选择器的change方法
         }
     }
 }