Browse Source

基本信息的晚上,装置关系的完善

“yueshang” 1 year ago
parent
commit
ff1fe14ca9

+ 8 - 0
src/api/iedNetwork/index.js

@@ -164,6 +164,14 @@ export function getLdeviceList(query) {
     params: query
   })
 }
+//基础信息中间图片上的文字信息
+export function getNodeAttrs(query) {
+  return request({
+    url: 'screen/scd/node/attrs',
+    method: 'get',
+    params: query
+  })
+}
 
 
 

+ 147 - 27
src/pages/netStructPicture/components/basicInfo.vue

@@ -16,6 +16,7 @@
     </div>
     <div class="wrapper">
       <div class="grid">
+        <!-- 左侧 -->
         <div
           class="col fluid"
           :class="{ transp: mainTitle && mainTitle.length < 2 }"
@@ -78,7 +79,54 @@
             </div>
           </div>
         </div>
-        <div class="col main-middle" id="middleLine"></div>
+        <!-- 中间 -->
+        <div class="col main-middle" id="middleLine">
+          <div v-if="attrsData">
+            <el-tooltip
+              class="box-item"
+              effect="light"
+              :content="attrsData.desc"
+              placement="top-start"
+            >
+              <div class="text-overflow ied_struct_desc">
+                {{ attrsData.desc }}
+              </div>
+            </el-tooltip>
+            <el-tooltip
+              class="box-item"
+              effect="light"
+              :content="attrsData.type"
+              placement="top-start"
+            >
+              <div class="text-overflow ied_struct_type">
+                {{ attrsData.type }}
+              </div>
+            </el-tooltip>
+            <el-tooltip
+              class="box-item"
+              effect="light"
+              :content="attrsData.manufacturer"
+              placement="top-start"
+            >
+              <div class="text-overflow ied_struct_manufacturer">
+                {{ attrsData.manufacturer }}
+              </div>
+            </el-tooltip>
+            <el-tooltip
+              class="box-item"
+              effect="light"
+              :content="attrsData.name"
+              placement="top-start"
+            >
+              <div
+                class="text-overflow ied_struct_manufacturer ied_struct_manufacturer1"
+              >
+                {{ attrsData.name }}
+              </div>
+            </el-tooltip>
+          </div>
+        </div>
+        <!-- 右侧 -->
         <div
           class="col fluid"
           style="margin-right: 20px"
@@ -189,7 +237,12 @@
         </div>
         <div class="child-item" v-if="mainTitle && mainTitle.length > 0">
           <div class="ldevice">LDevice</div>
-          <div class="ldevice-cont" v-for="(item, index) in mainTitle[0].childList[0]" :key="index" @click="clickMain(item)">
+          <div
+            class="ldevice-cont"
+            v-for="(item, index) in mainTitle[0].childList[0]"
+            :key="index"
+            @click="clickMain(item)"
+          >
             <img :src="legislation" alt="" />
             <div class="img-title">{{ item.attr_inst }}</div>
             <div class="decrip-child">{{ item.attr_desc }}</div>
@@ -221,11 +274,11 @@
         :cell-style="{ color: '#000' }"
       >
         <el-table-column prop="attr_ld_inst" label="ldInst" />
-        <el-table-column prop="attr_prefix" label="prefix"/>
-        <el-table-column prop="attr_ln_class" label="lnClass"/>
+        <el-table-column prop="attr_prefix" label="prefix" />
+        <el-table-column prop="attr_ln_class" label="lnClass" />
         <el-table-column prop="attr_ln_inst" label="lnInst" />
         <el-table-column prop="attr_do_name" label="doName" />
-        <el-table-column prop="da_datatype" label="attr_da_name" width="180"/>
+        <el-table-column prop="da_datatype" label="attr_da_name" width="180" />
         <el-table-column prop="attr_fc" label="fc" />
       </el-table>
     </el-dialog>
@@ -240,7 +293,9 @@
       <template #header>
         <div class="my-header">
           <div class="dialog-nav-title">
-            {{ `${clickMainTitle.attr_inst}${clickMainTitle.attr_desc} — LN/LN0节点列表` }}
+            {{
+              `${clickMainTitle.attr_inst}${clickMainTitle.attr_desc} — LN/LN0节点列表`
+            }}
           </div>
         </div>
       </template>
@@ -251,10 +306,10 @@
         height="450"
         :cell-style="{ color: '#000' }"
       >
-      <el-table-column type="index" label="序号" width="80" />
+        <el-table-column type="index" label="序号" width="80" />
         <el-table-column prop="attr_inst" label="inst" />
-        <el-table-column prop="attr_ln_class" label="lnClass"/>
-        <el-table-column prop="attr_ln_type" label="lnType"/>
+        <el-table-column prop="attr_ln_class" label="lnClass" />
+        <el-table-column prop="attr_ln_type" label="lnType" />
         <el-table-column prop="attr_desc" label="desc" />
       </el-table>
     </el-dialog>
@@ -265,7 +320,13 @@
 import { defineProps, onMounted, ref, inject, nextTick, watch } from "vue";
 import legislation from "@/assets/image/instruct/legislation.png";
 import cylinder from "@/assets/image/instruct/cylinder.png";
-import { getNodeList, getNetworkInfo, getLdeviceList,nodeList } from "@/api/iedNetwork";
+import {
+  getNodeList,
+  getNetworkInfo,
+  getLdeviceList,
+  nodeList,
+  getNodeAttrs,
+} from "@/api/iedNetwork";
 import LeaderLine from "../../../../public/leader-line.min.js";
 import AnimEvent from "../../../../public/anim-event.min.js";
 import { CloseBold } from "@element-plus/icons-vue";
@@ -286,10 +347,10 @@ const moBottom = ref(null); //底部方框所展示的MAC-Address等desc
 const moLeft = ref(null); //左侧方框所展示的MAC-Address等desc
 const moRight = ref(null); //右侧方框所展示的MAC-Address等desc
 const activeCircel = ref(0); //点击数字圆圈的样式
-const isOpennav = ref(false);//头部点击弹窗显示
-const clickNavTitle= ref(null);//头部点击弹窗数据
-const clickNavData = ref(null);//头部点击弹窗数据
-const isOpenMain = ref(false);//点击方框
+const isOpennav = ref(false); //头部点击弹窗显示
+const clickNavTitle = ref(null); //头部点击弹窗数据
+const clickNavData = ref(null); //头部点击弹窗数据
+const isOpenMain = ref(false); //点击方框
 const clickMainTitle = ref(null);
 const clickMainData = ref(null);
 const loading = ref(true);
@@ -389,7 +450,6 @@ const getMainList = async () => {
         }
       }
     }
-    console.log("mainTitle.value", mainTitle.value);
   }
 };
 //弹窗打开后使得线条在指定区域中
@@ -494,9 +554,19 @@ const clickCircel = (item, index, type) => {
     moLeft.value = JSON.parse(newData);
   }
 };
+const attrsData = ref(null);
+const getNode = async () => {
+  const attrRes = await getNodeAttrs({
+    scd_id: scdIdValue,
+    ied_name: props.checkData.ied_name,
+    node_id: props.checkData.node_id,
+  });
+  attrsData.value = attrRes.data;
+};
 onMounted(() => {
   getNav();
   getMainTitle();
+  getNode();
   nextTick(() => {
     setTimeout(() => {
       getLine();
@@ -533,6 +603,7 @@ watch(
       getNav();
       loading.value = true;
       getMainTitle();
+      getNode();
       nextTick(() => {
         setTimeout(() => {
           getLine();
@@ -548,12 +619,12 @@ const removeLine2 = () => {
   });
 };
 //点击头部展示的弹框
-const clickNav =async (item) => {
+const clickNav = async (item) => {
   clickNavTitle.value = item;
   isOpennav.value = true;
   const navRes = await nodeList({
     scd_id: scdIdValue,
-    parent_node_id:item.node_id,
+    parent_node_id: item.node_id,
     pagesize: 10000,
     name: "FCDA",
   });
@@ -562,29 +633,28 @@ const clickNav =async (item) => {
 const cancelClickNav = () => {
   clickNavData.value = null;
   isOpennav.value = false;
-}
-const clickMain =async (item) => {
-  console.log('item', item)
+};
+const clickMain = async (item) => {
   clickMainTitle.value = item;
   isOpenMain.value = true;
   const navRes = await nodeList({
     scd_id: scdIdValue,
-    parent_node_id:item.node_id,
+    parent_node_id: item.node_id,
     pagesize: 10000,
     name: "LN0",
   });
   const navRes2 = await nodeList({
     scd_id: scdIdValue,
-    parent_node_id:item.node_id,
+    parent_node_id: item.node_id,
     pagesize: 10000,
     name: "LN",
   });
-  clickMainData.value = [...navRes.data,...navRes2.data];
+  clickMainData.value = [...navRes.data, ...navRes2.data];
 };
 const cancelClickMain = () => {
   clickMainData.value = null;
   isOpenMain.value = false;
-}
+};
 </script>
 
 <style scoped lang="scss">
@@ -674,7 +744,7 @@ const cancelClickMain = () => {
       color: white;
       border-radius: 10px;
     }
-    .ldevice-cont{
+    .ldevice-cont {
       display: flex;
       flex-direction: column;
       align-items: center;
@@ -731,6 +801,56 @@ const cancelClickMain = () => {
   background: #fff url("~@/assets/image/instruct/network_slices.png") no-repeat
     center;
   background-size: 160px;
+  position: relative;
+  font-size: 12px;
+  .text-overflow {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display: block;
+    cursor: pointer;
+  }
+  .ied_struct_manufacturer {
+    line-height: 2rem;
+    transform: rotate(-33deg);
+    top: 65%;
+    position: absolute;
+    left: 62%;
+    border: 0px solid #cccccc1c;
+    font-style: italic;
+    font-size: 1rem;
+    width: 6rem;
+    text-align: center;
+  }
+  .ied_struct_manufacturer1 {
+    top: 54%;
+    left: 59%;
+  }
+  .ied_struct_desc {
+    line-height: 2rem;
+    position: absolute;
+    transform: rotate(31deg);
+    top: 15%;
+    left: 32%;
+    width: 59%;
+    word-break: break-word;
+    color: #134bea;
+    font-weight: bold;
+    font-style: italic;
+    text-align: center;
+  }
+  .ied_struct_type {
+    position: absolute;
+    transform: rotate(31deg);
+    top: 26%;
+    left: 17%;
+    color: #15010152;
+    font-size: 1rem;
+    font-style: italic;
+    width: 60%;
+    line-height: 1.5rem;
+    text-align: center;
+  }
 }
 
 /* 设置fluid样式 */
@@ -746,8 +866,8 @@ const cancelClickMain = () => {
   transform: translateX(-50%);
   margin-top: 40px;
 }
-.dialog-nav-title{
-  color:#09162C;
+.dialog-nav-title {
+  color: #09162c;
   font-size: 16px;
 }
 </style>

+ 4 - 4
src/pages/netStructPicture/components/infoTable.vue

@@ -11,9 +11,9 @@
         :highlight-current-row="true"
         ref="myTable5"
       >
-        <el-table-column type="index" label="序号" width="80" />
-        <el-table-column prop="accesspoint_name" label="访问点" width="180" />
-        <el-table-column label="逻辑设备(lnst)">
+        <el-table-column type="index" label="序号" width="60" />
+        <el-table-column prop="accesspoint_name" label="访问点"/>
+        <el-table-column label="逻辑设备(lnst)" width="160">
           <template #default="scope">
             {{ `${scope.row.ld_desc}(${scope.row.ld_inst})` }}
           </template>
@@ -45,7 +45,7 @@
         :cell-style="{ color: '#000' }"
       >
         <el-table-column type="index" label="序号" width="80" />
-        <el-table-column prop="doi_desc" label="条目描述" width="180" />
+        <el-table-column prop="doi_desc" label="条目描述" />
         <el-table-column prop="da_datatype" label="数据类型" />
         <el-table-column prop="short_addr" label="内部地址" />
       </el-table>

+ 139 - 51
src/pages/netStructPicture/components/inoutControl.vue

@@ -28,6 +28,7 @@
               class="ied-desc-child"
               v-for="(item3, index3) in cItem.childItem"
               :key="index3"
+              :class="{ 'smv-color': item3.ctrl_type == 'smv' }"
               :ref="(el) => setdomLeftChild2(el, item3)"
             >
               <div>{{ item3.ctrl_name }}</div>
@@ -47,11 +48,21 @@
             class="midlestyle"
             v-for="(item, index) in svInfo"
             :key="index"
+            :class="{ 'smv-color': item.attr_name == 'smvcb0' }"
             :ref="(el) => setdomMiddle2(el, item)"
           >
             <div>{{ `${item.ldinst}/${item.attr_name}` }}</div>
             <div>{{ item.datset_desc }}</div>
-            <div class="ied-desc">APPID:{{ item.APPID }}</div>
+            <div
+              class="ied-desc"
+              style="color: #1a2447"
+              v-if="item.attr_name != 'smvcb0'"
+            >
+              APPID:{{ item.APPID }}
+            </div>
+            <div class="ied-desc" style="color: #1a2447" v-else>
+              APPID:{{ item.address.APPID }}
+            </div>
           </div>
         </div>
       </div>
@@ -76,6 +87,7 @@
               class="ied-desc-child"
               v-for="(item3, index3) in cItem.childItem"
               :key="index3"
+              :class="{ 'smv-color': item3.ctrl_type == 'smv' }"
               :ref="(el) => setdomRight2Child2(el, item3)"
             >
               <div>{{ item3.ctrl_name }}</div>
@@ -96,7 +108,7 @@
   </div>
 </template>
 <script setup>
-import { onMounted, watch, ref, nextTick, defineEmits, inject  } from "vue";
+import { onMounted, watch, ref, nextTick, defineEmits, inject } from "vue";
 import LeaderLine from "../../../../public/leader-line.min.js";
 import AnimEvent from "../../../../public/anim-event.min.js";
 import inoutSendOrRv from "./inoutSendOrRv";
@@ -184,6 +196,7 @@ const getNetworkInfo = async () => {
     ied_name: props.checkData.ied_name,
   });
   if (svResInfoCtrl.data && svResInfoCtrl.data.GSEControl) {
+    //处理数据得到APPID
     svResInfo.data.forEach((item) => {
       svResInfoCtrl.data.GSEControl.forEach((key) => {
         if (item.cb_name == key.attr_name) {
@@ -191,7 +204,10 @@ const getNetworkInfo = async () => {
         }
       });
     });
-    svInfo.value = svResInfoCtrl.data.GSEControl;
+    svInfo.value = [
+      ...svResInfoCtrl.data.SampledValueControl,
+      ...svResInfoCtrl.data.GSEControl,
+    ];
     if (svInfo.value && svInfo.value.length > 3) {
       middleElement.value.style.marginTop = "20px";
     } else {
@@ -291,9 +307,42 @@ const bothSide = (data) => {
   leftList.value = formatArr.splice(0, long1);
   rightList.value = formatArr.splice(0);
 };
-
+const newLine = (endDom, startDom, options) => {
+  const BUTTON_HEIGHT = 24;
+  const BUTTON_OFFSET = 8;
+  let line;
+  const rectEnd = endDom.getBoundingClientRect();
+  line = new LeaderLine(
+    endDom,
+    LeaderLine.pointAnchor(startDom, { x: 0, y: rectEnd.top - 224 }),
+    {
+      color: "red",
+      size: 2,
+      path: "straight",
+      startSocket: "right",
+      endSocket: "left",
+    }
+  );
+  let elmButton = document.body.appendChild(document.createElement("div"));
+  let rect = startDom.getBoundingClientRect();
+  elmButton.className = "circel-button";
+  console.log('elmButton', elmButton)
+  elmButton.textContent = 'celmButton celmButton celmButton celmButton ';
+  elmButton.title = 'Remove Line';
+  elmButton.style.left = `${rect.right + BUTTON_OFFSET}px`;
+  elmButton.style.top = `${rect.top + rect.height / 2 - BUTTON_HEIGHT / 2}px`;
+  elmButton.addEventListener("click", () => {
+    
+  });
+ console.log('line', line)
+  return line;
+};
 const setLeaderline2 = () => {
-  // lineArr.value = [];
+  console.log(
+    "fdomListLeftChild2.valueirst",
+    domListMiddle2.value,
+    domList2.value
+  );
   //线条样式
   const startDom = document.getElementById("end");
   //左侧子组件
@@ -303,24 +352,25 @@ const setLeaderline2 = () => {
     const options = key.inputs_cnt.toString();
     const rectEnd = endDom.getBoundingClientRect();
     if (key.ctrl_type == "smv") {
-      line = new LeaderLine(
-        endDom,
-        LeaderLine.pointAnchor(startDom, { x: 0, y: rectEnd.top - 222 }),
-        {
-          color: "red",
-          size: 2,
-          path: "straight",
-          startSocket: "right",
-          endSocket: "left",
-          middleLabel: LeaderLine.captionLabel({
-            text: options,
-          }),
-        }
-      );
+      line = newLine(endDom, startDom, options);
+      // line = new LeaderLine(
+      //   endDom,
+      //   LeaderLine.pointAnchor(startDom, { x: 0, y: rectEnd.top - 224 }),
+      //   {
+      //     color: "red",
+      //     size: 2,
+      //     path: "straight",
+      //     startSocket: "right",
+      //     endSocket: "left",
+      //     middleLabel: LeaderLine.captionLabel({
+      //       text: options,
+      //     }),
+      //   }
+      // );
     } else {
       line = new LeaderLine(
         endDom,
-        LeaderLine.pointAnchor(startDom, { x: 0, y: rectEnd.top - 222 }),
+        LeaderLine.pointAnchor(startDom, { x: 0, y: rectEnd.top - 224 }),
         {
           color: "#255CE7",
           size: 2,
@@ -344,7 +394,7 @@ const setLeaderline2 = () => {
     const options = key.inputs_cnt.toString();
     if (key.ctrl_type == "smv") {
       line = new LeaderLine(
-        LeaderLine.pointAnchor(startDom, { x: "100%", y: rectEnd.top - 222 }),
+        LeaderLine.pointAnchor(startDom, { x: "100%", y: rectEnd.top - 224 }),
         endDom,
         {
           color: "red",
@@ -359,7 +409,7 @@ const setLeaderline2 = () => {
       );
     } else {
       line = new LeaderLine(
-        LeaderLine.pointAnchor(startDom, { x: "100%", y: rectEnd.top - 222 }),
+        LeaderLine.pointAnchor(startDom, { x: "100%", y: rectEnd.top - 224 }),
         endDom,
         {
           color: "#255CE7",
@@ -387,7 +437,7 @@ const setLeaderline2 = () => {
             if (item.ctrl_id == key2.node_id) {
               const startDom = value2;
               const options2 = item.inputs_cnt.toString();
-              line = new LeaderLine(endDom, startDom, {
+              let lineStyle = {
                 color: "#51637F",
                 size: 2,
                 path: "straight",
@@ -396,7 +446,11 @@ const setLeaderline2 = () => {
                 startSocket: "right",
                 endSocket: "left",
                 middleLabel: LeaderLine.captionLabel(options2),
-              });
+              };
+              if (key2.attr_name == "smvcb0") {
+                lineStyle.color = "red";
+              }
+              line = new LeaderLine(endDom, startDom, lineStyle);
               leaderLines2.value.push(line);
             }
           }
@@ -412,7 +466,7 @@ const setLeaderline2 = () => {
             if (item.ctrl_id == key2.node_id) {
               const startDom = value2;
               const options3 = item.inputs_cnt.toString();
-              line2 = new LeaderLine(startDom, endDom, {
+              let lineStyle2 = {
                 color: "#51637F",
                 size: 2,
                 path: "straight",
@@ -421,7 +475,11 @@ const setLeaderline2 = () => {
                 endSocket: "left",
                 startSocket: "right",
                 middleLabel: LeaderLine.captionLabel(options3),
-              });
+              };
+              if (key2.attr_name == "smvcb0") {
+                lineStyle2.color = "red";
+              }
+              line2 = new LeaderLine(startDom, endDom, lineStyle2);
               leaderLines2.value.push(line2);
             }
           }
@@ -447,20 +505,33 @@ const newPositionLine2 = () => {
     }),
     false
   );
+  window.addEventListener(
+    "resize",
+    AnimEvent.add(function () {
+      leaderLines2.value.forEach((line) => {
+        hiddenLine2();
+        line.position();
+        line.positionByWindowResize = false;
+      });
+    }),
+    false
+  );
 };
 //弹窗打开后使得线条在指定区域中
 const hiddenLine2 = () => {
-  const elmWrapper = document.getElementById("wrapper");
-  // 移动 line
-  document.body.querySelectorAll("body .leader-line").forEach((node) => {
-    elmWrapper.appendChild(node);
-  });
-  elmWrapper.style.transform = "none";
-  var rectWrapper = elmWrapper.getBoundingClientRect();
-  // Move to the origin of coordinates as the document
-  elmWrapper.style.transform = `translate(${
-    (rectWrapper.left + window.scrollY) * -1
-  }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
+  if (props.isPhoto == "photo") {
+    const elmWrapper = document.getElementById("wrapper");
+    // 移动 line
+    document.body.querySelectorAll("body .leader-line").forEach((node) => {
+      elmWrapper.appendChild(node);
+    });
+    elmWrapper.style.transform = "none";
+    var rectWrapper = elmWrapper.getBoundingClientRect();
+    // Move to the origin of coordinates as the document
+    elmWrapper.style.transform = `translate(${
+      (rectWrapper.left + window.scrollY) * -1
+    }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
+  }
 };
 const setLine2 = () => {
   if (listData2.value) {
@@ -478,13 +549,12 @@ const removeLine2 = () => {
   });
 };
 onMounted(() => {
-  if (props.checkData != null) {
+  if (props.checkData != null && props.isPhoto == "photo") {
     getIedChild();
-
+    getNetworkInfo();
   }
   //不加条件切换下方tab时会出现bug
   if (props.isPhoto == "photo") {
-    getNetworkInfo();
     nextTick(() => {
       setLine2();
       nextTick(() => {
@@ -498,10 +568,13 @@ watch(
   () => props.isPhoto,
   (newValue) => {
     tabValue.value = newValue;
-    if (tabValue.value == "photo") {
+    if (listData2.value != null && tabValue.value == "photo") {
       nextTick(() => {
         setLine2();
+        clickResetLine2();
         newPositionLine2();
+        getIedChild();
+        getNetworkInfo();
       });
     }
   }
@@ -512,11 +585,8 @@ watch(
     listData2.value = [];
     svInfo.value = [];
     listData2.value = newValue;
-    if (newValue != null) {
+    if (newValue != null && tabValue.value == "photo") {
       getIedChild();
-   
-    }
-    if (tabValue.value == "photo") {
       clickResetLine2();
       getNetworkInfo();
     }
@@ -543,12 +613,12 @@ watch(
   }
 );
 watch(
-    () => listData2.value,
-    (newValue) => {
-      emit("result", newValue);
-      clickResetLine2();
-    }
-  );
+  () => listData2.value,
+  (newValue) => {
+    emit("result", newValue);
+    clickResetLine2();
+  }
+);
 </script>
 <style lang="scss"  scoped>
 @mixin img-size {
@@ -641,4 +711,22 @@ watch(
   height: 0;
   position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
 }
+.smv-color {
+  color: red;
+  border: 1px solid red;
+}
+.circel-button {
+  width: 20px;
+  height: 20px;
+  border-radius: 10px;
+  background: #2a56e9;
+  position: absolute;
+  cursor: pointer;
+  color: white;
+  background-repeat: no-repeat;
+  background-position: center;
+  background-size: contain;
+  z-index: 9999;
+  background-image: url("~@/assets/image/instruct/navtop.png");
+}
 </style>

+ 5 - 5
src/pages/netStructPicture/components/netWork.vue

@@ -151,7 +151,7 @@ const loading = ref(true);
 //获取网络图的顶部列表
 const getNetWork = async () => {
   const infoRes = await nodeList({
-    scd_id: 568000158,
+    scd_id: 588000164,
     pagesize: 10000,
     name: "SubNetwork",
   });
@@ -170,7 +170,7 @@ const allApData = ref({});
 const initLoad = async () => {
   allApData.value = {};
   const allAP = await nodeList({
-    scd_id: 568000158,
+    scd_id: 588000164,
     pagesize: 10000,
     name: "ConnectedAP",
   });
@@ -198,7 +198,7 @@ const initLoad = async () => {
 };
 //处理重复的ip
 const ipNetaddr = async () => {
-  const ipRes = await iedNetaddr({ scd_id: 568000158 });
+  const ipRes = await iedNetaddr({ scd_id: 588000164 });
   if (ipRes.code == 1) {
     return;
   }
@@ -500,11 +500,11 @@ const clickNetworkInfo = (value) => {
 
 const iedRelationData = ref([]);
 const iedRelation = async () => {
-  const iedRes = await scdIedRelation({ scd_id: 568000158 });
+  const iedRes = await scdIedRelation({ scd_id: 588000164 });
   iedRelationData.value = iedRes.data;
 };
 //弹窗=============
-provide('scdId',568000158)
+provide('scdId',588000164)
 </script>
   
 <style scoped lang="scss">

+ 360 - 307
src/pages/netStructPicture/components/relationShip.vue

@@ -2,7 +2,7 @@
 <template>
   <div>
     <div class="main-cont" ref="myElement" id="treedom">
-      <div class="main-left">
+      <div class="main-left" ref="leftElement">
         <div
           v-for="(item, index) in leftList"
           :key="index"
@@ -26,7 +26,7 @@
           <div v-if="listData">{{ listData.desc }}</div>
         </div>
       </div>
-      <div class="main-right">
+      <div class="main-right" ref="rightElement">
         <div
           v-for="(item, index) in rightList"
           :key="index"
@@ -46,334 +46,387 @@
     </div>
     <div id="wrapper"></div>
   </div>
-  </template>
+</template>
   <script setup>
-  import { onMounted, watch, ref, nextTick, defineEmits } from "vue";
-  import devicePng from "@/assets/image/instruct/device.png";
-  import LeaderLine from "../../../../public/leader-line.min.js";
-  import AnimEvent from "../../../../public/anim-event.min.js";
-  const props = defineProps({
-    checkData: {
-      type: Object,
-      default: () => {},
-    },
-    isOpen: {
-      type: Boolean,
-      default: false,
-    },
-    iedRelation: {
-      type: Object,
-      default: () => {},
-    },
-    tabName: {
+import { onMounted, watch, ref, nextTick, defineEmits } from "vue";
+import devicePng from "@/assets/image/instruct/device.png";
+import LeaderLine from "../../../../public/leader-line.min.js";
+import AnimEvent from "../../../../public/anim-event.min.js";
+const props = defineProps({
+  checkData: {
+    type: Object,
+    default: () => {},
+  },
+  isOpen: {
+    type: Boolean,
+    default: false,
+  },
+  iedRelation: {
+    type: Object,
+    default: () => {},
+  },
+  tabName: {
     type: String,
     default: "",
   },
-  });
-  const middleElement = ref(null);
-  const myElement = ref(null);
-  let leaderLines = ref([]); //控制线条显示
-  const leftList = ref([]);
-  const rightList = ref([]);
-  const domList = ref(new Map()); //获取 所有的ref
-  const domListRight = ref(new Map()); //获取 所有的ref
-  const listData = ref(props.checkData); //线条左右两侧的数据
-  const emit = defineEmits(["result"]); //如果不加这个再次点击左侧会没有反应
-  const setdom = (el, item) => {
-    //左侧dom
-    if (el) {
-      domList.value.set(item, el);
-    }
-  };
-  const setdomRight = (el, item) => {
-    //右侧dom
-    if (el) {
-      domListRight.value.set(item, el);
-    }
-  };
-  const processArray = (arr) => {
-    // ref_ied_id作为键,obj作为值
-    const uniqueObjects = new Map();
-    // 遍历数组
-    for (const obj of arr) {
-      const { ref_ied_id } = obj;
-      // 如果当前对象的 ref_ied_id 属性已经存在于 uniqueObjects 中
-      if (uniqueObjects.has(ref_ied_id)) {
-        // 将对应对象的 ref_type 属性设为 2,箭头双向
-        uniqueObjects.get(ref_ied_id).ref_type = 2;
-      } else {
-        // 否则,将当前对象添加到 uniqueObjects 中
-        uniqueObjects.set(ref_ied_id, obj);
-      }
-    }
-    // 将 uniqueObjects 中的值转为数组并返回
-    return Array.from(uniqueObjects.values());
-  };
-  //点击图片的时候筛选出数据
-  const clickImg = (dataItem) => {
-    Object.values(props.iedRelation).find((item) => {
-      if (item.ied_name == dataItem.ref_ied_name) {
-        listData.value = item;
-      }
-    });
-  };
-  watch(
-    () => props.checkData,
-    (newValue, oldV) => {
-      listData.value = newValue;
-      if (newValue && leaderLines.value.length > 0) {
-        // leaderLines.value.forEach((line) => line.remove()); //清除连线
-        leaderLines.value = [];
-      }
-    },
-    { deep: true }
-  );
-  watch(
-    () => listData.value,
-    (newValue) => {
-      emit("result", newValue);
-      clickResetLine();
+});
+const middleElement = ref(null);
+const rightElement = ref(null);
+const leftElement = ref(null);
+const myElement = ref(null);
+let leaderLines = ref([]); //控制线条显示
+const leftList = ref([]);
+const rightList = ref([]);
+const domList = ref(new Map()); //获取 所有的ref
+const domListRight = ref(new Map()); //获取 所有的ref
+const listData = ref(props.checkData); //线条左右两侧的数据
+const emit = defineEmits(["result"]); //如果不加这个再次点击左侧会没有反应
+const setdom = (el, item) => {
+  //左侧dom
+  if (el) {
+    domList.value.set(item, el);
+  }
+};
+const setdomRight = (el, item) => {
+  //右侧dom
+  if (el) {
+    domListRight.value.set(item, el);
+  }
+};
+const processArray = (arr) => {
+  // ref_ied_id作为键,obj作为值
+  const uniqueObjects = new Map();
+  // 遍历数组
+  for (const obj of arr) {
+    const { ref_ied_id } = obj;
+    // 如果当前对象的 ref_ied_id 属性已经存在于 uniqueObjects 中
+    if (uniqueObjects.has(ref_ied_id)) {
+      // 将对应对象的 ref_type 属性设为 2,箭头双向
+      uniqueObjects.get(ref_ied_id).ref_type = 2;
+    } else {
+      // 否则,将当前对象添加到 uniqueObjects 中
+      uniqueObjects.set(ref_ied_id, obj);
     }
-  );
-  watch(
-    () => props.isOpen,
-    (newValue) => {
-      if (newValue) {
-        domList.value.clear();
-        domListRight.value.clear();
-        leaderLines.value = [];
-      }
-      nextTick(() => {
-        middleLinePosition();
-        removeLine();
-      });
+  }
+  // 将 uniqueObjects 中的值转为数组并返回
+  return Array.from(uniqueObjects.values());
+};
+//点击图片的时候筛选出数据
+const clickImg = (dataItem) => {
+  Object.values(props.iedRelation).find((item) => {
+    if (item.ied_name == dataItem.ref_ied_name) {
+      listData.value = item;
     }
-  );
-  //点击后重置数据和线条
-  const clickResetLine = () => {
-    domList.value.clear();
-    domListRight.value.clear();
-    leaderLines.value = [];
-    middleLinePosition();
-    setLine();
-    removeLine();
-  };
-  // 将设备列表分成两份
-  const bothSide = (data) => {
-    const formatArr = processArray(data);
-    const arrlenght = formatArr.length;
-    const long1 = Math.ceil(arrlenght / 2);
-    leftList.value = formatArr.splice(0, long1);
-    rightList.value = formatArr.splice(0);
-  };
-  
-  const setLeaderline = () => {
-    // lineArr.value = [];
-    //线条样式
-    const lineStyle0 = {
-      color: "#51637F",
-      size: 2,
-      path: "straight",
-      startPlug: "arrow1",
-      endPlug: "behind",
-      startSocket: "right",
-      endSocket: "left",
-    };
-    const lineStyle1 = {
-      color: "#51637F",
-      size: 2,
-      path: "straight",
-      endPlug: "arrow1",
-      startSocket: "right",
-      endSocket: "left",
-    };
-    const lineStyle2 = {
-      color: "#134BEA",
-      size: 2,
-      path: "straight",
-      startPlug: "arrow1",
-      endPlug: "arrow1",
-      startSocket: "right",
-      endSocket: "left",
-    };
-    const lineStyleRight0 = {
-      color: "#51637F",
-      size: 2,
-      path: "straight",
-      startPlug: "arrow1",
-      endPlug: "behind",
-      startSocket: "left",
-      endSocket: "right",
-    };
-    const lineStyleRight1 = {
-      color: "#51637F",
-      size: 2,
-      path: "straight",
-      endPlug: "arrow1",
-      startSocket: "left",
-      endSocket: "right",
-    };
-    const lineStyleRight2 = {
-      color: "#134BEA",
-      size: 2,
-      path: "straight",
-      startPlug: "arrow1",
-      endPlug: "arrow1",
-      startSocket: "left",
-      endSocket: "right",
-    };
-    const startDom = document.getElementById("end");
-    //循环画线
-    for (const [key, value] of domList.value) {
-      const endDom = value;
-      let line;
-      if (key.ref_type == 0) {
-        line = new LeaderLine(endDom, startDom, lineStyle0);
-      } else if (key.ref_type == 1) {
-        line = new LeaderLine(endDom, startDom, lineStyle1);
-      } else if (key.ref_type == 2) {
-        line = new LeaderLine(endDom, startDom, lineStyle2);
-      }
-      //  保存进数组,方便进行遍历删除
-      leaderLines.value.push(line);
+  });
+};
+watch(
+  () => props.checkData,
+  (newValue, oldV) => {
+    listData.value = newValue;
+    if (newValue && leaderLines.value.length > 0) {
+      // leaderLines.value.forEach((line) => line.remove()); //清除连线
+      leaderLines.value = [];
     }
-    //循环画线右侧
-    for (const [key, value] of domListRight.value) {
-      const endDom = value;
-      let line2;
-      if (key.ref_type == 0) {
-        line2 = new LeaderLine(endDom, startDom, lineStyleRight0);
-      } else if (key.ref_type == 1) {
-        line2 = new LeaderLine(endDom, startDom, lineStyleRight1);
-      } else if (key.ref_type == 2) {
-        line2 = new LeaderLine(endDom, startDom, lineStyleRight2);
-      }
-      //  保存进数组,方便进行遍历删除
-      leaderLines.value.push(line2);
+  },
+  { deep: true }
+);
+watch(
+  () => listData.value,
+  (newValue) => {
+    emit("result", newValue);
+    clickResetLine();
+  }
+);
+watch(
+  () => props.isOpen,
+  (newValue) => {
+    if (newValue) {
+      domList.value.clear();
+      domListRight.value.clear();
+      leaderLines.value = [];
     }
-    hiddenLine();
-  };
-  //设置中间盒子的所在位置
-  const middleLinePosition = () => {
-    setTimeout(() => {
-      const heights = myElement.value.scrollHeight;
-      if (leftList.value.length > 3 || rightList.value.length > 3) {
-        middleElement.value.style.marginTop = `${(heights - 60) / 2}px`; // 设置元素的垂直位置
-      } else {
-        middleElement.value.style.marginTop = "150px"; // 设置元素的垂直位置
-      }
-    }, 0);
-  };
-  onMounted(() => {
     nextTick(() => {
-      setLine();
       middleLinePosition();
-      nextTick(() => {
-        newPositionLine();
-      });
+      removeLine();
     });
-  });
-  //滚动时重定位线条
-  const newPositionLine = () => {
-    document.getElementById("treedom").addEventListener(
-      "scroll",
-      AnimEvent.add(() => {
-        leaderLines.value.forEach((line) => {
-          hiddenLine();
-          line.position();
-          line.positionByWindowResize = false;
-        });
-        //中间展示图片的
-      }),
-      false
-    );
+  }
+);
+//点击后重置数据和线条
+const clickResetLine = () => {
+  domList.value.clear();
+  domListRight.value.clear();
+  leaderLines.value = [];
+  middleLinePosition();
+  setLine();
+  removeLine();
+};
+// 将设备列表分成两份
+const bothSide = (data) => {
+  const formatArr = processArray(data);
+  const arrlenght = formatArr.length;
+  const long1 = Math.ceil(arrlenght / 2);
+  leftList.value = formatArr.splice(0, long1);
+  rightList.value = formatArr.splice(0);
+};
+
+const setLeaderline = () => {
+  // lineArr.value = [];
+  //线条样式
+  const lineStyle0 = {
+    color: "#51637F",
+    size: 2,
+    path: "straight",
+    startPlug: "arrow1",
+    endPlug: "behind",
+    startSocket: "right",
+    endSocket: "left",
   };
-  //弹窗打开后使得线条在指定区域中
-  const hiddenLine = () => {
-    const elmWrapper = document.getElementById("wrapper");
-    // 移动 line
-    document.body.querySelectorAll("body .leader-line").forEach((node) => {
-      elmWrapper.appendChild(node);
-    });
-    elmWrapper.style.transform = "none";
-    var rectWrapper = elmWrapper.getBoundingClientRect();
-    // Move to the origin of coordinates as the document
-    elmWrapper.style.transform = `translate(${
-      (rectWrapper.left + window.scrollY) * -1
-    }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
+  const lineStyle1 = {
+    color: "#51637F",
+    size: 2,
+    path: "straight",
+    endPlug: "arrow1",
+    startSocket: "right",
+    endSocket: "left",
   };
-  const setLine = () => {
-    if (listData.value) {
-      bothSide(listData.value.list);
-    }
-    setTimeout(() => {
-      setLeaderline();
-    }, 30);
+  const lineStyle2 = {
+    color: "#134BEA",
+    size: 2,
+    path: "straight",
+    startPlug: "arrow1",
+    endPlug: "arrow1",
+    startSocket: "right",
+    endSocket: "left",
   };
-  const removeLine = () => {
-    const elmWrapper = document.getElementById("wrapper");
-    document.body.querySelectorAll("body .leader-line").forEach((node) => {
-      elmWrapper.removeChild(node);
-    });
+  const lineStyleRight0 = {
+    color: "#51637F",
+    size: 2,
+    path: "straight",
+    startPlug: "arrow1",
+    endPlug: "behind",
+    startSocket: "left",
+    endSocket: "right",
   };
-  </script>
-  <style lang="scss">
-  @mixin img-size {
-    width: 150px;
-    height: 90px;
-    margin-bottom: 10px;
-  }
-  @mixin left-and-right {
-    display: flex;
-    flex-direction: column;
-  }
-  .main-cont {
-    margin-top: 60px;
-    display: flex;
-    justify-content: space-evenly;
-  }
-  
-  .leader-line {
-    z-index: 3000;
+  const lineStyleRight1 = {
+    color: "#51637F",
+    size: 2,
+    path: "straight",
+    endPlug: "arrow1",
+    startSocket: "left",
+    endSocket: "right",
+  };
+  const lineStyleRight2 = {
+    color: "#134BEA",
+    size: 2,
+    path: "straight",
+    startPlug: "arrow1",
+    endPlug: "arrow1",
+    startSocket: "left",
+    endSocket: "right",
+  };
+  const startDom = document.getElementById("end");
+  let count = 56;
+  //循环画线
+  for (const [key, value] of domList.value) {
+    const endDom = value;
+    let line;
+    count += 5;
+    if (key.ref_type == 0) {
+      line = new LeaderLine(
+        endDom,
+        LeaderLine.pointAnchor(startDom, { x: 0, y: count }),
+        lineStyle0
+      );
+    } else if (key.ref_type == 1) {
+      line = new LeaderLine(
+        endDom,
+        LeaderLine.pointAnchor(startDom, { x: 0, y: count }),
+        lineStyle1
+      );
+    } else if (key.ref_type == 2) {
+      line = new LeaderLine(
+        endDom,
+        LeaderLine.pointAnchor(startDom, { x: 0, y: count }),
+        lineStyle2
+      );
+    }
+    //  保存进数组,方便进行遍历删除
+    leaderLines.value.push(line);
   }
-  .main-left {
-    display: flex;
-    @include left-and-right;
-    .img-item {
-      @include img-size;
+  let count2 = 56;
+  //循环画线右侧
+  for (const [key, value] of domListRight.value) {
+    const endDom = value;
+    let line2;
+    count2 += 5;
+    if (key.ref_type == 0) {
+      line2 = new LeaderLine(
+        endDom,
+        LeaderLine.pointAnchor(startDom, { x: "100%", y: count2 }),
+        lineStyleRight0
+      );
+    } else if (key.ref_type == 1) {
+      line2 = new LeaderLine(
+        endDom,
+        LeaderLine.pointAnchor(startDom, { x: "100%", y: count2 }),
+        lineStyleRight1
+      );
+    } else if (key.ref_type == 2) {
+      line2 = new LeaderLine(
+        endDom,
+        LeaderLine.pointAnchor(startDom, { x: "100%", y: count2 }),
+        lineStyleRight2
+      );
     }
+    //  保存进数组,方便进行遍历删除
+    leaderLines.value.push(line2);
   }
-  .main-middle {
-    box-sizing: border-box;
-    img {
-      margin-bottom: 10px;
+  hiddenLine();
+};
+//设置中间盒子的所在位置
+const middleLinePosition = () => {
+  setTimeout(() => {
+    const heights = myElement.value.scrollHeight;
+    const leftListLength = leftList.value.length;
+    const rightListLength = rightList.value.length;
+    const setElementMarginTop = (element, value) => {
+      element.value.style.marginTop = `${value}px`;
+    };
+    if (leftList.value.length > 3 || rightList.value.length > 3) {
+      middleElement.value.style.marginTop = `${(heights - 60) / 2}px`; // 设置元素的垂直位置
+    } else {
+      setElementMarginTop(leftElement, 0);
+      setElementMarginTop(rightElement, 0);
+      setElementMarginTop(middleElement, 150);
     }
-    .middle-item {
-      @include left-and-right;
-      align-items: center;
-      color: #ffcb11;
+    if (rightListLength == 1) {
+      setElementMarginTop(rightElement, 165);
     }
-  }
-  .main-right {
-    display: flex;
-    @include left-and-right;
-    .img-item {
-      @include img-size;
+    if (leftListLength == 1) {
+      setElementMarginTop(leftElement, 165);
     }
+  }, 0);
+};
+onMounted(() => {
+  nextTick(() => {
+    setLine();
+    middleLinePosition();
+    nextTick(() => {
+      newPositionLine();
+    });
+  });
+});
+//滚动时重定位线条
+const newPositionLine = () => {
+  document.getElementById("treedom").addEventListener(
+    "scroll",
+    AnimEvent.add(() => {
+      leaderLines.value.forEach((line) => {
+        hiddenLine();
+        line.position();
+        line.positionByWindowResize = false;
+      });
+    }),
+    false
+  );
+  window.addEventListener(
+    "resize",
+    AnimEvent.add(function () {
+      leaderLines.value.forEach((line) => {
+        hiddenLine();
+        line.position();
+        line.positionByWindowResize = false;
+      });
+    }),
+    false
+  );
+};
+//弹窗打开后使得线条在指定区域中
+const hiddenLine = () => {
+  const elmWrapper = document.getElementById("wrapper");
+  // 移动 line
+  document.body.querySelectorAll("body .leader-line").forEach((node) => {
+    elmWrapper.appendChild(node);
+  });
+  elmWrapper.style.transform = "none";
+  var rectWrapper = elmWrapper.getBoundingClientRect();
+  // Move to the origin of coordinates as the document
+  elmWrapper.style.transform = `translate(${
+    (rectWrapper.left + window.scrollY) * -1
+  }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
+};
+const setLine = () => {
+  if (listData.value) {
+    bothSide(listData.value.list);
   }
-  
-  .cont {
+  setTimeout(() => {
+    setLeaderline();
+  }, 200);
+};
+const removeLine = () => {
+  const elmWrapper = document.getElementById("wrapper");
+  document.body.querySelectorAll("body .leader-line").forEach((node) => {
+    elmWrapper.removeChild(node);
+  });
+};
+</script>
+  <style lang="scss">
+@mixin img-size {
+  width: 150px;
+  height: 90px;
+  margin-bottom: 10px;
+}
+@mixin left-and-right {
+  display: flex;
+  flex-direction: column;
+}
+.main-cont {
+  margin-top: 60px;
+  display: flex;
+  justify-content: space-evenly;
+}
+
+.leader-line {
+  z-index: 3000;
+}
+.main-left {
+  display: flex;
+  @include left-and-right;
+  .img-item {
+    @include img-size;
+  }
+}
+.main-middle {
+  box-sizing: border-box;
+  img {
+    margin-bottom: 10px;
+  }
+  .middle-item {
     @include left-and-right;
     align-items: center;
-    margin-bottom: 10px;
-    .ied-desc {
-      color: #255ce7;
-    }
+    color: #ffcb11;
+  }
+}
+.main-right {
+  display: flex;
+  @include left-and-right;
+  .img-item {
+    @include img-size;
   }
-  
-  #wrapper {
-    width: 0;
-    height: 0;
-    position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
+}
+
+.cont {
+  @include left-and-right;
+  align-items: center;
+  margin-bottom: 10px;
+  .ied-desc {
+    color: #255ce7;
   }
-  </style>
+}
+
+#wrapper {
+  width: 0;
+  height: 0;
+  position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
+}
+</style>

+ 6 - 6
src/pages/netStructPicture/components/scdVisual.vue

@@ -161,7 +161,7 @@ import scdDialogIndex from "./scdDialogIndex";
 const userStoreCode = useDataStore();
 const data = reactive({
   queryParams: {
-    scd_id: 568000158,
+    scd_id: 588000164,
   },
 });
 const loading = ref(true);
@@ -171,7 +171,7 @@ const { queryParams } = toRefs(data);
 // 表单重置
 const reset = () => {
   queryParams.value = {
-    scd_id: 568000158,
+    scd_id: 588000164,
     voltage_level_id: null, //电压等级
     area_id: null, //间隔
     device_type_id: null, //装置类型
@@ -185,7 +185,7 @@ const allIedType = [{ name: "全部", code: "alls" }];
 const voltageLevel = ref([{ name: "全部", id: "alls" }]); //电压等级
 const areaType = ref([]);
 const getArea = async () => {
-  const areaRes = await areaList({ scd_id: 568000158 });
+  const areaRes = await areaList({ scd_id: 588000164 });
   if (!areaRes.data) {
     voltageLevel.value = [];
     loading.value = false;
@@ -223,7 +223,7 @@ const getArea = async () => {
 //设备类型
 const iedTypeData = ref([]);
 const getTypelist = async () => {
-  const typeRes = await iedTypelist({ scd_id: 568000158 });
+  const typeRes = await iedTypelist({ scd_id: 588000164 });
   iedTypeData.value = typeRes.data ? [...allIedType, ...typeRes.data] : [];
 };
 const iedName = ref([]);
@@ -254,7 +254,7 @@ const searchInput = (value) => {
 const count = ref(0);
 const iedNameData = async () => {
   //IED编码或名称
-  const iedRes = await scdIedRelation({ scd_id: 568000158 });
+  const iedRes = await scdIedRelation({ scd_id: 588000164 });
   iedName.value = iedRes.data;
   count.value = iedRes.count;
 };
@@ -282,7 +282,7 @@ const changeLevel = async (value, mainValue) => {
     open.value = true;
     dialogData.value = iedName.value;
   } else if (value) {
-    const mainClick = { scd_id: 568000158, area_id: value };
+    const mainClick = { scd_id: 588000164, area_id: value };
     const forms = mainValue ? mainClick : queryParams.value;
     open.value = true;
     dialogData.value = [];