scdVisual.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. <template>
  2. <div class="main">
  3. <!-- 统计和搜索栏 -->
  4. <div class="search-nav">
  5. <el-form
  6. :model="queryParams"
  7. ref="queryRef"
  8. :inline="true"
  9. label-width="68px"
  10. >
  11. <el-form-item
  12. ><div class="nav-item">
  13. 总计 <span>{{ count }}</span> 个设备
  14. </div></el-form-item
  15. >
  16. <el-form-item label="电压等级" prop="voltage_level_id">
  17. <el-select
  18. ref="levelRef"
  19. v-model="queryParams.voltage_level_id"
  20. placeholder="请选择电压等级"
  21. clearable
  22. @change="changeLevel"
  23. >
  24. <el-option
  25. v-for="dict in voltageLevel"
  26. :key="dict.id"
  27. :label="dict.name"
  28. :value="dict.id"
  29. />
  30. </el-select>
  31. </el-form-item>
  32. <el-form-item label="间隔" prop="area_id">
  33. <el-select
  34. ref="levelRef"
  35. v-model="queryParams.area_id"
  36. placeholder="请选择间隔"
  37. @change="changeLevel"
  38. clearable
  39. >
  40. <el-option
  41. v-for="dict in areaData"
  42. :key="dict.id"
  43. :label="dict.name"
  44. :value="dict.id"
  45. />
  46. </el-select>
  47. </el-form-item>
  48. <el-form-item label="设备类型" prop="device_type_id">
  49. <el-select
  50. ref="levelRef"
  51. v-model="queryParams.device_type_id"
  52. placeholder="请选择设备类型"
  53. @change="changeLevel"
  54. clearable
  55. >
  56. <el-option
  57. v-for="dict in iedTypeData"
  58. :key="dict.code"
  59. :label="dict.name"
  60. :value="dict.code"
  61. />
  62. </el-select>
  63. </el-form-item>
  64. <el-form-item label="快捷搜索" prop="iedrela">
  65. <el-select
  66. v-model="queryParams.iedrela"
  67. placeholder="请输入IED编码或名称"
  68. clearable
  69. ref="selectRef"
  70. v-if="showIedList"
  71. :loading="loadingsearch"
  72. @clear="showIedList = false"
  73. @change="searchIedrela"
  74. >
  75. <template #header>
  76. <span class="search-header" v-if="searchIedList.length > 0">
  77. 为您找到 <span>{{ searchIedList.length }}</span> 个相关结果
  78. </span>
  79. </template>
  80. <el-option
  81. v-for="dict in searchIedList"
  82. :key="dict.node_id"
  83. :label="dict.desc"
  84. :value="dict"
  85. ></el-option>
  86. </el-select>
  87. <el-input
  88. ref="selectInputRef"
  89. v-model="queryParams.iedrela"
  90. placeholder="请输入IED编码或名称"
  91. :suffix-icon="Search"
  92. clearable
  93. @change="searchInput"
  94. v-else
  95. />
  96. </el-form-item>
  97. </el-form>
  98. </div>
  99. <el-scrollbar height="64vh" v-loading="loading" v-if="loadDating">
  100. <div
  101. v-for="(item, index) in voltageLevel"
  102. :key="index"
  103. style="padding-right: 10px"
  104. >
  105. <el-row class="contanier" v-if="item.id != 'alls'">
  106. <el-col :span="3">
  107. <div
  108. :class="
  109. item.levelData.length > 7 ? 'file_img' : 'file_img file_lim'
  110. "
  111. >
  112. {{ item.name }}
  113. </div>
  114. </el-col>
  115. <el-col :span="20" class="ied_item">
  116. <div
  117. class="ied_item_child"
  118. v-for="(itemChild, indexChild) in item.levelData"
  119. :key="indexChild"
  120. @click="changeLevel(itemChild.id, itemChild.name)"
  121. >
  122. <el-tooltip
  123. :content="itemChild.name"
  124. effect="light"
  125. placement="top"
  126. ><div>{{ itemChild.name }}</div></el-tooltip
  127. >
  128. <img :src="scdIed" alt="" />
  129. </div>
  130. </el-col>
  131. </el-row>
  132. </div>
  133. </el-scrollbar>
  134. </div>
  135. <div class="container-none" v-if="!loading && !loadDating">
  136. <img src="../../../assets/image/create.png" alt="" />
  137. 该变电站还未签入任何SCD文件!
  138. </div>
  139. <scd-dialog-index
  140. :open="open"
  141. @done="done"
  142. :dialogData="dialogData"
  143. :checkLabel="checkLabel"
  144. :iedRelationData="iedRelationData"
  145. ></scd-dialog-index>
  146. <!-- 快速搜索用的弹窗 -->
  147. <dialog-index
  148. :openBig="openBig"
  149. @done="donesearch"
  150. :checkDialogData="checkDialogData"
  151. :iedRelationData="iedRelationData"
  152. ></dialog-index>
  153. </template>
  154. <script setup>
  155. import { onMounted, reactive, ref, toRefs, nextTick, provide } from "vue";
  156. import dialogIndex from "./dialogIndex.vue";
  157. import scdIed from "@/assets/image/instruct/scdIed.png";
  158. import {
  159. iedTypelist,
  160. areaList,
  161. scdIedRelation,
  162. areaIedList,
  163. } from "@/api/iedNetwork";
  164. import { useDataStore } from "@/store/modules/golbal-data";
  165. import scdDialogIndex from "./scdDialogIndex";
  166. import { useRoute } from "vue-router";
  167. import { Search } from "@element-plus/icons-vue";
  168. const userStoreCode = useDataStore();
  169. const route = useRoute();
  170. // const scdIdValue = 1248000337;
  171. const scdIdValue = route.query.id;
  172. //快捷搜索=====
  173. const loadingsearch = ref(false);
  174. const openBig = ref(false); //快捷搜索
  175. const iedRelationData = ref([]);
  176. const checkDialogData = ref(null);
  177. const iedRelation = async () => {
  178. const iedRes = await scdIedRelation({ scd_id: scdIdValue });
  179. if (!iedRes||!iedRes.data) return;
  180. iedRelationData.value = iedRes.data;
  181. };
  182. const donesearch = (emits) => {
  183. openBig.value = emits;
  184. checkDialogData.value = null;
  185. };
  186. const searchIedrela = (value) => {
  187. if (!value) return;
  188. openBig.value = true;
  189. Object.values(iedRelationData.value).find((item) => {
  190. if (item.ied_name == value.ied_name) {
  191. checkDialogData.value = item;
  192. }
  193. });
  194. };
  195. //快捷搜索=====
  196. const data = reactive({
  197. queryParams: {
  198. scd_id: scdIdValue,
  199. },
  200. });
  201. const loading = ref(true);
  202. const loadDating = ref(false);
  203. const open = ref(false);
  204. const { queryParams } = toRefs(data);
  205. // 表单重置
  206. const reset = () => {
  207. queryParams.value = {
  208. scd_id: scdIdValue,
  209. voltage_level_id: null, //电压等级
  210. area_id: null, //间隔
  211. device_type_id: null, //装置类型
  212. };
  213. };
  214. const areaData = ref([]); //获取间隔
  215. const allLevel = ref([]); // 获取所有电压
  216. const all = [{ name: "全部", id: "alls" }];
  217. const allIedType = [{ name: "全部", code: "alls" }];
  218. const voltageLevel = ref([{ name: "全部", id: "alls" }]); //电压等级
  219. const areaType = ref([]);
  220. const getArea = async () => {
  221. const areaRes = await areaList({ scd_id: scdIdValue });
  222. if (!areaRes||!areaRes.data) {
  223. voltageLevel.value = [];
  224. loading.value = false;
  225. loadDating.value = false;
  226. return;
  227. }
  228. loading.value = false;
  229. areaData.value = [...all, ...areaRes.data]; //搜索处的间隔
  230. //处理电压等级的搜索展示数据
  231. const levelData = [
  232. ...new Set(areaRes.data.map((itemlevel) => itemlevel.voltage_level)),
  233. ];
  234. if (!levelData) return;
  235. levelData.forEach((myLevelItem) => {
  236. const findData = allLevel.value.find((allItem) => {
  237. return allItem.id == myLevelItem;
  238. });
  239. if (findData) {
  240. voltageLevel.value.push(findData);
  241. }
  242. });
  243. //处理主界面的数据展示
  244. if (!voltageLevel.value) return;
  245. voltageLevel.value.forEach((item) => {
  246. if (item.id == "alls") return;
  247. item.levelData = [];
  248. const findType = areaRes.data.filter((itemType) => {
  249. return itemType.voltage_level == item.id;
  250. });
  251. if (findType) {
  252. item.levelData.push(...findType);
  253. }
  254. });
  255. loadDating.value = true;
  256. };
  257. //设备类型
  258. const iedTypeData = ref([]);
  259. const getTypelist = async () => {
  260. const typeRes = await iedTypelist({ scd_id: scdIdValue });
  261. if (!typeRes) return;
  262. iedTypeData.value = typeRes.data ? [...allIedType, ...typeRes.data] : [];
  263. };
  264. const iedName = ref([]);
  265. const showIedList = ref(false);
  266. //搜索ied编码或名称
  267. const searchIedList = ref([]);
  268. const selectRef = ref(null);
  269. const searchInput = (value) => {
  270. loadingsearch.value = true;
  271. setTimeout(() => {
  272. if (value && iedName.value) {
  273. loadingsearch.value = false;
  274. showIedList.value = true;
  275. searchIedList.value = Object.values(iedName.value).filter((item) => {
  276. const lowercaseValue = value.toLowerCase(); //不区分大小写
  277. const iedNameLower = item.ied_name ? item.ied_name.toLowerCase() : null;
  278. const descLower = item.desc ? item.desc.toLowerCase() : null;
  279. return (
  280. (iedNameLower !== null && iedNameLower.includes(lowercaseValue)) ||
  281. (descLower !== null && descLower.includes(lowercaseValue))
  282. );
  283. });
  284. // 选择框自动展开
  285. nextTick(() => {
  286. selectRef.value.toggleMenu();
  287. });
  288. } else {
  289. showIedList.value = false;
  290. searchIedList.value = [];
  291. }
  292. }, 200);
  293. };
  294. const count = ref(0);
  295. const iedNameData = async () => {
  296. //IED编码或名称
  297. const iedRes = await scdIedRelation({ scd_id: scdIdValue });
  298. if(!iedRes) return;
  299. iedName.value = iedRes.data;
  300. count.value = iedRes.count;
  301. };
  302. const done = (emits) => {
  303. open.value = emits;
  304. reset();
  305. dialogData.value = [];
  306. };
  307. //选择电压
  308. const dialogData = ref([]);
  309. const levelRef = ref(null); //为了得到选中的label值
  310. const checkLabel = ref("");
  311. const changeLevel = async (value, mainValue) => {
  312. nextTick(() => {
  313. checkLabel.value = mainValue ? mainValue : levelRef.value.selectedLabel;
  314. });
  315. if(!queryParams.value) return;
  316. //如果选中的是当前选项,那么其他搜索框的内容应置为空
  317. Object.keys(queryParams.value).forEach((item) => {
  318. if (queryParams.value[item] !== value && item != "scd_id") {
  319. queryParams.value[item] = null;
  320. }
  321. });
  322. if (value == "alls") {
  323. //全部
  324. open.value = true;
  325. dialogData.value = iedName.value;
  326. } else if (value) {
  327. const mainClick = { scd_id: scdIdValue, area_id: value };
  328. const forms = mainValue ? mainClick : queryParams.value;
  329. open.value = true;
  330. dialogData.value = [];
  331. //搜索的弹框内容
  332. const searchLevel = await areaIedList(forms);
  333. if (!searchLevel||!searchLevel.data) return;
  334. dialogData.value = Object.values(iedName.value).filter((item) => {
  335. return searchLevel.data.some((levelItem) => {
  336. return item.node_id == levelItem.ied_id;
  337. });
  338. });
  339. }
  340. };
  341. //弹窗=============
  342. provide("scdId", scdIdValue);
  343. onMounted(async () => {
  344. iedNameData();
  345. allLevel.value = await userStoreCode.GlobalCodes();
  346. getArea();
  347. getTypelist();
  348. iedRelation();
  349. });
  350. </script>
  351. <style scoped lang="scss">
  352. @mixin mid-center {
  353. display: flex;
  354. align-items: center;
  355. }
  356. .main {
  357. margin: 40px;
  358. }
  359. .search-nav {
  360. @include mid-center;
  361. justify-content: center;
  362. .nav-item {
  363. color: #134bea;
  364. font-size: 16px;
  365. span {
  366. color: #ffcb11;
  367. font-size: 20px;
  368. }
  369. }
  370. :deep(.el-form-item__label) {
  371. color: #1a2447;
  372. line-height: 40px;
  373. }
  374. :deep(.el-input) {
  375. height: 40px;
  376. }
  377. }
  378. .search-header {
  379. display: flex;
  380. justify-content: center;
  381. span {
  382. color: #134bea;
  383. padding: 0 2px;
  384. }
  385. }
  386. //主要内容版块
  387. .contanier {
  388. background: #f6faff;
  389. box-shadow: inset 0px 0px 11px 1px rgba(188, 207, 255, 0.78);
  390. border-radius: 8px;
  391. margin-bottom: 24px;
  392. // max-height: 320px;
  393. @include mid-center;
  394. overflow-y: auto;
  395. .file_img {
  396. @include mid-center;
  397. justify-content: center;
  398. background: url("~@/assets/image/instruct/file_back.png") no-repeat;
  399. background-size: 144px;
  400. width: 144px;
  401. height: 144px;
  402. margin: 24px;
  403. font-size: 20px;
  404. color: #1a2447;
  405. font-weight: bold;
  406. padding-top: 8px;
  407. }
  408. .file_lim {
  409. background-size: 144px 80px;
  410. width: 144px;
  411. height: 80px;
  412. font-size: 16px;
  413. }
  414. @media (max-width: 1220px) {
  415. .file_img {
  416. background-size: 100px;
  417. width: 100px;
  418. height: 100px;
  419. }
  420. }
  421. .ied_item {
  422. // margin: 0px 24px 10px 0;
  423. margin: 24px;
  424. margin-left: 0;
  425. display: flex;
  426. align-items: start;
  427. flex-wrap: wrap;
  428. .ied_item_child {
  429. display: flex;
  430. flex-basis: 14%;
  431. flex-direction: column;
  432. align-items: center;
  433. font-size: 16px;
  434. cursor: pointer;
  435. div {
  436. position: relative;
  437. top: 10px;
  438. display: -webkit-box;
  439. /*弹性伸缩盒子模型显示*/
  440. -webkit-box-orient: vertical;
  441. /*排列方式*/
  442. -webkit-line-clamp: 1;
  443. /*显示文本行数*/
  444. overflow: hidden;
  445. /*溢出隐藏*/
  446. }
  447. }
  448. .ied_item_child:hover div {
  449. color: #255ce7;
  450. font-weight: 600;
  451. }
  452. img {
  453. width: 64px;
  454. height: 64px;
  455. }
  456. }
  457. }
  458. .container-none {
  459. font-size: 18px;
  460. display: flex;
  461. flex-direction: column;
  462. justify-content: center;
  463. align-items: center;
  464. & > img {
  465. width: 220px;
  466. height: 220px;
  467. }
  468. }
  469. :deep(.el-input .el-input__icon) {
  470. cursor: pointer;
  471. }
  472. </style>