basicInfo.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  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. const props = defineProps({
  338. checkData: {
  339. type: Object,
  340. default: () => {},
  341. },
  342. isOpen: {
  343. type: Boolean,
  344. default: false,
  345. },
  346. });
  347. const scdIdValue = inject("scdId");
  348. const navList = ref(null); //最头部的数据
  349. const mainTitle = ref(null); //每个方框的标题
  350. const moBottom = ref(null); //底部方框所展示的MAC-Address等desc
  351. const moLeft = ref(null); //左侧方框所展示的MAC-Address等desc
  352. const moRight = ref(null); //右侧方框所展示的MAC-Address等desc
  353. const activeCircel1 = ref(0); //点击数字圆圈的样式
  354. const activeCircel2 = ref(0); //点击数字圆圈的样式
  355. const activeCircel3 = ref(0); //点击数字圆圈的样式
  356. const isOpennav = ref(false); //头部点击弹窗显示
  357. const clickNavTitle = ref(null); //头部点击弹窗数据
  358. const clickNavData = ref(null); //头部点击弹窗数据
  359. const isOpenMain = ref(false); //点击方框
  360. const clickMainTitle = ref(null);
  361. const clickMainData = ref(null);
  362. const loading = ref(true);
  363. const getNav = async () => {
  364. const navRes = await getNodeList({
  365. scd_id: scdIdValue,
  366. pagesize: 10000,
  367. ied_name: props.checkData.ied_name,
  368. name: "DataSet",
  369. });
  370. navList.value = navRes.data;
  371. };
  372. const getMainTitle = async () => {
  373. const mainRes = await getNodeList({
  374. scd_id: scdIdValue,
  375. pagesize: 10000,
  376. ied_name: props.checkData.ied_name,
  377. name: "AccessPoint",
  378. });
  379. //得到每个方框中LDevice中的内容
  380. Promise.all(
  381. mainRes.data.map(async (item) => {
  382. item.childList = [];
  383. const res = await getLdeviceList({
  384. accessPointId: item.node_id,
  385. scd_id: scdIdValue,
  386. });
  387. item.childList.push(res.data);
  388. })
  389. ).then(() => {
  390. //等待执行完上面的api
  391. loading.value = false;
  392. mainTitle.value = mainRes.data;
  393. getMainList();
  394. });
  395. };
  396. const mainList = ref({});
  397. const titleName = ref([]);
  398. //几个方框的数据
  399. const getMainList = async () => {
  400. mainList.value = {};
  401. titleName.value = [];
  402. const newarr = [];
  403. const infoRes = await getNetworkInfo({
  404. scd_id: scdIdValue,
  405. ied_name: props.checkData.ied_name,
  406. });
  407. //处理分类数据
  408. for (let i = 0; i < infoRes.data.length; i++) {
  409. if (infoRes.data[i].address_json != "") {
  410. let newData = infoRes.data[i].address_json
  411. .replace("MAC-Address", "address")
  412. .replace("VLAN-PRIORITY", "priority")
  413. .replace("VLAN-ID", "vlanId");
  414. infoRes.data[i].address_json = JSON.parse(newData);
  415. }
  416. let item = infoRes.data[i];
  417. const key = item.ap_name;
  418. newarr.push(key);
  419. if (mainList.value[key] == null) {
  420. mainList.value[key] = {
  421. name: key,
  422. list: [item],
  423. };
  424. } else {
  425. mainList.value[key].list.push(item);
  426. }
  427. }
  428. //处理表头下方段落的描述
  429. if (mainList.value && mainTitle.value) {
  430. mainTitle.value.forEach((key) => {
  431. key.list = [];
  432. Object.keys(mainList.value).forEach((item) => {
  433. if (item == key.attr_name) {
  434. key.list = mainList.value[item].list;
  435. }
  436. });
  437. });
  438. //分布默认的左侧右侧和下侧的数据
  439. for (let i = 0; i < mainTitle.value.length; i++) {
  440. if (
  441. mainTitle.value[i].list.length > 0 &&
  442. mainTitle.value[i].list[0].address_json != ""
  443. ) {
  444. const targetElement = mainTitle.value[i];
  445. switch (i) {
  446. case 0:
  447. moBottom.value = targetElement.list[0].address_json;
  448. break;
  449. case 1:
  450. moLeft.value = targetElement.list[0].address_json;
  451. break;
  452. case 2:
  453. moRight.value = targetElement.list[0].address_json;
  454. break;
  455. }
  456. }
  457. }
  458. }
  459. };
  460. //弹窗打开后使得线条在指定区域中
  461. const hiddenLine2 = () => {
  462. const elmWrapper = document.getElementById("wrappers");
  463. // 移动 line
  464. document.body.querySelectorAll("body .leader-line").forEach((node) => {
  465. elmWrapper.appendChild(node);
  466. });
  467. elmWrapper.style.transform = "none";
  468. var rectWrapper = elmWrapper.getBoundingClientRect();
  469. elmWrapper.style.transform = `translate(${
  470. (rectWrapper.left + window.scrollY) * -1
  471. }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
  472. };
  473. const leaderLines = ref([]); //控制线条显示
  474. //滚动时重定位线条
  475. const newPositionLine2 = () => {
  476. document.getElementById("treedom4").addEventListener(
  477. "scroll",
  478. AnimEvent.add(() => {
  479. leaderLines.value.forEach((line) => {
  480. if (line) {
  481. hiddenLine2();
  482. line.position();
  483. line.positionByWindowResize = false;
  484. }
  485. });
  486. //中间展示图片的
  487. }),
  488. false
  489. );
  490. };
  491. const getLine = () => {
  492. const topDom = document.getElementById("topLine");
  493. const leftDom = document.getElementById("leftLine");
  494. const rightDom = document.getElementById("rightLine");
  495. const bottomDom = document.getElementById("bottomLine");
  496. const middlDom = document.getElementById("middleLine");
  497. let lineStyle = {
  498. color: "#134BEA",
  499. size: 2,
  500. path: "straight",
  501. endPlug: "disc",
  502. startPlug: "disc",
  503. middleLabel: LeaderLine.captionLabel("AccessPoint", {
  504. fontSize: 10,
  505. color: "#7F8EB2",
  506. }),
  507. };
  508. let lineStyleTop = {
  509. ...lineStyle,
  510. middleLabel: LeaderLine.captionLabel({
  511. text: "DataSet",
  512. fontSize: 10,
  513. color: "#7F8EB2",
  514. }),
  515. };
  516. let lineStyleright = {
  517. ...lineStyle,
  518. middleLabel: LeaderLine.captionLabel("AccessPoint", {
  519. fontSize: 10,
  520. color: "#7F8EB2",
  521. }),
  522. };
  523. let lineStylebottom = {
  524. ...lineStyle,
  525. middleLabel: LeaderLine.captionLabel({
  526. text: "AccessPoint",
  527. fontSize: 10,
  528. color: "#7F8EB2",
  529. }),
  530. };
  531. leaderLines.value.push(new LeaderLine(middlDom, topDom, lineStyleTop)); //上面和中间连线
  532. if (mainTitle.value && mainTitle.value.length > 0) {
  533. leaderLines.value.push(
  534. new LeaderLine(middlDom, bottomDom, lineStylebottom)
  535. );
  536. }
  537. if (mainTitle.value && mainTitle.value.length > 2) {
  538. leaderLines.value.push(new LeaderLine(middlDom, rightDom, lineStyleright));
  539. }
  540. if (mainTitle.value && mainTitle.value.length > 1) {
  541. leaderLines.value.push(new LeaderLine(leftDom, middlDom, lineStyle));
  542. }
  543. newPositionLine2();
  544. hiddenLine2();
  545. };
  546. //点击数字
  547. const clickCircel1 = (item, index, type) => {
  548. commonClickCircel(item, index, type,1);
  549. };
  550. const clickCircel2 = (item, index, type) => {
  551. commonClickCircel(item, index, type,2);
  552. };
  553. const clickCircel3 = (item, index, type) => {
  554. commonClickCircel(item, index, type,3);
  555. };
  556. const commonClickCircel = (item, index, type,num) => {
  557. switch(num){
  558. case 1:
  559. activeCircel1.value = index;
  560. break;
  561. case 2:
  562. activeCircel2.value = index;
  563. break;
  564. case 3:
  565. activeCircel3.value = index;
  566. break;
  567. }
  568. let data = JSON.stringify(item.address_json);
  569. let newData = data
  570. .replace("MAC-Address", "address")
  571. .replace("VLAN-PRIORITY", "priority")
  572. .replace("VLAN-ID", "vlanId");
  573. if (type == "moBottom") {
  574. moBottom.value = JSON.parse(newData);
  575. } else if (type == "moRight") {
  576. moRight.value = JSON.parse(newData);
  577. } else {
  578. moLeft.value = JSON.parse(newData);
  579. }
  580. };
  581. const attrsData = ref(null);
  582. const getNode = async () => {
  583. const attrRes = await getNodeAttrs({
  584. scd_id: scdIdValue,
  585. ied_name: props.checkData.ied_name,
  586. node_id: props.checkData.node_id,
  587. });
  588. attrsData.value = attrRes.data;
  589. };
  590. onMounted(() => {
  591. getNav();
  592. getMainTitle();
  593. getNode();
  594. nextTick(() => {
  595. setTimeout(() => {
  596. getLine();
  597. }, 500);
  598. });
  599. });
  600. watch(
  601. () => props.isOpen,
  602. (newValue) => {
  603. nextTick(() => {
  604. if (!newValue) {
  605. removeLine2();
  606. leaderLines.value = [];
  607. loading.value = false;
  608. } else {
  609. setTimeout(() => {
  610. getLine();
  611. }, 500);
  612. }
  613. });
  614. }
  615. );
  616. watch(
  617. () => props.checkData,
  618. (newValue) => {
  619. if (newValue) {
  620. removeLine2();
  621. if (leaderLines.value.length > 0) {
  622. leaderLines.value = [];
  623. }
  624. activeCircel1.value = 0;
  625. activeCircel2.value = 0;
  626. activeCircel3.value = 0;
  627. isOpenMain.value = false;
  628. isOpennav.value = false;
  629. getNav();
  630. loading.value = true;
  631. getMainTitle();
  632. getNode();
  633. nextTick(() => {
  634. setTimeout(() => {
  635. getLine();
  636. }, 500);
  637. });
  638. }
  639. }
  640. );
  641. const removeLine2 = () => {
  642. const elmWrapper = document.getElementById("wrappers");
  643. if (elmWrapper) {
  644. document.body.querySelectorAll("body .leader-line").forEach((node) => {
  645. elmWrapper.removeChild(node);
  646. });
  647. }
  648. };
  649. //点击头部展示的弹框
  650. const clickNav = async (item) => {
  651. clickNavTitle.value = item;
  652. isOpennav.value = true;
  653. const navRes = await nodeList({
  654. scd_id: scdIdValue,
  655. parent_node_id: item.node_id,
  656. pagesize: 10000,
  657. name: "FCDA",
  658. });
  659. clickNavData.value = navRes.data;
  660. };
  661. const cancelClickNav = () => {
  662. clickNavData.value = null;
  663. isOpennav.value = false;
  664. };
  665. const clickMain = async (item) => {
  666. clickMainTitle.value = item;
  667. isOpenMain.value = true;
  668. const navRes = await nodeList({
  669. scd_id: scdIdValue,
  670. parent_node_id: item.node_id,
  671. pagesize: 10000,
  672. name: "LN0",
  673. });
  674. const navRes2 = await nodeList({
  675. scd_id: scdIdValue,
  676. parent_node_id: item.node_id,
  677. pagesize: 10000,
  678. name: "LN",
  679. });
  680. clickMainData.value = [...navRes.data, ...navRes2.data];
  681. };
  682. const cancelClickMain = () => {
  683. clickMainData.value = null;
  684. isOpenMain.value = false;
  685. };
  686. </script>
  687. <style scoped lang="scss">
  688. #treedom4 {
  689. height: 72vh;
  690. overflow-y: auto;
  691. }
  692. .wrapper {
  693. position: relative;
  694. }
  695. .nav {
  696. height: 160px;
  697. background: #f3f5fa;
  698. overflow-y: auto;
  699. border: 2px dashed #a3ade0;
  700. display: flex;
  701. justify-content: start;
  702. flex-wrap: wrap;
  703. position: relative;
  704. margin: 16px;
  705. .nav-img {
  706. width: 30px;
  707. height: 30px;
  708. }
  709. .nav-cont {
  710. display: flex;
  711. flex-direction: column;
  712. align-items: center;
  713. cursor: pointer;
  714. margin: 8px 0;
  715. flex-basis: 14%;
  716. .describe-text {
  717. color: #134bea;
  718. }
  719. }
  720. }
  721. .main-bottom,
  722. .fluid {
  723. border: 2px dashed #a3ade0;
  724. background-color: #f7f8f8;
  725. display: flex;
  726. flex-direction: column;
  727. max-width: 36%;
  728. img {
  729. width: 40px;
  730. height: 40px;
  731. }
  732. .title {
  733. font-size: 16px;
  734. font-weight: bold;
  735. margin: 12px 0;
  736. text-align: center;
  737. }
  738. .attr-desc {
  739. margin: 10px;
  740. }
  741. .decrip {
  742. color: #7484ab;
  743. font-size: 14px;
  744. margin-right: 15px;
  745. width: 130px;
  746. display: inline-block;
  747. }
  748. .decrip-child {
  749. color: #7484ab;
  750. font-size: 14px;
  751. }
  752. .decrip-item {
  753. font-weight: bold;
  754. font-size: 14px;
  755. }
  756. .child-item {
  757. display: flex;
  758. margin: 12px;
  759. flex-wrap: wrap;
  760. border: 1px solid #5182ff;
  761. position: relative;
  762. & > div {
  763. margin: 8px;
  764. }
  765. .ldevice {
  766. position: absolute;
  767. top: -20px;
  768. left: -10px;
  769. padding: 0 4px;
  770. background: #5182ff;
  771. color: white;
  772. border-radius: 10px;
  773. }
  774. .ldevice-cont {
  775. display: flex;
  776. flex-direction: column;
  777. align-items: center;
  778. cursor: pointer;
  779. }
  780. }
  781. .img-title {
  782. color: #134bea;
  783. }
  784. }
  785. .circle-all {
  786. margin-bottom: 10px;
  787. display: flex;
  788. flex-wrap: wrap;
  789. }
  790. .circel {
  791. color: #7c58a8;
  792. display: inline-block;
  793. width: 20px;
  794. height: 20px;
  795. margin-bottom: 5px;
  796. margin-right: 5px;
  797. border: 1px solid #606c93;
  798. border-radius: 10px;
  799. text-align: center;
  800. line-height: 20px;
  801. margin-left: 0.5rem;
  802. cursor: pointer;
  803. }
  804. .active-circel {
  805. color: #134bea;
  806. border: 1px solid #134bea;
  807. }
  808. .Image {
  809. width: 193px;
  810. height: 150px;
  811. }
  812. /* 设置网格布局相关的样式 */
  813. .grid {
  814. display: flex;
  815. flex-wrap: nowrap;
  816. justify-content: space-between;
  817. align-items: center;
  818. margin-top: 50px;
  819. }
  820. .grid > .col {
  821. box-sizing: border-box;
  822. // padding: 10px;
  823. }
  824. /* 设置fixed2样式 */
  825. .main-middle {
  826. width: 160px;
  827. height: 160px;
  828. background: #fff url("~@/assets/image/instruct/network_slices.png") no-repeat
  829. center;
  830. background-size: 160px;
  831. position: relative;
  832. font-size: 12px;
  833. .text-overflow {
  834. overflow: hidden;
  835. text-overflow: ellipsis;
  836. white-space: nowrap;
  837. display: block;
  838. cursor: pointer;
  839. }
  840. .ied_struct_manufacturer {
  841. line-height: 2rem;
  842. transform: rotate(-33deg);
  843. top: 65%;
  844. position: absolute;
  845. left: 62%;
  846. border: 0px solid #cccccc1c;
  847. font-style: italic;
  848. font-size: 1rem;
  849. width: 6rem;
  850. text-align: center;
  851. }
  852. .ied_struct_manufacturer1 {
  853. top: 54%;
  854. left: 59%;
  855. }
  856. .ied_struct_desc {
  857. line-height: 2rem;
  858. position: absolute;
  859. transform: rotate(31deg);
  860. top: 15%;
  861. left: 32%;
  862. width: 59%;
  863. word-break: break-word;
  864. color: #134bea;
  865. font-weight: bold;
  866. font-style: italic;
  867. text-align: center;
  868. }
  869. .ied_struct_type {
  870. position: absolute;
  871. transform: rotate(31deg);
  872. top: 26%;
  873. left: 17%;
  874. color: #15010152;
  875. font-size: 1rem;
  876. font-style: italic;
  877. width: 60%;
  878. line-height: 1.5rem;
  879. text-align: center;
  880. }
  881. }
  882. /* 设置fluid样式 */
  883. .fluid {
  884. flex-grow: 1;
  885. }
  886. .transp {
  887. border: none;
  888. }
  889. .main-bottom {
  890. position: absolute;
  891. left: 50%;
  892. transform: translateX(-50%);
  893. margin-top: 40px;
  894. }
  895. .dialog-nav-title {
  896. color: #09162c;
  897. font-size: 16px;
  898. }
  899. </style>