basicInfo.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. <template>
  2. <div id="treedom4" v-loading="loading">
  3. <div style="position: relative">
  4. <div class="nav" id="topLine">
  5. <div
  6. class="nav-cont"
  7. v-for="(item, index) in navList"
  8. :key="index"
  9. @click="clickNav(item)"
  10. >
  11. <img :src="cylinder" alt="" class="nav-img" />
  12. <div>{{ item.attr_name }}</div>
  13. <div class="describe-text">{{ `(${item.attr_desc})` }}</div>
  14. </div>
  15. </div>
  16. </div>
  17. <div class="wrapper">
  18. <div class="grid">
  19. <!-- 左侧 -->
  20. <div
  21. class="col fluid"
  22. :class="{ transp: mainTitle && mainTitle.length < 2 }"
  23. style="margin-left: 20px"
  24. id="leftLine"
  25. >
  26. <div v-if="mainTitle && mainTitle.length > 1">
  27. <div class="title">
  28. {{ mainTitle[1].attr_name
  29. }}<span v-if="mainTitle[0].attr_desc">{{
  30. `(${mainTitle[1].attr_desc})`
  31. }}</span>
  32. </div>
  33. <div class="attr-desc" v-if="moLeft">
  34. <div>
  35. <span class="decrip">MAC-Address:</span>
  36. <span class="decrip-item" v-if="!moLeft.address">无</span>
  37. <span v-else>{{ moLeft.address }}</span>
  38. </div>
  39. <div>
  40. <span class="decrip">VLAN-PRIORITY:</span>
  41. <span class="decrip-item" v-if="!moLeft.priority">无</span>
  42. <span v-else>{{ moLeft.priority }}</span>
  43. </div>
  44. <div>
  45. <span class="decrip">APPID:</span>
  46. <span class="decrip-item" v-if="!moLeft.APPID">无</span>
  47. <span v-else>{{ moLeft.APPID }}</span>
  48. </div>
  49. <div>
  50. <span class="decrip">VLAN-ID:</span>
  51. <span class="decrip-item" v-if="!moLeft.vlanId">无</span>
  52. <span v-else>{{ moLeft.vlanId }}</span>
  53. </div>
  54. </div>
  55. <div v-if="mainList" class="circle-all">
  56. <span
  57. v-for="(item, index) in mainTitle[1].list"
  58. :key="index"
  59. @click="clickCircel1(item, index, 'moLeft')"
  60. ><span
  61. class="circel"
  62. :class="{ 'circel active-circel': index == activeCircel1 }"
  63. v-if="item.address_json != ''"
  64. >{{ index + 1 }}</span
  65. ></span
  66. >
  67. </div>
  68. </div>
  69. <div class="child-item" v-if="mainTitle && mainTitle.length > 1">
  70. <div class="ldevice">LDevice</div>
  71. <div
  72. v-for="(item, index) in mainTitle[1].childList[0]"
  73. :key="index"
  74. @click="clickMain(item)"
  75. class="ldevice-cont"
  76. >
  77. <img :src="legislation" alt="" />
  78. <div class="img-title">{{ item.attr_inst }}</div>
  79. <div class="decrip-child">{{ item.attr_desc }}</div>
  80. </div>
  81. </div>
  82. </div>
  83. <!-- 中间 -->
  84. <div class="col main-middle" id="middleLine">
  85. <div v-if="attrsData">
  86. <el-tooltip
  87. class="box-item"
  88. effect="light"
  89. :content="attrsData.desc"
  90. placement="top-start"
  91. >
  92. <div class="text-overflow ied_struct_desc">
  93. {{ attrsData.desc }}
  94. </div>
  95. </el-tooltip>
  96. <el-tooltip
  97. class="box-item"
  98. effect="light"
  99. :content="attrsData.type"
  100. placement="top-start"
  101. >
  102. <div class="text-overflow ied_struct_type">
  103. {{ attrsData.type }}
  104. </div>
  105. </el-tooltip>
  106. <el-tooltip
  107. class="box-item"
  108. effect="light"
  109. :content="attrsData.manufacturer"
  110. placement="top-start"
  111. >
  112. <div class="text-overflow ied_struct_manufacturer">
  113. {{ attrsData.manufacturer }}
  114. </div>
  115. </el-tooltip>
  116. <el-tooltip
  117. class="box-item"
  118. effect="light"
  119. :content="attrsData.name"
  120. placement="top-start"
  121. >
  122. <div
  123. class="text-overflow ied_struct_manufacturer ied_struct_manufacturer1"
  124. >
  125. {{ attrsData.name }}
  126. </div>
  127. </el-tooltip>
  128. </div>
  129. </div>
  130. <!-- 右侧 -->
  131. <div
  132. class="col fluid"
  133. style="margin-right: 20px"
  134. :class="{ transp: mainTitle && mainTitle.length < 3 }"
  135. id="rightLine"
  136. >
  137. <div v-if="mainTitle && mainTitle.length > 2">
  138. <div class="title">
  139. {{ mainTitle[2].attr_name
  140. }}<span v-if="mainTitle[0].attr_desc">{{
  141. `(${mainTitle[2].attr_desc})`
  142. }}</span>
  143. </div>
  144. <div class="attr-desc" v-if="moRight">
  145. <div>
  146. <span class="decrip">MAC-Address:</span>
  147. <span class="decrip-item" v-if="!moRight.address">无</span>
  148. <span v-else>{{ moRight.address }}</span>
  149. </div>
  150. <div>
  151. <span class="decrip">VLAN-PRIORITY:</span>
  152. <span class="decrip-item" v-if="!moRight.priority">无</span>
  153. <span v-else>{{ moRight.priority }}</span>
  154. </div>
  155. <div>
  156. <span class="decrip">APPID:</span>
  157. <span class="decrip-item" v-if="!moRight.APPID">无</span>
  158. <span v-else>{{ moRight.APPID }}</span>
  159. </div>
  160. <div>
  161. <span class="decrip">VLAN-ID:</span>
  162. <span class="decrip-item" v-if="!moRight.vlanId">无</span>
  163. <span v-else>{{ moRight.vlanId }}</span>
  164. </div>
  165. </div>
  166. <div v-if="mainList" class="circle-all">
  167. <span
  168. v-for="(item, index) in mainTitle[2].list"
  169. :key="index"
  170. @click="clickCircel2(item, index, 'moRight')"
  171. ><span
  172. class="circel"
  173. :class="{ 'circel active-circel': index == activeCircel2 }"
  174. v-if="item.address_json != ''"
  175. >{{ index + 1 }}</span
  176. ></span
  177. >
  178. </div>
  179. </div>
  180. <div class="child-item" v-if="mainTitle && mainTitle.length > 2">
  181. <div class="ldevice">LDevice</div>
  182. <div
  183. v-for="(item, index) in mainTitle[2].childList[0]"
  184. :key="index"
  185. @click="clickMain(item)"
  186. class="ldevice-cont"
  187. >
  188. <img :src="legislation" alt="" />
  189. <div class="img-title">{{ item.attr_inst }}</div>
  190. <div class="decrip-child">{{ item.attr_desc }}</div>
  191. </div>
  192. </div>
  193. </div>
  194. </div>
  195. <div
  196. class="main-bottom"
  197. id="bottomLine"
  198. :class="{ transp: mainTitle && mainTitle.length < 1 }"
  199. >
  200. <div v-if="mainTitle && mainTitle.length > 0">
  201. <div class="title">
  202. {{ mainTitle[0].attr_name
  203. }}<span v-if="mainTitle[0].attr_desc">{{
  204. `(${mainTitle[0].attr_desc})`
  205. }}</span>
  206. </div>
  207. <div class="attr-desc" v-if="moBottom">
  208. <div>
  209. <span class="decrip">MAC-Address:</span>
  210. <span class="decrip-item" v-if="!moBottom.address">无</span>
  211. <span v-else>{{ moBottom.address }}</span>
  212. </div>
  213. <div>
  214. <span class="decrip">VLAN-PRIORITY:</span>
  215. <span class="decrip-item" v-if="!moBottom.priority">无</span>
  216. <span v-else>{{ moBottom.priority }}</span>
  217. </div>
  218. <div>
  219. <span class="decrip">APPID:</span>
  220. <span class="decrip-item" v-if="!moBottom.APPID">无</span>
  221. <span v-else>{{ moBottom.APPID }}</span>
  222. </div>
  223. <div>
  224. <span class="decrip">VLAN-ID:</span>
  225. <span class="decrip-item" v-if="!moBottom.vlanId">无</span>
  226. <span v-else>{{ moBottom.vlanId }}</span>
  227. </div>
  228. </div>
  229. <div v-if="mainList" class="circle-all">
  230. <span
  231. v-for="(item, index) in mainTitle[0].list"
  232. :key="index"
  233. @click="clickCircel3(item, index, 'moBottom')"
  234. ><span
  235. class="circel"
  236. :class="{ 'circel active-circel': index == activeCircel3 }"
  237. v-if="item.address_json != ''"
  238. >{{ index + 1 }}</span
  239. ></span
  240. >
  241. </div>
  242. </div>
  243. <div class="child-item" v-if="mainTitle && mainTitle.length > 0">
  244. <div class="ldevice">LDevice</div>
  245. <div
  246. class="ldevice-cont"
  247. v-for="(item, index) in mainTitle[0].childList[0]"
  248. :key="index"
  249. @click="clickMain(item)"
  250. >
  251. <img :src="legislation" alt="" />
  252. <div class="img-title">{{ item.attr_inst }}</div>
  253. <div class="decrip-child">{{ item.attr_desc }}</div>
  254. </div>
  255. </div>
  256. </div>
  257. </div>
  258. <div id="wrappers"></div>
  259. <!-- 点击头部的弹框 -->
  260. <el-dialog
  261. @close="cancelClickNav"
  262. v-model="isOpennav"
  263. append-to-body
  264. draggable
  265. style="height: 550px"
  266. >
  267. <template #header>
  268. <div class="my-header">
  269. <div class="dialog-nav-title">
  270. {{ `(${clickNavTitle.attr_desc}) — FCDA列表` }}
  271. </div>
  272. </div>
  273. </template>
  274. <el-table
  275. :data="clickNavData"
  276. style="width: 100%"
  277. stripe
  278. height="450"
  279. :cell-style="{ color: '#000' }"
  280. >
  281. <el-table-column prop="attr_ld_inst" label="ldInst" />
  282. <el-table-column prop="attr_prefix" label="prefix" />
  283. <el-table-column prop="attr_ln_class" label="lnClass" />
  284. <el-table-column prop="attr_ln_inst" label="lnInst" />
  285. <el-table-column prop="attr_do_name" label="doName" />
  286. <el-table-column prop="da_datatype" label="attr_da_name" width="180" />
  287. <el-table-column prop="attr_fc" label="fc" />
  288. </el-table>
  289. </el-dialog>
  290. <!-- 点击方框的弹窗 -->
  291. <el-dialog
  292. @close="cancelClickMain"
  293. v-model="isOpenMain"
  294. append-to-body
  295. draggable
  296. style="height: 550px"
  297. >
  298. <template #header>
  299. <div class="my-header">
  300. <div class="dialog-nav-title">
  301. {{
  302. `${clickMainTitle.attr_inst}${clickMainTitle.attr_desc} — LN/LN0节点列表`
  303. }}
  304. </div>
  305. </div>
  306. </template>
  307. <el-table
  308. :data="clickMainData"
  309. style="width: 100%"
  310. stripe
  311. height="450"
  312. :cell-style="{ color: '#000' }"
  313. >
  314. <el-table-column type="index" label="序号" width="80" />
  315. <el-table-column prop="attr_inst" label="inst" />
  316. <el-table-column prop="attr_ln_class" label="lnClass" />
  317. <el-table-column prop="attr_ln_type" label="lnType" />
  318. <el-table-column prop="attr_desc" label="desc" />
  319. </el-table>
  320. </el-dialog>
  321. </div>
  322. </template>
  323. <script setup>
  324. import { defineProps, onMounted, ref, inject, nextTick, watch } from "vue";
  325. import legislation from "@/assets/image/instruct/legislation.png";
  326. import cylinder from "@/assets/image/instruct/cylinder.png";
  327. import {
  328. getNodeList,
  329. getNetworkInfo,
  330. getLdeviceList,
  331. nodeList,
  332. getNodeAttrs,
  333. } from "@/api/iedNetwork";
  334. import LeaderLine from "../../../../public/leader-line.min.js";
  335. import AnimEvent from "../../../../public/anim-event.min.js";
  336. import { CloseBold } from "@element-plus/icons-vue";
  337. import { useRoute } from "vue-router";
  338. const route = useRoute();
  339. const props = defineProps({
  340. checkData: {
  341. type: Object,
  342. default: () => {},
  343. },
  344. isOpen: {
  345. type: Boolean,
  346. default: false,
  347. },
  348. delScdId:{
  349. type:String,
  350. default: '',
  351. }
  352. });
  353. const navList = ref(null); //最头部的数据
  354. const mainTitle = ref(null); //每个方框的标题
  355. const moBottom = ref(null); //底部方框所展示的MAC-Address等desc
  356. const moLeft = ref(null); //左侧方框所展示的MAC-Address等desc
  357. const moRight = ref(null); //右侧方框所展示的MAC-Address等desc
  358. const activeCircel1 = ref(0); //点击数字圆圈的样式
  359. const activeCircel2 = ref(0); //点击数字圆圈的样式
  360. const activeCircel3 = ref(0); //点击数字圆圈的样式
  361. const isOpennav = ref(false); //头部点击弹窗显示
  362. const clickNavTitle = ref(null); //头部点击弹窗数据
  363. const clickNavData = ref(null); //头部点击弹窗数据
  364. const isOpenMain = ref(false); //点击方框
  365. const clickMainTitle = ref(null);
  366. const clickMainData = ref(null);
  367. const loading = ref(true);
  368. const getNav = async () => {
  369. const navRes = await getNodeList({
  370. scd_id: scdIdValue,
  371. pagesize: 10000,
  372. ied_name: props.checkData.ied_name,
  373. name: "DataSet",
  374. });
  375. navList.value = navRes.data;
  376. };
  377. const getMainTitle = async () => {
  378. const mainRes = await getNodeList({
  379. scd_id: scdIdValue,
  380. pagesize: 10000,
  381. ied_name: props.checkData.ied_name,
  382. name: "AccessPoint",
  383. });
  384. //得到每个方框中LDevice中的内容
  385. Promise.all(
  386. mainRes.data.map(async (item) => {
  387. item.childList = [];
  388. const res = await getLdeviceList({
  389. accessPointId: item.node_id,
  390. scd_id: scdIdValue,
  391. });
  392. item.childList.push(res.data);
  393. })
  394. ).then(() => {
  395. //等待执行完上面的api
  396. loading.value = false;
  397. mainTitle.value = mainRes.data;
  398. getMainList();
  399. });
  400. };
  401. const mainList = ref({});
  402. const titleName = ref([]);
  403. //几个方框的数据
  404. const getMainList = async () => {
  405. mainList.value = {};
  406. titleName.value = [];
  407. const newarr = [];
  408. const infoRes = await getNetworkInfo({
  409. scd_id: scdIdValue,
  410. ied_name: props.checkData.ied_name,
  411. });
  412. //处理分类数据
  413. for (let i = 0; i < infoRes.data.length; i++) {
  414. if (infoRes.data[i].address_json != "") {
  415. let newData = infoRes.data[i].address_json
  416. .replace("MAC-Address", "address")
  417. .replace("VLAN-PRIORITY", "priority")
  418. .replace("VLAN-ID", "vlanId");
  419. infoRes.data[i].address_json = JSON.parse(newData);
  420. }
  421. let item = infoRes.data[i];
  422. const key = item.ap_name;
  423. newarr.push(key);
  424. if (mainList.value[key] == null) {
  425. mainList.value[key] = {
  426. name: key,
  427. list: [item],
  428. };
  429. } else {
  430. mainList.value[key].list.push(item);
  431. }
  432. }
  433. //处理表头下方段落的描述
  434. if (mainList.value && mainTitle.value) {
  435. mainTitle.value.forEach((key) => {
  436. key.list = [];
  437. Object.keys(mainList.value).forEach((item) => {
  438. if (item == key.attr_name) {
  439. key.list = mainList.value[item].list;
  440. }
  441. });
  442. });
  443. //分布默认的左侧右侧和下侧的数据
  444. for (let i = 0; i < mainTitle.value.length; i++) {
  445. if (
  446. mainTitle.value[i].list.length > 0 &&
  447. mainTitle.value[i].list[0].address_json != ""
  448. ) {
  449. const targetElement = mainTitle.value[i];
  450. switch (i) {
  451. case 0:
  452. moBottom.value = targetElement.list[0].address_json;
  453. break;
  454. case 1:
  455. moLeft.value = targetElement.list[0].address_json;
  456. break;
  457. case 2:
  458. moRight.value = targetElement.list[0].address_json;
  459. break;
  460. }
  461. }
  462. }
  463. }
  464. };
  465. //弹窗打开后使得线条在指定区域中
  466. const hiddenLine2 = () => {
  467. const elmWrapper = document.getElementById("wrappers");
  468. if(!elmWrapper) return;
  469. // 移动 line
  470. document.body.querySelectorAll("body .leader-line").forEach((node) => {
  471. elmWrapper.appendChild(node);
  472. });
  473. elmWrapper.style.transform = "none";
  474. var rectWrapper = elmWrapper.getBoundingClientRect();
  475. elmWrapper.style.transform = `translate(${
  476. (rectWrapper.left + window.scrollY) * -1
  477. }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
  478. };
  479. const leaderLines = ref([]); //控制线条显示
  480. //滚动时重定位线条
  481. const newPositionLine2 = () => {
  482. document.getElementById("treedom4").addEventListener(
  483. "scroll",
  484. AnimEvent.add(() => {
  485. leaderLines.value.forEach((line) => {
  486. if (line) {
  487. hiddenLine2();
  488. line.position();
  489. line.positionByWindowResize = false;
  490. }
  491. });
  492. //中间展示图片的
  493. }),
  494. false
  495. );
  496. document.getElementById("treedom4").addEventListener(
  497. "resize",
  498. AnimEvent.add(function () {
  499. leaderLines.value.forEach((line) => {
  500. hiddenLine2();
  501. line.position();
  502. line.positionByWindowResize = false;
  503. });
  504. }),
  505. false
  506. );
  507. };
  508. const getLine = () => {
  509. const topDom = document.getElementById("topLine");
  510. const leftDom = document.getElementById("leftLine");
  511. const rightDom = document.getElementById("rightLine");
  512. const bottomDom = document.getElementById("bottomLine");
  513. const middlDom = document.getElementById("middleLine");
  514. let lineStyle = {
  515. color: "#134BEA",
  516. size: 2,
  517. path: "straight",
  518. endPlug: "disc",
  519. startPlug: "disc",
  520. middleLabel: LeaderLine.captionLabel("AccessPoint", {
  521. fontSize: 10,
  522. color: "#7F8EB2",
  523. }),
  524. };
  525. let lineStyleTop = {
  526. ...lineStyle,
  527. middleLabel: LeaderLine.captionLabel({
  528. text: "DataSet",
  529. fontSize: 10,
  530. color: "#7F8EB2",
  531. }),
  532. };
  533. let lineStyleright = {
  534. ...lineStyle,
  535. middleLabel: LeaderLine.captionLabel("AccessPoint", {
  536. fontSize: 10,
  537. color: "#7F8EB2",
  538. }),
  539. };
  540. let lineStylebottom = {
  541. ...lineStyle,
  542. middleLabel: LeaderLine.captionLabel({
  543. text: "AccessPoint",
  544. fontSize: 10,
  545. color: "#7F8EB2",
  546. }),
  547. };
  548. LeaderLine.positionByWindowResize = false;
  549. leaderLines.value.push(new LeaderLine(middlDom, topDom, lineStyleTop)); //上面和中间连线
  550. if (mainTitle.value && mainTitle.value.length > 0) {
  551. leaderLines.value.push(
  552. new LeaderLine(middlDom, bottomDom, lineStylebottom)
  553. );
  554. }
  555. if (mainTitle.value && mainTitle.value.length > 2) {
  556. leaderLines.value.push(new LeaderLine(middlDom, rightDom, lineStyleright));
  557. }
  558. if (mainTitle.value && mainTitle.value.length > 1) {
  559. leaderLines.value.push(new LeaderLine(leftDom, middlDom, lineStyle));
  560. }
  561. newPositionLine2();
  562. hiddenLine2();
  563. };
  564. //点击数字
  565. const clickCircel1 = (item, index, type) => {
  566. commonClickCircel(item, index, type,1);
  567. };
  568. const clickCircel2 = (item, index, type) => {
  569. commonClickCircel(item, index, type,2);
  570. };
  571. const clickCircel3 = (item, index, type) => {
  572. commonClickCircel(item, index, type,3);
  573. };
  574. const commonClickCircel = (item, index, type,num) => {
  575. switch(num){
  576. case 1:
  577. activeCircel1.value = index;
  578. break;
  579. case 2:
  580. activeCircel2.value = index;
  581. break;
  582. case 3:
  583. activeCircel3.value = index;
  584. break;
  585. }
  586. let data = JSON.stringify(item.address_json);
  587. let newData = data
  588. .replace("MAC-Address", "address")
  589. .replace("VLAN-PRIORITY", "priority")
  590. .replace("VLAN-ID", "vlanId");
  591. if (type == "moBottom") {
  592. moBottom.value = JSON.parse(newData);
  593. } else if (type == "moRight") {
  594. moRight.value = JSON.parse(newData);
  595. } else {
  596. moLeft.value = JSON.parse(newData);
  597. }
  598. };
  599. const attrsData = ref(null);
  600. const getNode = async () => {
  601. const attrRes = await getNodeAttrs({
  602. scd_id: scdIdValue,
  603. ied_name: props.checkData.ied_name,
  604. node_id: props.checkData.node_id,
  605. });
  606. attrsData.value = attrRes.data;
  607. };
  608. let scdIdValue = '';
  609. onMounted(() => {
  610. if (props.delScdId) {
  611. scdIdValue = props.delScdId;
  612. } else {
  613. scdIdValue = route.query.id;
  614. }
  615. getNav();
  616. getMainTitle();
  617. getNode();
  618. nextTick(() => {
  619. setTimeout(() => {
  620. getLine();
  621. }, 500);
  622. });
  623. });
  624. watch(
  625. () => props.isOpen,
  626. (newValue) => {
  627. nextTick(() => {
  628. if (!newValue) {
  629. removeLine2();
  630. leaderLines.value = [];
  631. loading.value = false;
  632. } else {
  633. setTimeout(() => {
  634. getLine();
  635. }, 500);
  636. }
  637. });
  638. }
  639. );
  640. watch(
  641. () => props.checkData,
  642. (newValue) => {
  643. if (newValue) {
  644. removeLine2();
  645. if (leaderLines.value.length > 0) {
  646. leaderLines.value = [];
  647. }
  648. activeCircel1.value = 0;
  649. activeCircel2.value = 0;
  650. activeCircel3.value = 0;
  651. isOpenMain.value = false;
  652. isOpennav.value = false;
  653. getNav();
  654. loading.value = true;
  655. getMainTitle();
  656. getNode();
  657. nextTick(() => {
  658. setTimeout(() => {
  659. getLine();
  660. }, 500);
  661. });
  662. }
  663. }
  664. );
  665. const removeLine2 = () => {
  666. const elmWrapper = document.getElementById("wrappers");
  667. if (elmWrapper) {
  668. document.body.querySelectorAll("#wrappers .leader-line").forEach((node) => {
  669. elmWrapper.removeChild(node);
  670. });
  671. }
  672. };
  673. //点击头部展示的弹框
  674. const clickNav = async (item) => {
  675. clickNavTitle.value = item;
  676. isOpennav.value = true;
  677. const navRes = await nodeList({
  678. scd_id: scdIdValue,
  679. parent_node_id: item.node_id,
  680. pagesize: 10000,
  681. name: "FCDA",
  682. });
  683. clickNavData.value = navRes.data;
  684. };
  685. const cancelClickNav = () => {
  686. clickNavData.value = null;
  687. isOpennav.value = false;
  688. };
  689. const clickMain = async (item) => {
  690. clickMainTitle.value = item;
  691. isOpenMain.value = true;
  692. const navRes = await nodeList({
  693. scd_id: scdIdValue,
  694. parent_node_id: item.node_id,
  695. pagesize: 10000,
  696. name: "LN0",
  697. });
  698. const navRes2 = await nodeList({
  699. scd_id: scdIdValue,
  700. parent_node_id: item.node_id,
  701. pagesize: 10000,
  702. name: "LN",
  703. });
  704. clickMainData.value = [...navRes.data, ...navRes2.data];
  705. };
  706. const cancelClickMain = () => {
  707. clickMainData.value = null;
  708. isOpenMain.value = false;
  709. };
  710. </script>
  711. <style scoped lang="scss">
  712. #treedom4 {
  713. height: 72vh;
  714. overflow-y: auto;
  715. }
  716. .wrapper {
  717. position: relative;
  718. }
  719. .nav {
  720. height: 160px;
  721. background: #f3f5fa;
  722. overflow-y: auto;
  723. border: 2px dashed #a3ade0;
  724. display: flex;
  725. justify-content: start;
  726. flex-wrap: wrap;
  727. position: relative;
  728. margin: 16px;
  729. .nav-img {
  730. width: 30px;
  731. height: 30px;
  732. }
  733. .nav-cont {
  734. display: flex;
  735. flex-direction: column;
  736. align-items: center;
  737. cursor: pointer;
  738. margin: 8px 0;
  739. flex-basis: 14%;
  740. .describe-text {
  741. color: #134bea;
  742. }
  743. }
  744. }
  745. .main-bottom,
  746. .fluid {
  747. border: 2px dashed #a3ade0;
  748. background-color: #f7f8f8;
  749. display: flex;
  750. flex-direction: column;
  751. max-width: 36%;
  752. img {
  753. width: 40px;
  754. height: 40px;
  755. }
  756. .title {
  757. font-size: 16px;
  758. font-weight: bold;
  759. margin: 12px 0;
  760. text-align: center;
  761. }
  762. .attr-desc {
  763. margin: 10px;
  764. }
  765. .decrip {
  766. color: #7484ab;
  767. font-size: 14px;
  768. margin-right: 15px;
  769. width: 130px;
  770. display: inline-block;
  771. }
  772. .decrip-child {
  773. color: #7484ab;
  774. font-size: 14px;
  775. }
  776. .decrip-item {
  777. font-weight: bold;
  778. font-size: 14px;
  779. }
  780. .child-item {
  781. display: flex;
  782. margin: 12px;
  783. flex-wrap: wrap;
  784. border: 1px solid #5182ff;
  785. position: relative;
  786. & > div {
  787. margin: 8px;
  788. }
  789. .ldevice {
  790. position: absolute;
  791. top: -20px;
  792. left: -10px;
  793. padding: 0 4px;
  794. background: #5182ff;
  795. color: white;
  796. border-radius: 10px;
  797. }
  798. .ldevice-cont {
  799. display: flex;
  800. flex-direction: column;
  801. align-items: center;
  802. cursor: pointer;
  803. }
  804. }
  805. .img-title {
  806. color: #134bea;
  807. }
  808. }
  809. .circle-all {
  810. margin-bottom: 10px;
  811. display: flex;
  812. flex-wrap: wrap;
  813. }
  814. .circel {
  815. color: #7c58a8;
  816. display: inline-block;
  817. width: 20px;
  818. height: 20px;
  819. margin-bottom: 5px;
  820. margin-right: 5px;
  821. border: 1px solid #606c93;
  822. border-radius: 10px;
  823. text-align: center;
  824. line-height: 20px;
  825. margin-left: 0.5rem;
  826. cursor: pointer;
  827. }
  828. .active-circel {
  829. color: #134bea;
  830. border: 1px solid #134bea;
  831. }
  832. .Image {
  833. width: 193px;
  834. height: 150px;
  835. }
  836. /* 设置网格布局相关的样式 */
  837. .grid {
  838. display: flex;
  839. flex-wrap: nowrap;
  840. justify-content: space-between;
  841. align-items: center;
  842. margin-top: 50px;
  843. }
  844. .grid > .col {
  845. box-sizing: border-box;
  846. // padding: 10px;
  847. }
  848. /* 设置fixed2样式 */
  849. .main-middle {
  850. width: 160px;
  851. height: 160px;
  852. background: #fff url("~@/assets/image/instruct/network_slices.png") no-repeat
  853. center;
  854. background-size: 160px;
  855. position: relative;
  856. font-size: 12px;
  857. .text-overflow {
  858. overflow: hidden;
  859. text-overflow: ellipsis;
  860. white-space: nowrap;
  861. display: block;
  862. cursor: pointer;
  863. }
  864. .ied_struct_manufacturer {
  865. line-height: 2rem;
  866. transform: rotate(-33deg);
  867. top: 65%;
  868. position: absolute;
  869. left: 62%;
  870. border: 0px solid #cccccc1c;
  871. font-style: italic;
  872. font-size: 1rem;
  873. width: 6rem;
  874. text-align: center;
  875. }
  876. .ied_struct_manufacturer1 {
  877. top: 54%;
  878. left: 59%;
  879. }
  880. .ied_struct_desc {
  881. line-height: 2rem;
  882. position: absolute;
  883. transform: rotate(31deg);
  884. top: 15%;
  885. left: 32%;
  886. width: 59%;
  887. word-break: break-word;
  888. color: #134bea;
  889. font-weight: bold;
  890. font-style: italic;
  891. text-align: center;
  892. }
  893. .ied_struct_type {
  894. position: absolute;
  895. transform: rotate(31deg);
  896. top: 26%;
  897. left: 17%;
  898. color: #15010152;
  899. font-size: 1rem;
  900. font-style: italic;
  901. width: 60%;
  902. line-height: 1.5rem;
  903. text-align: center;
  904. }
  905. }
  906. /* 设置fluid样式 */
  907. .fluid {
  908. flex-grow: 1;
  909. }
  910. .transp {
  911. border: none;
  912. }
  913. .main-bottom {
  914. position: absolute;
  915. left: 50%;
  916. transform: translateX(-50%);
  917. margin-top: 40px;
  918. }
  919. .dialog-nav-title {
  920. color: #09162c;
  921. font-size: 16px;
  922. }
  923. </style>