CidTree.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. <template>
  2. <div>
  3. <div class="bigBox" :class="{ bigBoxUp: isUPdate == 'update' }">
  4. <div>
  5. <div class="titles">
  6. <img
  7. style="width: 20px; height: 20px"
  8. src="../../../assets/icon/HardDrives.png"
  9. alt=""
  10. />
  11. <div>装置列表</div>
  12. </div>
  13. </div>
  14. <div class="tagBox">
  15. <div
  16. class="cont-line tagP"
  17. :class="{ clicktag: tagChoose == index }"
  18. v-for="(item, index) in tagList"
  19. :key="index"
  20. @click="tagClick(item, index)"
  21. >
  22. <span v-if="!OpensclTrue">{{
  23. `(${item.ied_name})${item.desc}`
  24. }}</span>
  25. <span v-else>{{ `(${item.ied_name})${item.ied_desc}` }}</span>
  26. </div>
  27. </div>
  28. <div class="setting">
  29. <el-tree
  30. :data="treeData"
  31. :props="defaultProps"
  32. highlight-current
  33. @node-click="handleNodeClick"
  34. >
  35. <template #default="{ node, data }">
  36. <span class="label" :class="{ 'tree-label': node.expanded }">{{
  37. node.label
  38. }}</span
  39. ><span
  40. :class="{ 'tree-label': clickItemcode == data.itemcode }"
  41. style="position: absolute; right: 10px"
  42. ><span v-if="OpensclTrue">{{ data.num }}</span
  43. ><span v-else>{{ data.num }}</span></span
  44. >
  45. </template>
  46. </el-tree>
  47. </div>
  48. </div>
  49. </div>
  50. </template>
  51. <script setup>
  52. import { ref, onMounted, toRefs, watch } from "vue";
  53. import cid from "@/api/cid/cid";
  54. import scdCheck from "@/api/scdCheck/scdCheck";
  55. import { compIedstatType } from "@/api/scdCheck/scdCheck2";
  56. import { useRoute } from "vue-router";
  57. const route = useRoute();
  58. const props = defineProps({
  59. OpensclTrue: {
  60. type: Boolean,
  61. default: false,
  62. },
  63. iedRelation: {
  64. type: Object,
  65. default: () => {},
  66. },
  67. UPdate: {
  68. //判断是否是点击更改 进入的界面
  69. type: String,
  70. default: "",
  71. },
  72. clickRowDatas: {
  73. type: Object,
  74. default: () => {},
  75. },
  76. allCidStart: {
  77. type: Array,
  78. default: () => [],
  79. },
  80. });
  81. const emit = defineEmits(["treeBack", "clickCode", "treeBackDefalut"]);
  82. let tagList = ref(props.iedRelation);
  83. const loading = ref(true);
  84. let tagChoose = ref("");
  85. let treeData = ref([
  86. {
  87. label: "装置信息",
  88. itemcode: "ied",
  89. num: 0,
  90. children: [
  91. {
  92. label: "基本信息",
  93. itemcode: "scd.ied",
  94. num: 0,
  95. },
  96. ],
  97. },
  98. {
  99. label: "通信参数",
  100. itemcode: "Communication",
  101. num: 0,
  102. children: [
  103. {
  104. label: "通信接入点",
  105. itemcode: "scd.ied.Communication",
  106. num: 0,
  107. },
  108. {
  109. label: "站控层通信参数",
  110. itemcode: "scd.ied.Communication.S1",
  111. num: 0,
  112. },
  113. {
  114. label: "GOOSE 通信参数",
  115. itemcode: "scd.ied.Communication.GSE",
  116. num: 0,
  117. },
  118. { label: "SV 通信参数", itemcode: "scd.ied.Communication.SMV", num: 0 },
  119. ],
  120. },
  121. {
  122. label: "测点信息",
  123. itemcode: "Point",
  124. num: 0,
  125. children: [
  126. {
  127. label: "遥信",
  128. itemcode: "scd.ied.YX",
  129. num: 0,
  130. },
  131. {
  132. label: "遥控",
  133. itemcode: "scd.ied.YK",
  134. num: 0,
  135. },
  136. {
  137. label: "遥测",
  138. itemcode: "scd.ied.YC",
  139. num: 0,
  140. },
  141. {
  142. label: "遥脉",
  143. num: 0,
  144. itemcode: "scd.ied.YM",
  145. },
  146. {
  147. label: "定值",
  148. itemcode: "scd.ied.DZ",
  149. num: 0,
  150. },
  151. ],
  152. },
  153. {
  154. label: "回路配置",
  155. itemcode: "config",
  156. num: 0,
  157. children: [
  158. {
  159. label: "发布虚端子",
  160. itemcode: "scd.ied.FCDA",
  161. num: 0,
  162. },
  163. {
  164. label: "定阅虚端子",
  165. itemcode: "scd.ied.ExtRef",
  166. num: 0,
  167. },
  168. {
  169. label: "虚回路信息",
  170. itemcode: "scd.ied.Relation",
  171. num: 0,
  172. },
  173. ],
  174. },
  175. {
  176. label: "建模信息",
  177. itemcode: "model",
  178. num: 0,
  179. children: [
  180. {
  181. label: "数据集",
  182. itemcode: "scd.ied.DatSet",
  183. num: 0,
  184. },
  185. {
  186. label: "数据集成员",
  187. itemcode: "scd.ied.DatSetMeber",
  188. num: 0,
  189. },
  190. {
  191. label: "GOOSE控制块",
  192. itemcode: "scd.ied.GSEControl",
  193. num: 0,
  194. },
  195. {
  196. label: "SV控制块",
  197. itemcode: "scd.ied.SampledValueControl",
  198. num: 0,
  199. },
  200. {
  201. label: "报告控制块",
  202. itemcode: "scd.ied.ReportControl",
  203. num: 0,
  204. },
  205. {
  206. label: "日志控制块",
  207. itemcode: "scd.ied.LogControl",
  208. num: 0,
  209. },
  210. ],
  211. },
  212. ]);
  213. let needName = ref("");
  214. //得到差异项code的数字数据
  215. const codeStatic = async () => {
  216. const ids = clickRow.value ? clickRow.value.id : "";
  217. const names = clickTage.value ? clickTage.value.ied_name : "";
  218. const res = await compIedstatType({
  219. comp_id: ids,
  220. ied_name: names,
  221. comptype: "u",
  222. });
  223. updateNum(treeData.value, res.data);
  224. };
  225. const updateNum = (treeNode, data) => {
  226. for (let node of treeNode) {
  227. node.num = 0;
  228. // 检查当前节点的 itemcode 是否在 data 中
  229. if (data && data.hasOwnProperty(node.itemcode)) {
  230. node.num = parseInt(data[node.itemcode]);
  231. }
  232. if (data && node.itemcode == "scd.ied.Relation"&&data["scd.ied.ExtRef"]) {
  233. node.num = parseInt(data["scd.ied.ExtRef"]);
  234. }
  235. // 如果当前节点有子节点,递归处理子节点
  236. if (node.children) {
  237. updateNum(node.children, data);
  238. // 计算父级节点的num是子节点num的和
  239. node.num = node.children
  240. .filter((child) => child.itemcode !== "scd.ied.Relation")
  241. .reduce((total, child) => total + child.num, 0);
  242. }
  243. }
  244. loading.value = false
  245. };
  246. let defaultProps = ref({
  247. label: "label",
  248. children: "children",
  249. num: "num",
  250. });
  251. const isUPdate = ref(props.UPdate);
  252. watch(
  253. () => props.UPdate,
  254. (newValue) => {
  255. isUPdate.value = newValue;
  256. }
  257. );
  258. watch(
  259. () => props.iedRelation, //点击SCD文件一致性校核,点击查看,点击修改进如的装置列表
  260. (newValue) => {
  261. if (newValue) {
  262. tagList.value = newValue;
  263. }
  264. }
  265. );
  266. const allCidStartProps = ref(null);
  267. watch(
  268. //CID一致性校验左侧的数据处理
  269. () => props.allCidStart,
  270. (newValue) => {
  271. if (newValue && newValue.length) {
  272. allCidStartProps.value = newValue;
  273. treeData.value.forEach((node) => {
  274. addChildItems(node, newValue);
  275. });
  276. }
  277. }
  278. );
  279. //Cid使用递归
  280. const addChildItems = (node, data) => {
  281. if (!node.childItemCid) {
  282. node.childItemCid = [];
  283. }
  284. data.forEach((item) => {
  285. if (node.itemcode === item.diff_object_type) {
  286. let text;
  287. text = item.diff_desc.replace(/[\r|\n|\t]/g, ""); //处理返回的数据中换行等,整理好规整数据
  288. item.diff_desc = JSON.parse(text);
  289. node.childItemCid.push(item);
  290. }
  291. });
  292. if (node.children) {
  293. node.children.forEach((childNode) => {
  294. addChildItems(childNode, data);
  295. });
  296. // 计算并设置 num 值
  297. let childrenNum = 0;
  298. node.children.forEach((childNode) => {
  299. childrenNum += childNode.childItemCid.length;
  300. });
  301. node.num = childrenNum;
  302. } else {
  303. node.num = node.childItemCid.length;
  304. }
  305. };
  306. const reload = () => {
  307. if (!props.OpensclTrue) {
  308. //网络结构体点击CID一致性校核打开获取的装置列表
  309. cid.getAll({ scd_id: route.query.id, ied_name: "" }).then((res) => {
  310. tagList.value = res.data;
  311. tagChoose.value = res.data ? Object.keys(res.data)[0] : "";
  312. clickTage.value = res.data ? Object.values(res.data)[0] : "";
  313. emit("treeBack", clickTage.value)
  314. });
  315. }
  316. };
  317. const clickTage = ref(null);
  318. const tagClick = (row, num) => {
  319. loading.value = true;
  320. treeData.value.forEach(item=>{
  321. item.num = 0;
  322. item.childItemCid = [];
  323. if(item.children){
  324. item.children.forEach(key=>{
  325. key.num=0;
  326. key.childItemCid = [];
  327. })
  328. }
  329. })
  330. tagChoose.value = num;
  331. clickTage.value = row;
  332. // cid
  333. // .findFile({
  334. // scd_id: route.query.id,
  335. // ied_name: row.desc,
  336. // pageno: 1,
  337. // pagesize: 10,
  338. // station_id: route.query.stationId,
  339. // })
  340. // .then((res) => {});
  341. // scdCheck
  342. // .lookCheck({
  343. // pageindex: 1,
  344. // pagesize: 10,
  345. // station_id: route.query.stationId,
  346. // scd_id: route.query.id,
  347. // is_checkin: 2,
  348. // ied_name: row.ied_name,
  349. // })
  350. // .then((res) => {
  351. // let fileInfo;
  352. // if (res.data) {
  353. // fileInfo = res.data.filter((item) => item.scd_id == route.query.id);
  354. // if (fileInfo.length > 0) {
  355. // emit("treeBack", row, fileInfo[0]);
  356. // }
  357. // }
  358. // let a = res.data.filter((item) => item.type_name == "CID");
  359. // if (a.length > 0) {
  360. // needName.value = a[0].file_name;
  361. // emit("treeBack", needName.value, a[0].id);
  362. // }
  363. // });
  364. if (props.OpensclTrue) {
  365. codeStatic();
  366. }
  367. };
  368. const clickRow = ref(props.clickRowDatas);
  369. //对比文件:头部对比的单个数据
  370. watch(
  371. () => props.clickRowDatas,
  372. (newValue) => {
  373. if (newValue) {
  374. clickRow.value = newValue;
  375. }
  376. }
  377. );
  378. const clickItemcode = ref("");
  379. const handleNodeClick = (e) => {
  380. clickItemcode.value = e.itemcode;
  381. emit("clickCode", e.itemcode, e);
  382. };
  383. onMounted(() => {
  384. tagChoose.value = props.iedRelation ? Object.keys(props.iedRelation)[0] : "";
  385. clickTage.value = props.iedRelation
  386. ? Object.values(props.iedRelation)[0]
  387. : "";
  388. emit("treeBackDefalut", clickTage.value);
  389. reload();
  390. if (props.OpensclTrue) {
  391. codeStatic();
  392. }
  393. });
  394. </script>
  395. <style scoped lang="scss">
  396. p,
  397. h3 {
  398. margin: 0;
  399. padding: 0;
  400. }
  401. .bigBox {
  402. width: 100%;
  403. height: calc(100vh - 280px);
  404. margin-top: 20px;
  405. border: 1px solid #a3ade0;
  406. border-radius: 2px;
  407. cursor: pointer;
  408. background: #f7f8fb;
  409. & > div:first-child {
  410. display: flex;
  411. justify-content: flex-start;
  412. align-items: center;
  413. color: #1a2447;
  414. margin: 16px 0 0 16px;
  415. }
  416. }
  417. .bigBoxUp {
  418. height: calc(100vh - 230px) !important;
  419. }
  420. :deep(.el-tree) {
  421. --el-fill-color-blank: #f7f8fb;
  422. }
  423. .tagBox {
  424. width: 92%;
  425. height: 45%;
  426. overflow-y: auto;
  427. margin: 8px 16px 0px 16px;
  428. }
  429. .tagP {
  430. overflow: hidden;
  431. text-overflow: ellipsis;
  432. white-space: nowrap;
  433. margin-top: 8px;
  434. font-size: 16px;
  435. }
  436. .setting {
  437. width: 92%;
  438. height: 45%;
  439. overflow-y: auto;
  440. border-top: 1px solid #a3ade0;
  441. margin: 2px auto;
  442. .label {
  443. padding: 5px 8px;
  444. }
  445. :deep(.el-tree--highlight-current .el-tree-node) {
  446. margin: 5px 0;
  447. color: #1a2447;
  448. }
  449. :deep(
  450. .el-tree--highlight-current
  451. .el-tree-node.is-current
  452. > .el-tree-node__content
  453. ) {
  454. background: transparent;
  455. }
  456. :deep(
  457. .el-tree--highlight-current
  458. .el-tree-node.is-current
  459. > .el-tree-node__content
  460. .label
  461. ) {
  462. color: #134bea;
  463. border: 1px solid #255ce7;
  464. background: #f6f9ff;
  465. }
  466. }
  467. .titles {
  468. display: flex;
  469. align-items: center;
  470. & > div {
  471. font-size: 16px;
  472. margin-left: 8px;
  473. vertical-align: middle;
  474. font-weight: bold;
  475. }
  476. }
  477. .cont-line,
  478. :deep(.el-tree-node__label) {
  479. color: #1a2447;
  480. font-size: 14px;
  481. }
  482. .clicktag {
  483. color: #255ce7;
  484. }
  485. .tree-label {
  486. color: #134bea;
  487. }
  488. </style>