CreateMis.vue 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. <template>
  2. <div>
  3. <div class="createMisBox" v-if="selects == 1">
  4. <div>
  5. <h1 style="font-size: 18px; font-weight: bolder; color: #1a2447">
  6. {{ editAndAdd }}
  7. </h1>
  8. </div>
  9. <div class="formBox" v-loading="saveLoading">
  10. <el-form
  11. ref="myForm"
  12. :inline="true"
  13. label-position="top"
  14. :model="newMission"
  15. class="demo-form-inline"
  16. style="width: 1200px; margin: 0 auto"
  17. :rules="missionRules"
  18. require-asterisk-position="right"
  19. label-width="500px"
  20. >
  21. <el-form-item label="检测任务名称" prop="misName">
  22. <el-input
  23. class="bestInput"
  24. v-model="newMission.misName"
  25. placeholder="请输入任务名称"
  26. clearable
  27. />
  28. </el-form-item>
  29. <el-form-item label="任务编号" prop="misNum">
  30. <el-input
  31. class="bestInput"
  32. disabled
  33. v-model="newMission.misNum"
  34. placeholder="自动生成任务编号..."
  35. clearable
  36. />
  37. </el-form-item>
  38. <el-form-item label="检测变电站" prop="flashId">
  39. <el-select
  40. style="width: 340px; height: 40px"
  41. v-model="newMission.flashId"
  42. placeholder="请选择变电站"
  43. clearable
  44. @change="flashChange"
  45. >
  46. <template v-for="(item, index) in flashList">
  47. <el-option :label="item.label" :value="item.value" />
  48. </template>
  49. </el-select>
  50. <img
  51. @click="addFlash"
  52. style="width: 40px; height: 40px"
  53. src="../../../assets/icon/create_misBtn.png"
  54. alt=""
  55. />
  56. </el-form-item>
  57. <el-form-item label="检测模型" prop="cmodel">
  58. <el-input
  59. class="bestInput"
  60. style="width: 600px"
  61. disabled
  62. placeholder="输入内容"
  63. v-model="newMission.cmodel"
  64. ></el-input>
  65. <!-- <el-button @click="modelOpen" style="height: 40px;margin-left: 5px;" type="primary"
  66. plain><el-icon>
  67. <Coin style="color: #449DFD;" />
  68. </el-icon>选择模型</el-button> -->
  69. <div class="choose-base" @click="modelOpen">
  70. <img :src="database" alt="" />
  71. 选择模型
  72. </div>
  73. </el-form-item>
  74. <el-form-item label="报告模板" prop="reportNow">
  75. <el-select
  76. class="bestInput"
  77. style="width: 400px; height: 40px"
  78. @chang="bmChange"
  79. v-model="newMission.reportNow"
  80. placeholder="请选择模板"
  81. clearable
  82. >
  83. <el-option
  84. v-for="(item, index) in rmList"
  85. :label="item.name"
  86. :value="item.id"
  87. />
  88. </el-select>
  89. </el-form-item>
  90. <el-form-item style="color: #ccc; font-size: 12px"
  91. >模型说明:如果更改了检查模型,保存后需要对间隔列表及装置进行"重新解析"</el-form-item
  92. >
  93. <el-form-item prop="misMes">
  94. <template #label>
  95. <span style="color: red">任务说明</span>
  96. </template>
  97. <el-input
  98. style="width: 1136px"
  99. v-model="newMission.misMes"
  100. ></el-input>
  101. </el-form-item>
  102. <el-form-item label="SCD文件">
  103. <!-- <div style="width:100%;text-align: left;">{{ scdName }}</div> -->
  104. <el-upload
  105. ref="upload"
  106. class="upload-demo"
  107. :http-request="nowUpload"
  108. :limit="2"
  109. element-loading-text="上传中..."
  110. element-loading-background="rgba(255, 255, 255, 0.8)"
  111. :show-file-list="false"
  112. >
  113. <template #trigger>
  114. <!-- <el-button
  115. style="
  116. border-bottom: 1px solid #7bbafd;
  117. width: calc(100vw - 1000px);
  118. "
  119. type="primary"
  120. plain
  121. >{{ scdName ? scdName : "点击选择SCD文件" }}</el-button
  122. > -->
  123. <div class="clk-scd">
  124. <img :src="scdicon" alt="" />
  125. {{ scdName ? scdName : "点击选择SCD文件" }}
  126. </div>
  127. </template>
  128. </el-upload>
  129. <span
  130. style="margin-left: 10px; color: #3be078"
  131. v-loading="scdLoading"
  132. >{{
  133. textIs
  134. ? scdLoading
  135. ? "正在进行SCD间隔装置分析"
  136. : "SCD分析已完成"
  137. : ""
  138. }}
  139. </span>
  140. </el-form-item>
  141. </el-form>
  142. </div>
  143. <!-- 间隔、装置列表 -->
  144. <div>
  145. <el-button class="backs" @click="backMent">返回</el-button>
  146. <el-button
  147. style="width: 124px; height: 30px; background: #255ce7"
  148. @click="saveMent"
  149. type="primary"
  150. >保存</el-button
  151. >
  152. </div>
  153. <div class="gapAndUnit" v-if="successScd">
  154. <!-- 间隔列表 -->
  155. <div class="gapBox">
  156. <div
  157. class="interval"
  158. style="justify-content: space-between; margin: 5px"
  159. >
  160. <div class="interval">
  161. <img
  162. src="../../../assets/icon/DotsNine.png"
  163. alt=""
  164. class="img-interval"
  165. style="vertical-align: middle"
  166. />
  167. <span
  168. style="
  169. font-size: 16px;
  170. font-weight: 400;
  171. height: 24px;
  172. line-height: 24px;
  173. margin-left: 5px;
  174. "
  175. >间隔列表</span
  176. >
  177. </div>
  178. <div class="img-interval border-r" @click="addInterval">
  179. <img :src="addPng" class="img-interval" />
  180. </div>
  181. </div>
  182. <!-- <p :class="jgSelect == index ? 'result' : ''" v-for="(item, index) in jgList"
  183. style="text-align: left;cursor: pointer;" @click="jgClick(item, index)">
  184. {{ item.name }}
  185. </p> -->
  186. <!-- <el-tree :props="anyProps" :data="anyData" @node-click="handleCheckChange" /> -->
  187. <el-tree
  188. :props="anyProps"
  189. :data="anyData"
  190. @node-click="handleCheckChange"
  191. node-key="id"
  192. highlight-current
  193. >
  194. <template #default="{ node, data }">
  195. <div class="trees interval">
  196. <el-badge
  197. v-if="data.isLog"
  198. :value="data.filterLength"
  199. class="item"
  200. >
  201. <span>{{ node.label }}</span>
  202. </el-badge>
  203. <span v-else>{{ node.label }}</span>
  204. <img
  205. v-if="loadAreaId == data.area_id"
  206. @click="delInterval(data)"
  207. :src="ClosePng"
  208. alt=""
  209. class="img-interval-child"
  210. />
  211. </div>
  212. </template>
  213. </el-tree>
  214. </div>
  215. <!-- 装置列表 -->
  216. <div
  217. class="unitBox"
  218. v-loading="iedLoading"
  219. element-loading-text="正在解析间隔..."
  220. >
  221. <div
  222. style="
  223. display: flex;
  224. justify-content: flex-start;
  225. align-items: center;
  226. margin: 10px 10px;
  227. height: 43px;
  228. "
  229. >
  230. <div>
  231. <img
  232. src="../../../assets/icon/HardDrives.png"
  233. alt=""
  234. style="vertical-align: middle"
  235. />
  236. </div>
  237. <div style="height: 24px; margin-left: 5px">
  238. <span style="font-size: 16px; font-weight: 400"
  239. >装置列表——间隔:<em style="color: #255ce7">{{ jg }}</em></span
  240. >
  241. <span
  242. :title="flashLevel ? flashLevel : ''"
  243. style="
  244. font-size: 16px;
  245. cursor: pointer;
  246. font-weight: 400;
  247. margin-left: 30px;
  248. "
  249. >检测模型:<em style="color: #255ce7">{{
  250. flashLevel ? flashLevel.slice(0, 4) : ""
  251. }}</em></span
  252. >
  253. </div>
  254. <div
  255. style="
  256. position: absolute;
  257. top: 5px;
  258. right: 0px;
  259. display: flex;
  260. justify-content: center;
  261. align-items: center;
  262. "
  263. >
  264. <!-- <div style="margin: 0 10px;">
  265. <el-checkbox label="开启检测" size="large" />
  266. </div> -->
  267. <!-- <div style="margin: 5px">
  268. <el-button type="primary" size="small" plain
  269. >追加装置</el-button
  270. >
  271. </div> -->
  272. <div class="choose-base" @click="checkTime">追加装置</div>
  273. <div class="choose-base" @click="setIedExtrefNo">端子编号</div>
  274. <!-- <div style="margin: 5px">
  275. <el-button
  276. type="primary"
  277. size="small"
  278. plain
  279. @click="setIedExtrefNo"
  280. >端子编号</el-button
  281. >
  282. </div> -->
  283. </div>
  284. </div>
  285. <div style="margin: 10px; float: left">
  286. <!-- <div v-for="(item, index) in mx">
  287. {{ item.ied_name }}
  288. </div> -->
  289. <el-tag
  290. v-for="(item, index) in mx"
  291. :key="item.ied_name"
  292. @click="tagClick(item, index)"
  293. size="large"
  294. :class="item.isChoose ? 'mx-2' : 'mx-1'"
  295. closable
  296. effect="plain"
  297. @close="tagClose(item, index)"
  298. style="cursor: pointer"
  299. >
  300. {{ "[" + item.ied_name + "]" + (item.attr_desc || "") }}
  301. <span style="color: rgb(112, 112, 210); font-weight: bold">{{
  302. item.ied_no ? "NO:" + item.ied_no : ""
  303. }}</span>
  304. </el-tag>
  305. </div>
  306. </div>
  307. </div>
  308. <div v-if="successScd">
  309. <el-button class="backs cancel-add" @click="backMent">返回</el-button>
  310. <el-button style="width: 100px; height: 30px" @click="aginParseArea"
  311. >重新解析</el-button
  312. >
  313. <el-button class="sure-add" type="primary" @click="iedSave"
  314. >保存</el-button
  315. >
  316. </div>
  317. </div>
  318. <!-- 模态框组件 -->
  319. <div>
  320. <LookScd
  321. v-if="scdLooks"
  322. :scdLooks="scdLooks"
  323. @nowBack="nowBack"
  324. @lookNum="lookNum"
  325. ></LookScd>
  326. <ModelTree
  327. v-if="treeMool"
  328. :treeMool="treeMool"
  329. :treeNeed="treeNeed"
  330. :spaceInterval="spaceInterval"
  331. :checkedNodeNames="checkedNodeNames"
  332. @treeBack="treeBack"
  333. @treeNum="treeNum"
  334. >
  335. </ModelTree>
  336. <FlashCreate
  337. v-if="fcModal"
  338. :fcModal="fcModal"
  339. @fcBack="fcBack"
  340. ></FlashCreate>
  341. <CheckIed
  342. v-if="iedModal"
  343. :iedModal="iedModal"
  344. :loadScdId="loadScdId"
  345. @iedBack="iedBack"
  346. @iedArrBack="iedArrBack"
  347. >
  348. </CheckIed>
  349. </div>
  350. <el-dialog
  351. v-model="openAddInterval"
  352. width="25vw"
  353. style="height: 400px"
  354. append-to-body
  355. draggable
  356. >
  357. <template #header>
  358. <div class="my-header">
  359. <div class="title">添加间隔</div>
  360. </div>
  361. </template>
  362. <el-form
  363. :model="queryParams"
  364. :rules="rules"
  365. ref="queryRef"
  366. label-width="120px"
  367. >
  368. <el-form-item label="间隔名称" prop="area_name">
  369. <el-input v-model="queryParams.area_name" clearable></el-input>
  370. </el-form-item>
  371. <el-form-item label="间隔所属模型" prop="model_id">
  372. <el-select
  373. ref="levelRef"
  374. v-model="queryParams.model_id"
  375. placeholder="请选择所属模型"
  376. clearable
  377. style="width: 100%"
  378. >
  379. <el-option
  380. v-for="dict in spaceInterval"
  381. :key="dict.model_id"
  382. :label="dict.model_name"
  383. :value="dict.model_id"
  384. />
  385. </el-select>
  386. </el-form-item>
  387. <!-- <el-form-item label="检测间隔类型" prop="area_type">
  388. <el-select
  389. ref="levelRef"
  390. v-model="queryParams.area_type"
  391. placeholder="请选择间隔类型"
  392. clearable
  393. style="width: 100%"
  394. >
  395. <el-option
  396. v-for="dict in IntavalType"
  397. :key="dict.id"
  398. :label="dict.name"
  399. :value="dict.id"
  400. />
  401. </el-select>
  402. </el-form-item> -->
  403. </el-form>
  404. <template #footer>
  405. <span
  406. class="dialog-footer"
  407. style="display: flex; justify-content: center"
  408. >
  409. <el-button type="primary" class="sure-add" @click="sureAdd">
  410. 确认
  411. </el-button>
  412. <el-button @click="cancelClick" class="cancel-add">取消</el-button>
  413. </span>
  414. </template>
  415. </el-dialog>
  416. </div>
  417. </template>
  418. <script setup>
  419. import {
  420. ref,
  421. onMounted,
  422. reactive,
  423. watch,
  424. onBeforeUnmount,
  425. toRefs,
  426. nextTick,
  427. } from "vue";
  428. import { debounce } from "lodash";
  429. import flashPower from "../../../api/flashPower";
  430. import report from "@/api/report";
  431. import scd from "@/api/scd";
  432. import task from "@/api/task";
  433. import cid from "@/api/cid/cid";
  434. import LookScd from "../modalComp/LookScd.vue";
  435. import ModelTree from "../modalComp/ModelTree.vue";
  436. import FlashCreate from "../modalComp/FlashCreate.vue";
  437. import CheckIed from "../modalComp/CheckIed.vue";
  438. import database from "@/assets/image/database.png";
  439. import clickChose from "@/assets/image/click_chose.png";
  440. import scdicon from "@/assets/image/scdicon.png";
  441. import addPng from "@/assets/image/scdcheck/add.png";
  442. import ClosePng from "@/assets/image/Close.png";
  443. import systemRow from "@/api/systemRow";
  444. import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
  445. const props = defineProps({
  446. btnSelect: {
  447. type: Number,
  448. require: true,
  449. },
  450. taskList: {
  451. type: Array,
  452. require: true,
  453. },
  454. editRow: {
  455. type: Object,
  456. require: true,
  457. },
  458. status: {
  459. type: Number,
  460. require: true,
  461. },
  462. });
  463. let selects = props.btnSelect;
  464. let arrList = props.taskList;
  465. let newMission = ref({
  466. misName: "",
  467. misNum: "",
  468. flashId: "",
  469. reportNow: "",
  470. misMes: "",
  471. scdFolder: "",
  472. misId: "",
  473. cmodel: "",
  474. }); //创建任务提交表单
  475. //表单验证
  476. let missionRules = ref({
  477. misName: [{ required: true, message: "请输入名称", trigger: "blur" }],
  478. flashId: [{ required: true, message: "请选择变电站", trigger: "blur" }],
  479. reportNow: [{ required: true, message: "请选择模板", trigger: "blur" }],
  480. misMes: [{ required: true, message: "请输入任务说明", trigger: "blur" }],
  481. cmodel: [{ required: true, message: "请选择检测模型", trigger: "blur" }],
  482. }); //表单验证
  483. let flashList = ref([]); //表单选择的变电站
  484. let scdLooks = ref(false); //选择scd文件时的显示与否
  485. let treeMool = ref(false); //选择模型模态框 //选择模型显示与否
  486. let btnName = ref("点击选择scd文件"); //按钮内修改文字
  487. let jg = ref("请选择"); //间隔
  488. let jgList = ref([]); //间隔列表
  489. let jgSelect = ref(); //选择间隔
  490. let jgid = ref(""); //间隔id
  491. let mx = ref([]); //模型
  492. let mxList = ref([]); //模型列表
  493. let mxId = ref(""); //模型id
  494. let rmList = ref([]); //报告模板list
  495. let scdId = ref(""); //lookscd.vue返回的scdid
  496. let scdName = ref(""); //lookscd.vue返回的scdname
  497. let cmodel = ref("");
  498. let fcModal = ref(false); //创建变电站模态框
  499. let scdLoading = ref(false); //上传scd文件后进行分析
  500. let loadScdId = ref(0); //上传成功后拿到的scdid
  501. let successScd = ref(false); //保存任务后继续选择的间隔模型
  502. let iedModal = ref(false); //checkied.vue模态框状态
  503. let loadAreaId = ref(""); //area_id
  504. let iedName = ref(""); //一串ied名称字符串
  505. let iedLoading = ref(false); //加载ied
  506. let needEdit = ref({}); //需要编辑的任务
  507. const openAddInterval = ref(false); //打开添加间隔
  508. let anyProps = ref({
  509. label: "area_name",
  510. id: "area_id",
  511. });
  512. let treeNeed = ref([]); //modelTree.vue需要的回显数据
  513. let checkedNodeNames = ref([]);
  514. let anyData = ref([]);
  515. let states = ref(0);
  516. let flashLevel = ref("");
  517. const myForm = ref(null); //表单ref
  518. let saveLoading = ref(false);
  519. let editAndAdd = ref("新建检测任务");
  520. let textIs = ref(false);
  521. let filterLength = ref(0); //装置筛选有无attr_desc属性时的数组长度
  522. let editTask_models = ref([]); //编辑任务时的原模型列表。保存时需要与选择的模型进行差异对比
  523. const spaceInterval = ref([]); //所属间隔的数据
  524. watch(
  525. () => props.editRow,
  526. (newVal) => {
  527. needEdit.value = newVal;
  528. }
  529. );
  530. watch(
  531. () => props.status,
  532. (newValue, oldValue) => {
  533. if (newValue !== 2) {
  534. resetForm(); // 重置表单数据
  535. }
  536. }
  537. );
  538. const resetForm = () => {
  539. if (myForm.value) {
  540. myForm.value.resetFields();
  541. states.value = 1;
  542. }
  543. };
  544. const reload = () => {
  545. states.value = props.status;
  546. if (states.value == 2) {
  547. if (props.editRow.name) {
  548. needEdit.value = props.editRow;
  549. newMission.value.misName = needEdit.value.name; //任务名称
  550. newMission.value.misNum = needEdit.value.code;
  551. newMission.value.misId = needEdit.value.id; //任务id
  552. newMission.value.flashId = needEdit.value.station_id; //变电站id
  553. newMission.value.misMes = needEdit.value.memo; //备注或描述
  554. newMission.value.reportNow = needEdit.value.report_id; //报告模板
  555. loadScdId.value = needEdit.value.scd_id; //scdid
  556. editAndAdd.value = "编辑检测任务";
  557. task.getTaskById({ id: needEdit.value.id - 0 }).then((res) => {
  558. if (res.data != null && res.data.models != null) {
  559. let modelnames = res.data.models.map((item, index) => {
  560. return item.model_name;
  561. });
  562. editTask_models.value = res.data.models;
  563. spaceInterval.value = res.data.models;
  564. let treeNeedAry = [];
  565. spaceInterval.value = [];
  566. let arr = res.data.models.map((item, index) => {
  567. treeNeedAry.push(item.sys_model_id);
  568. spaceInterval.value.push({
  569. model_id: item.model_id,
  570. model_name: item.model_name,
  571. });
  572. return item.model_id;
  573. });
  574. newMission.value.cmodel = modelnames.join(",");
  575. mxId.value = arr;
  576. treeNeed.value = treeNeedAry;
  577. checkedNodeNames.value = modelnames;
  578. loadScdId.value = res.data.scd_id;
  579. scdName.value = res.data.scd_info.scd_name;
  580. successScd.value = true;
  581. loadAreaInfo(res.data.scd_id * 1);
  582. }
  583. });
  584. } else {
  585. return;
  586. }
  587. } else {
  588. return;
  589. }
  590. };
  591. const modelId = ref(null);
  592. const areaType = ref("");
  593. const loadAreaInfo = (scdid) => {
  594. mx.value = [];
  595. scd.getLoadScd({ scd_id: scdid }).then((res) => {
  596. iedLoading.value = false;
  597. if (res.code == 0) {
  598. successScd.value = true;
  599. anyData.value = [];
  600. if (res.data == null) {
  601. ElMessage({
  602. message: "未解析到间隔",
  603. type: "info",
  604. });
  605. return;
  606. }
  607. modelId.value = res.data.length ? res.data[0].model_id : null;
  608. anyData.value = res.data.map((item) => {
  609. //获取可能有问题的ied数量,比如没找到的装置
  610. let alertieds =
  611. item.ieds == null
  612. ? []
  613. : item.ieds.filter((r) => {
  614. return r.attr_desc == null || r.attr_desc == "";
  615. });
  616. return {
  617. ...item,
  618. isLog: alertieds.length > 0 ? true : false,
  619. filterLength: alertieds.length,
  620. }; // 使用展开运算符为每个对象添加一个名为 isLog 的新属性,并设置其值为 true
  621. });
  622. }
  623. });
  624. };
  625. //获取变电站
  626. const searchAllFlash = () => {
  627. flashPower.getAllArea({}).then((res) => {
  628. flashPower.getAllFlashPower({ pid: res.data[0].pid }).then((res) => {
  629. if (res.data == null) {
  630. return;
  631. } else {
  632. flashList.value = res.data.map((item) => {
  633. return {
  634. label: item.area_name,
  635. value: item.id,
  636. };
  637. });
  638. }
  639. });
  640. });
  641. report.getReport({}).then((res) => {
  642. rmList.value = res.data;
  643. });
  644. };
  645. //变电站下拉框change事件
  646. const flashChange = (e) => {
  647. // searchScd(e)
  648. newMission.value.flashId = e;
  649. };
  650. const bmChange = (e) => {
  651. newMission.value.reportNow = e.id;
  652. };
  653. //间隔点击
  654. const jgClick = (row, num) => {
  655. jg.value = row.name;
  656. jgSelect.value = num;
  657. jgid.value = row.id;
  658. };
  659. // 选择scd文件
  660. const chooseScdFile = () => {
  661. scdLooks.value = true;
  662. };
  663. // lookscd组件传回得数据
  664. const nowBack = (data, names, sid) => {
  665. scdLooks.value = data;
  666. if (names && sid) {
  667. newMission.value.scdFolder = sid;
  668. btnName.value = names;
  669. scd.getScdMiddle({ scd_id: sid }).then((res) => {
  670. console.log(res, "sid");
  671. });
  672. scd.getIedMiddle({ scd_id: sid }).then((res) => {
  673. console.log(res, "ied");
  674. });
  675. }
  676. };
  677. const saveMent = () => {
  678. successScd.value = false;
  679. //保存检测任务
  680. myForm.value.validate((val) => {
  681. if (val) {
  682. let tmpmodelid = mxId.value.toString().split(",");
  683. for (let i = 0; i < tmpmodelid.length; i++) {
  684. for (let j = 0; j < editTask_models.value.length; j++) {
  685. if (editTask_models.value[j].sys_model_id == null) {
  686. tmpmodelid[i] = editTask_models.value[j].model_id;
  687. break;
  688. }
  689. if (
  690. tmpmodelid[i] == editTask_models.value[j].sys_model_id ||
  691. tmpmodelid[i] == editTask_models.value[j].model_id
  692. ) {
  693. tmpmodelid[i] = editTask_models.value[j].model_id;
  694. break;
  695. }
  696. }
  697. }
  698. mxId.value = tmpmodelid.join(",");
  699. console.log("保存检测任务时的model_id", mxId.value);
  700. saveLoading.value = true;
  701. task
  702. .createTask({
  703. // id: newMission.value.misId - 0,
  704. code: newMission.value.misNum,
  705. id: needEdit.value.id - 0,
  706. name: newMission.value.misName,
  707. station_id: newMission.value.flashId - 0,
  708. memo: newMission.value.misMes,
  709. report_id: newMission.value.reportNow - 0,
  710. scd_id: loadScdId.value - 0,
  711. modelids: mxId.value.toString(),
  712. })
  713. .then((res) => {
  714. if (res.code == 0) {
  715. ElMessage({
  716. message: "创建成功",
  717. type: "success",
  718. });
  719. saveLoading.value = false;
  720. // emit("createBack", 0)
  721. loadAreaInfo(loadScdId.value * 1);
  722. reload(); //编辑 的时候
  723. } else {
  724. ElMessage({
  725. message: res.msg,
  726. type: "error",
  727. });
  728. saveLoading.value = false;
  729. }
  730. });
  731. }
  732. });
  733. };
  734. //文件上传
  735. const nowUpload = (e) => {
  736. if (scdLoading.value) {
  737. return;
  738. }
  739. const loading = ElLoading.service({
  740. lock: true,
  741. text: "文件上传中",
  742. background: "rgba(0, 0, 0, 0.7)",
  743. });
  744. cid
  745. .fileUpload({
  746. station_id: newMission.value.flashId - 0,
  747. data_type: "a_scd",
  748. file: e.file,
  749. })
  750. .then((res) => {
  751. scdLoading.value = true;
  752. if (res.code == 0) {
  753. loading.close();
  754. }
  755. scdName.value = res.data.filename;
  756. scd
  757. .loadScd({
  758. station_id: newMission.value.flashId - 0,
  759. scd_path: res.data.path,
  760. scd_name: res.data.filename,
  761. })
  762. .then((the) => {
  763. // scd.getLoadScd({ scd_id: the.data - 0 }).then(lod => {
  764. // console.log(lod,'rsasdas');
  765. if (the.code == 0) {
  766. loadScdId.value = the.data - 0;
  767. scdLoading.value = false;
  768. textIs.value = true;
  769. }
  770. // })
  771. });
  772. });
  773. };
  774. //树形组件
  775. const handleCheckChange = (e) => {
  776. console.log("e====", e);
  777. jg.value = e.area_name;
  778. loadAreaId.value = e.area_id;
  779. flashLevel.value = e.model_name.split("]")[1];
  780. //优先从间隔结果中查找其ied装置列表,如果没找到,则尝试调用接口获取
  781. let areaInfo = anyData.value.filter((r) => {
  782. return r.area_id == e.area_id;
  783. });
  784. if (
  785. areaInfo.length > 0 &&
  786. areaInfo.ieds != null &&
  787. areaInfo.ieds.length > 0
  788. ) {
  789. mx.value = areaInfo[0].ieds.map((item) => ({
  790. ...item,
  791. isChoose: false,
  792. }));
  793. iedName.value = mx.value.map((item) => item.ied_name).join(",");
  794. return;
  795. }
  796. //调用接口获取
  797. iedLoading.value = true;
  798. scd
  799. .getTikIed({ scd_id: loadScdId.value - 0, area_id: e.area_id - 0 })
  800. .then((res) => {
  801. if (res.data != null) {
  802. mx.value = res.data.map((item) => ({ ...item, isChoose: false }));
  803. iedName.value = mx.value.map((item) => item.ied_name).join(",");
  804. // 该循环是为了判断树形结构上是否有提示
  805. let ccc = res.data.map((param) => {
  806. if (!param.attr_desc) {
  807. return param;
  808. }
  809. });
  810. iedLoading.value = false;
  811. } else {
  812. mx.value = [];
  813. iedLoading.value = false;
  814. }
  815. });
  816. };
  817. const aginParseArea = () => {
  818. ElMessageBox.confirm("将清除原来的间隔数据,确定吗?", "间隔解析")
  819. .then(() => {
  820. iedLoading.value = true;
  821. scd
  822. .aginParseArea({ scd_id: loadScdId.value * 1 })
  823. .then((res) => {
  824. if (res.code == 0) {
  825. ElMessage({
  826. type: "success",
  827. message: "间隔解析成功!",
  828. duration: 1500,
  829. });
  830. loadAreaInfo(loadScdId.value * 1);
  831. } else {
  832. ElMessage({
  833. type: "error",
  834. message: res.msg,
  835. duration: 3000,
  836. });
  837. iedLoading.value = false;
  838. }
  839. })
  840. .catch((res) => {
  841. ElMessage({
  842. type: "error",
  843. message: "服务器发生异常!",
  844. duration: 3000,
  845. });
  846. });
  847. })
  848. .catch(() => {});
  849. };
  850. //保存ied状态
  851. const iedSave = () => {
  852. scd
  853. .stickIed({
  854. scd_id: loadScdId.value - 0,
  855. area_id: loadAreaId.value - 0,
  856. ied_ids: iedName.value,
  857. })
  858. .then((res) => {
  859. if (res.code == 0) {
  860. ElMessage({
  861. type: "success",
  862. message: "间隔装置设置保存成功!",
  863. duration: 1500,
  864. });
  865. loadAreaInfo(loadScdId.value * 1);
  866. } else {
  867. ElMessage({
  868. type: "error",
  869. message: res.msg,
  870. duration: 3000,
  871. });
  872. }
  873. });
  874. };
  875. const tagClose = (row, num) => {
  876. console.log("row", row, num);
  877. ElMessageBox.confirm(
  878. "确认从该间隔移除当前装置" + row.ied_name + "吗?",
  879. "删除装置"
  880. )
  881. .then(() => {
  882. mx.value.splice(num, 1);
  883. iedName.value = mx.value.map((item) => item.ied_name).join(",");
  884. })
  885. .catch(() => {});
  886. };
  887. //tag标签的点击事件
  888. const tagClick = (row, num) => {
  889. // 将所有对象的 isChoose 属性设置为 false
  890. mx.value.forEach((item) => {
  891. item.isChoose = false;
  892. });
  893. // 将当前点击的对象的 isChoose 属性设置为 true
  894. row.isChoose = true;
  895. };
  896. //打开选择ied
  897. const checkTime = () => {
  898. iedModal.value = true;
  899. };
  900. //新建变电站
  901. const addFlash = () => {
  902. fcModal.value = true;
  903. };
  904. const emit = defineEmits(["createBack"]);
  905. //返回切换
  906. const backMent = () => {
  907. emit("createBack", 0);
  908. };
  909. //modeltree传回数据
  910. const treeBack = (data) => {
  911. console.log("data", data);
  912. treeMool.value = data;
  913. };
  914. //选择模型打开模态框
  915. const modelOpen = () => {
  916. treeMool.value = true;
  917. };
  918. //模型树选择返回的模型数据 //modelTree.vue返回的id函数
  919. const treeNum = (data, name, chooseData) => {
  920. mxId.value = data;
  921. console.log("选中树返回的model_id mxId.value ", chooseData);
  922. // cmodel.value = name.toString()
  923. newMission.value.cmodel = name.toString();
  924. spaceInterval.value = chooseData;
  925. };
  926. const lookNum = (name, id) => {
  927. scdId.value = id;
  928. scd.getScdMiddle({ scd_id: id }).then((res) => {
  929. jgList.value = res.data;
  930. });
  931. scdName.value = name;
  932. };
  933. //flashcreate.vue返回的模态框值
  934. const fcBack = (data) => {
  935. fcModal.value = data;
  936. };
  937. //checkied.vue返回模态框状态
  938. const iedBack = (data) => {
  939. iedModal.value = data;
  940. };
  941. //checkied.vue返回选择数组
  942. const iedArrBack = (data) => {
  943. for (let i = 0; i < data.length; i++) {
  944. let obj = mx.value.filter((item) => item.ied_name == data[i].ied_name);
  945. if (obj != null && obj.length > 0) {
  946. ElMessage({
  947. type: "info",
  948. message: data[i].ied_name + ":该装置已存在!",
  949. duration: 3000,
  950. });
  951. return;
  952. }
  953. }
  954. mx.value = mx.value.concat(data);
  955. iedName.value = mx.value.map((item) => item.ied_name).join(",");
  956. };
  957. //设置装置信号端子收发编号
  958. const setIedExtrefNo = () => {
  959. if (mx.value == null || mx.value.length == 0) {
  960. ElMessage({
  961. message: "请先选择一个装置",
  962. type: "info",
  963. });
  964. return;
  965. }
  966. //获取当前选择的装置
  967. const ied = mx.value.filter((item) => {
  968. return item.isChoose == true;
  969. });
  970. if (ied.length == 0 || ied[0].attr_name == "") {
  971. ElMessage({
  972. message: "请先选择一个有效的装置",
  973. type: "info",
  974. });
  975. return;
  976. }
  977. ElMessageBox.prompt(
  978. '当装置是通过编号来确认端子信号收发(如PM接收的"线路5A相失灵"端子)时才设置此编号:',
  979. "装置端子编号",
  980. {
  981. confirmButtonText: "确定",
  982. cancelButtonText: "取消",
  983. inputPattern: /^[^\s]{0,5}$/,
  984. inputErrorMessage: "编号格式不正确:只支持不超过5位的字符!",
  985. inputValue: ied[0].ied_no,
  986. }
  987. )
  988. .then(({ value }) => {
  989. // 用户点击确定,value 是输入的内容
  990. scd
  991. .setAreaIedNo({
  992. area_id: loadAreaId.value * 1,
  993. ied_name: ied[0].attr_name,
  994. ied_no: value,
  995. })
  996. .then((res) => {
  997. if (res != null && res.code == 0) {
  998. ElMessage({
  999. message: "操作成功",
  1000. type: "success",
  1001. });
  1002. ied[0].ied_no = value;
  1003. let areaInfo = anyData.value.filter((r) => {
  1004. return r.area_id == loadAreaId.value;
  1005. });
  1006. areaInfo.ieds = []; //清除ieds,以便下次点击间隔时触发从后台重新获取装置列表
  1007. } else {
  1008. ElMessage({
  1009. message: "操作失败:" + res.msg,
  1010. type: "success",
  1011. });
  1012. }
  1013. });
  1014. })
  1015. .catch(() => {
  1016. // 用户点击取消或关闭对话框
  1017. });
  1018. };
  1019. //新增间隔
  1020. const data = reactive({
  1021. queryParams: {
  1022. scd_id: loadScdId.value - 0,
  1023. },
  1024. });
  1025. const queryRef = ref(null);
  1026. const { queryParams } = toRefs(data);
  1027. // 表单重置
  1028. const reset = () => {
  1029. queryParams.value = {
  1030. scd_id: loadScdId.value - 0,
  1031. model_id: null, //电压等级
  1032. area_type: null, //间隔
  1033. area_name: null, //装置类型
  1034. };
  1035. if (!queryRef.value) return;
  1036. queryRef.value.resetFields();
  1037. };
  1038. //添加间隔
  1039. const rules = reactive({
  1040. model_id: [{ required: true, message: "请选择间隔模型", trigger: "change" }],
  1041. area_name: [{ required: true, message: "请输入间隔名称", trigger: "blur" }],
  1042. });
  1043. const addInterval = () => {
  1044. reset();
  1045. openAddInterval.value = true;
  1046. };
  1047. const sureAdd = debounce(async () => {
  1048. queryRef.value.validate(async (val) => {
  1049. if (val) {
  1050. const data = {
  1051. ...queryParams.value,
  1052. model_id: queryParams.value.model_id * 1,
  1053. };
  1054. const res = await task.intervalAdd(data);
  1055. const meg =
  1056. res && res.code == 0
  1057. ? { type: "success", message: `添加成功` }
  1058. : { type: "error", message: res.msg };
  1059. ElMessage(meg);
  1060. loadAreaInfo(loadScdId.value * 1);
  1061. openAddInterval.value = res && res.code == 0?false:true;
  1062. }
  1063. });
  1064. }, 500);
  1065. const cancelClick = () => {
  1066. reset();
  1067. openAddInterval.value = false;
  1068. };
  1069. //删除间隔
  1070. const delInterval = (data) => {
  1071. console.log("data", data);
  1072. ElMessageBox.confirm(`确认删除 [${data.area_name}] 间隔吗?`, "提示", {
  1073. confirmButtonText: "确认",
  1074. cancelButtonText: "取消",
  1075. type: "warning",
  1076. })
  1077. .then(async () => {
  1078. const res = await task.intervalDel({
  1079. scd_id: loadScdId.value - 0,
  1080. area_id: data.area_id,
  1081. });
  1082. const meg =
  1083. res && res.code == 0
  1084. ? { type: "success", message: `删除成功` }
  1085. : { type: "error", message: `删除失败` };
  1086. ElMessage(meg);
  1087. if (res && res.code == 0) {
  1088. loadAreaInfo(loadScdId.value * 1);
  1089. }
  1090. })
  1091. .catch(() => {});
  1092. };
  1093. //获取间隔类型
  1094. const IntavalType = ref(null);
  1095. const getIntavalType = async () => {
  1096. const res = await systemRow.getChildren({ code: "area_type" });
  1097. IntavalType.value = res ? res.data : null;
  1098. };
  1099. onMounted(() => {
  1100. searchAllFlash();
  1101. getIntavalType();
  1102. reload();
  1103. });
  1104. onBeforeUnmount(() => {
  1105. resetForm();
  1106. });
  1107. </script>
  1108. <style scoped lang="scss">
  1109. em {
  1110. font-style: normal;
  1111. color: #5779d7;
  1112. margin-right: 5px;
  1113. }
  1114. .createMisBox {
  1115. width: 100%;
  1116. height: calc(100vh - 150px);
  1117. text-align: center;
  1118. margin-top: 20px;
  1119. /* line-height: calc(100vh - 150px); */
  1120. }
  1121. .formBox {
  1122. width: 1136px;
  1123. height: 360px;
  1124. margin: 0 auto;
  1125. /* border-bottom: 1px dashed #dbdbdb; */
  1126. }
  1127. .bestInput {
  1128. width: 360px;
  1129. height: 40px;
  1130. border-radius: 2px 2px 2px 2px;
  1131. }
  1132. .gapAndUnit {
  1133. width: 1136px;
  1134. /* height: 150px; */
  1135. /* border: 1px solid black; */
  1136. margin: 5px auto;
  1137. display: flex;
  1138. justify-content: space-around;
  1139. align-items: center;
  1140. }
  1141. .gapBox {
  1142. width: 288px;
  1143. height: calc(100vh - 640px);
  1144. overflow-y: auto;
  1145. border: 1px solid #5779d7;
  1146. }
  1147. .unitBox {
  1148. width: 832px;
  1149. height: calc(100vh - 640px);
  1150. overflow-y: auto;
  1151. border: 1px solid #5779d7;
  1152. position: relative;
  1153. }
  1154. .result {
  1155. color: #5779d7;
  1156. }
  1157. .chooseSpan {
  1158. width: 150px;
  1159. height: 30px;
  1160. margin-left: 10px;
  1161. border: 1px solid blue;
  1162. text-align: center;
  1163. line-height: 30px;
  1164. }
  1165. .mx-1 {
  1166. float: left;
  1167. min-width: 100px;
  1168. height: 30px;
  1169. margin-right: 10px;
  1170. margin-top: 5px;
  1171. margin-bottom: 5px;
  1172. border: 1px solid #A3ADE0;
  1173. color: #1a2447;
  1174. padding: 19px 7px;
  1175. :deep(.el-icon svg) {
  1176. /* color: red; */
  1177. color: #a3ade0;
  1178. }
  1179. }
  1180. .mx-2 {
  1181. float: left;
  1182. min-width: 100px;
  1183. height: 30px;
  1184. margin-right: 10px;
  1185. margin-top: 5px;
  1186. margin-bottom: 5px;
  1187. border: 1px solid #255ce7;
  1188. background-color: #f6f9ff;
  1189. color: #255ce7;
  1190. padding: 19px 7px;
  1191. :deep(.el-icon svg) {
  1192. /* color: red; */
  1193. color: #255ce7;
  1194. }
  1195. }
  1196. :deep(.el-form--inline .el-form-item) {
  1197. margin-right: 12px !important;
  1198. margin-bottom: 10px !important;
  1199. }
  1200. :deep(.el-select .el-input__wrapper) {
  1201. height: 38px;
  1202. }
  1203. .demo-form-inline:nth-child(2) {
  1204. background-color: red;
  1205. }
  1206. .my-red-label {
  1207. color: red;
  1208. }
  1209. :deep(.el-tag--large .el-tag__close) {
  1210. margin-left: 25px;
  1211. }
  1212. .choose-base {
  1213. height: 42px;
  1214. margin-left: 5px;
  1215. width: 112px;
  1216. font-size: 14px;
  1217. color: #255ce7;
  1218. display: flex;
  1219. flex-direction: row;
  1220. align-items: center;
  1221. justify-content: center;
  1222. cursor: pointer;
  1223. background: url("~@/assets/image/scdcheck/bgscd.png") no-repeat center;
  1224. background-size: 112px 48px;
  1225. img {
  1226. width: 20px;
  1227. height: 20px;
  1228. margin: 0 4px 0 0;
  1229. }
  1230. }
  1231. :deep(.el-form-item__label) {
  1232. color: #1a2447;
  1233. }
  1234. .clk-scd {
  1235. width: 954px;
  1236. background: url("~@/assets/image/click_chose.png") no-repeat center;
  1237. color: #255ce7;
  1238. background-size: 954px 45px;
  1239. height: 45px;
  1240. line-height: 45px;
  1241. img {
  1242. width: 20px;
  1243. height: 20px;
  1244. margin: 0 4px 0 0;
  1245. vertical-align: middle;
  1246. }
  1247. }
  1248. .backs {
  1249. width: 124px;
  1250. height: 30px;
  1251. background: #f1f3f9;
  1252. box-shadow: inset 0px 2px 1px 0px rgba(255, 255, 255, 0.6),
  1253. 0px 2px 4px 0px rgba(138, 157, 205, 0.63);
  1254. }
  1255. .interval {
  1256. display: flex;
  1257. align-items: center;
  1258. }
  1259. .img-interval {
  1260. width: 20px;
  1261. height: 20px;
  1262. }
  1263. .img-interval-child {
  1264. width: 14px;
  1265. height: 14px;
  1266. border: 1px solid #e50505;
  1267. border-radius: 3px;
  1268. }
  1269. .border-r {
  1270. border: 1px solid #255ce7;
  1271. border-radius: 3px;
  1272. }
  1273. .trees {
  1274. width: 90%;
  1275. justify-content: space-between;
  1276. img {
  1277. margin-right: 3px;
  1278. }
  1279. }
  1280. .my-header {
  1281. border-bottom: 1px solid #a3ade0;
  1282. font-size: 16px;
  1283. color: #1a2447;
  1284. .title {
  1285. padding-bottom: 15px;
  1286. }
  1287. }
  1288. .sure-add {
  1289. width: 100px;
  1290. height: 30px;
  1291. background: #255ce7;
  1292. }
  1293. .cancel-add {
  1294. width: 100px;
  1295. height: 30px;
  1296. background: #f1f3f9;
  1297. }
  1298. </style>