areaCard.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /* 自定义tabs */
  2. <template>
  3. <div class="body" :style="style">
  4. <img class="logo" src="../../assets/img/logo.png" alt="">
  5. <div class="title">{{ title }}</div>
  6. <div style="margin-top: 50px; height:85%;" @contextmenu="contextmenu">
  7. <el-scrollbar>
  8. <div class="scoll">
  9. <div class="matrix" v-if="startList.length>0">
  10. <div class="problemTitle">启动</div>
  11. <MatrixBlock @on-click="handleDetial" @choose-click="handleClick" :dataList="startList">
  12. </MatrixBlock>
  13. </div>
  14. <div class="matrix" v-if="stopList.length>0">
  15. <div class="problemTitle">停机</div>
  16. <MatrixBlock @on-click="handleDetial" @choose-click="handleClick" :dataList="stopList">
  17. </MatrixBlock>
  18. </div>
  19. </div>
  20. </el-scrollbar>
  21. </div>
  22. <div v-if="current===1" class="send" @click="handleSend">发送</div>
  23. <div class="success" v-if="showFlag&&current===0">指令发送成功</div>
  24. </div>
  25. <WindturbineDetailPages v-model="dialogVisible" :showSvg="showSvg" @close="handleClose" :svgWeb="svgWeb"
  26. :stationName="stationName" :windturbine="currentWindturbine"></WindturbineDetailPages>
  27. </template>
  28. <script>
  29. import BackgroundData from 'utils/BackgroundData'
  30. import WindturbineDetailPages from "../WindturbineDetailPages.vue";
  31. import MatrixBlock from "../matrixBlock.vue";
  32. import MessageBridge from 'utils/MessageBridge'
  33. export default {
  34. name: 'gy-card',
  35. components: {
  36. MatrixBlock,
  37. WindturbineDetailPages
  38. },
  39. created: function () {
  40. this.initData();
  41. this.suggestion();
  42. },
  43. emits: ["parentRun"],
  44. props: {
  45. title: {
  46. type: String,
  47. default: '',
  48. required: true,
  49. },
  50. height: {
  51. type: Number,
  52. default: 200,
  53. },
  54. },
  55. data() {
  56. return {
  57. current:1,
  58. windturbinelist: {},
  59. titleList: [],
  60. startList: [],
  61. stopList: [],
  62. chooseList: [],
  63. sendList: [],
  64. currentWindturbine: {},
  65. dialogVisible: false,
  66. showSvg: false,
  67. showFlag: false,
  68. svgWeb: '',
  69. stationName: '',
  70. // 定时器
  71. timer: "",
  72. controlErorCodes: [
  73. "控制成功",
  74. "控制命令发送失败",
  75. "无效的控制地址",
  76. "被控设备异常",
  77. "无效的控制功能",
  78. "网络连接错误,检查场站通信",
  79. "控制结果读取超时",
  80. "未知错误",
  81. "控制命令错误",
  82. "收到无法识别数据",
  83. "未读取到数据包",
  84. "未知错误",
  85. "风机操作过频繁",
  86. "风机被挂牌",
  87. "风机操作与风机状态不符",
  88. "需要登录",
  89. ],
  90. boosterStation: {
  91. 'MHS_SYZ': {
  92. name: '麻黄山升压站'
  93. },
  94. 'NSS_SYZ': {
  95. name: '牛首山升压站'
  96. },
  97. 'QS_SYZ': {
  98. name: '青山升压站'
  99. },
  100. 'QS3_SYZ': {
  101. name: '青山三期升压站'
  102. },
  103. 'SBQ_SYZ': {
  104. name: '石板泉升压站'
  105. },
  106. 'XS_SYZ': {
  107. name: '香山升压站'
  108. },
  109. 'DWK_SYZ': {
  110. name: '大武口升压站'
  111. },
  112. 'PL_SYZ': {
  113. name: '平罗升压站'
  114. },
  115. 'PL2_SYZ': {
  116. name: '平罗二期升压站'
  117. },
  118. 'XH_SYZ': {
  119. name: '宣和升压站'
  120. },
  121. 'MCH_SYZ': {
  122. name: '马场湖升压站'
  123. },
  124. 'HZJ_SYZ': {
  125. name: '海子井升压站'
  126. },
  127. }
  128. }
  129. },
  130. computed: {
  131. style() {
  132. return `width: 100%; height: ${this.height}vh;`
  133. },
  134. },
  135. methods: {
  136. control(current){
  137. this.current = current
  138. },
  139. initData: function () {
  140. var mb = MessageBridge.getInstance();
  141. var vs = [{ key: "/topic/suggestion", action: this.suggestion }];
  142. var vss = [{ key: "/topic/voice-control", action: this.windturbineMessage }];
  143. mb.register(vs);
  144. mb.register(vss);
  145. },
  146. suggestion(msg, headers) {
  147. this.titleList = msg?JSON.parse(msg):this.$store.state.suggestion
  148. if (this.current === 0) {
  149. let dateList = []
  150. this.titleList.forEach(item => {
  151. item.operateStyle === 'Start' ? this.windturbinelist[item.windturbineId].controlType = 1 : this.windturbinelist[item.windturbineId].controlType = 2
  152. dateList.push(this.windturbinelist[item.windturbineId])
  153. })
  154. let mss = {}
  155. mss.type = 'send'
  156. this.timer = setTimeout(() => {
  157. this.menuClicked(mss, dateList, 'automatic')
  158. this.showFlag = false
  159. clearInterval(this.timer);
  160. }, 3000);
  161. }
  162. },
  163. windturbineMessage(msg) {
  164. let arr = []
  165. if (msg === 'CLOSE') {
  166. arr.push(msg)
  167. } else {
  168. arr = msg.split('-')
  169. }
  170. this.dialogVisible = false
  171. this.showSvg = false
  172. this.svgWeb = ''
  173. console.log(arr);
  174. if (arr[0] === 'OPEN_FJ') {
  175. this.currentWindturbine = this.windturbinelist[arr[1]]
  176. this.dialogVisible = true;
  177. } else if (arr[0] === 'CLOSE') {
  178. this.dialogVisible = false
  179. } else if (arr[0] === 'OPEN_SYZ') {
  180. this.showSvg = true
  181. this.dialogVisible = true
  182. this.svgWeb = arr[1];
  183. this.stationName = this.boosterStation[arr[1]].name
  184. } else if (arr[0] === 'CONTROL_START' || arr[0] === 'CONTROL_STOP' || arr[0] === 'CONTROL_MAINTAIN') {
  185. let windControlList=[];
  186. let mss = {}
  187. for(var i=1;i<arr.length;i++){
  188. windControlList[i-1]=this.windturbinelist [arr[i]];
  189. switch (arr[0]) {
  190. case 'CONTROL_START':
  191. //mss.controlType = '1'
  192. windControlList[i-1].controlType = '1'
  193. break
  194. case 'CONTROL_STOP':
  195. //mss.controlType = '2'
  196. windControlList[i-1].controlType = '2'
  197. break
  198. case 'CONTROL_MAINTAIN':
  199. //mss.controlType = '6'
  200. windControlList[i-1].controlType = '6'
  201. break
  202. }
  203. }
  204. /* arr.forEach(item =>{
  205. if(item === (this.windturbinelist[item]?this.windturbinelist[item].windturbineId:'')){
  206. windControlList.push(this.windturbinelist [item])
  207. switch (arr[0]) {
  208. case 'CONTROL_START':
  209. //mss.controlType = '1'
  210. break
  211. case 'CONTROL_STOP':
  212. //mss.controlType = '2'
  213. break
  214. case 'CONTROL_MAINTAIN':
  215. //mss.controlType = '6'
  216. break
  217. }
  218. }
  219. }) */
  220. //let windturbine = this.windturbinelist[arr[1]]
  221. /* switch (arr[0]) {
  222. case 'CONTROL_START':
  223. mss.controlType = '1'
  224. break
  225. case 'CONTROL_STOP':
  226. mss.controlType = '2'
  227. break
  228. case 'CONTROL_MAINTAIN':
  229. mss.controlType = '6'
  230. break
  231. } */
  232. mss.type = 'send'
  233. this.menuClicked(mss, windControlList,true)
  234. }
  235. // else if (arr[0] === 'CONTROL_LOCK_OVERHAUL' || arr[0] === 'CONTROL_LOCK_MAINTAIN' || arr[0] === 'CONTROL_LOCK_LNVOLVED_OVERHAUL' ||
  236. // arr[0] === 'CONTROL_LOCK_LNVOLVED_MAINTAIN' || arr[0] === 'CONTROL_LOCK_LNVOLVED_PG' || arr[0] === 'CONTROL_LOCK_LNVOLVED_WEATHER' || arr[0] === 'CONTROL_UNLOCK') {
  237. // let windturbine = this.windturbinelist[arr[1]]
  238. // switch (arr[0]) {
  239. // case 'CONTROL_LOCK_OVERHAUL':
  240. // this.menuClicked({ type: "lock", value: "CheckLock" }, windturbine);
  241. // break;
  242. // case 'CONTROL_LOCK_MAINTAIN':
  243. // this.menuClicked({ type: "lock", value: "FaultLock" }, windturbine);
  244. // break;
  245. // case 'CONTROL_LOCK_LNVOLVED_OVERHAUL':
  246. // this.menuClicked({ type: "lock", value: "StationCheckLock" }, windturbine);
  247. // break;
  248. // case 'CONTROL_LOCK_LNVOLVED_MAINTAIN':
  249. // this.menuClicked({ type: "lock", value: "StationFaulLock" }, windturbine);
  250. // break;
  251. // case 'CONTROL_LOCK_LNVOLVED_PG':
  252. // this.menuClicked({ type: "lock", value: "StationPowerLineLock" }, windturbine);
  253. // break;
  254. // case 'CONTROL_LOCK_LNVOLVED_WEATHER':
  255. // this.menuClicked({ type: "lock", value: "StationWeatherLock" }, windturbine);
  256. // break;
  257. // case 'CONTROL_UNLOCK':
  258. // this.menuClicked({ type: "lock", value: "UnLock" }, windturbine);
  259. // break;
  260. // }
  261. // }
  262. },
  263. handleClick(values) {
  264. if (values.active) {
  265. let showIndex = null
  266. this.chooseList.forEach((item, index) => {
  267. if (item.windturbineId === values.windturbineId) {
  268. showIndex = index
  269. }
  270. })
  271. this.chooseList.splice(showIndex, 1);
  272. } else {
  273. this.chooseList.push(values)
  274. }
  275. this.startList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
  276. this.stopList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
  277. },
  278. handleDetial(itm) {
  279. this.dialogVisible = true;
  280. this.currentWindturbine = itm;
  281. },
  282. handleClose() {
  283. this.dialogVisible = false
  284. this.showSvg = false
  285. },
  286. handleSend() {
  287. if (this.chooseList.length > 0) {
  288. this.menuClicked({ type: "send" });
  289. }
  290. },
  291. /* 右键菜单 */
  292. contextmenu() {
  293. const { remote } = require("electron");
  294. var that = this;
  295. const menuTemplate = [
  296. {
  297. label: "发送",
  298. click() {
  299. that.menuClicked({ type: "send" });
  300. },
  301. },
  302. {
  303. label: "挂牌",
  304. submenu: [
  305. {
  306. label: "检修",
  307. click() {
  308. that.menuClicked({ type: "lock", value: "CheckLock" });
  309. },
  310. },
  311. {
  312. label: "故障维修",
  313. click() {
  314. that.menuClicked({ type: "lock", value: "FaultLock" });
  315. },
  316. },
  317. {
  318. label: "场内受累检修",
  319. click() {
  320. that.menuClicked({ type: "lock", value: "StationCheckLock" });
  321. },
  322. },
  323. {
  324. label: "场内受累故障",
  325. click() {
  326. that.menuClicked({ type: "lock", value: "StationFaulLock" });
  327. },
  328. },
  329. {
  330. label: "场外受累电网",
  331. click() {
  332. that.menuClicked({
  333. type: "lock",
  334. value: "StationPowerLineLock",
  335. });
  336. },
  337. },
  338. {
  339. label: "场外受累天气",
  340. click() {
  341. that.menuClicked({ type: "lock", value: "StationWeatherLock" });
  342. },
  343. },
  344. ],
  345. },
  346. // {
  347. // label: "标注",
  348. // click() {
  349. // that.menuClicked({ type: "marking" });
  350. // },
  351. // },
  352. ];
  353. const menu = remote.Menu.buildFromTemplate(menuTemplate);
  354. menu.popup(remote.getCurrentWindow());
  355. },
  356. menuClicked(msg, windturbine, automatic) {
  357. var bd = BackgroundData.getInstance();
  358. if (!bd.LoginUser) {
  359. this.$notify({
  360. title: "请登录",
  361. message: "控制风机需要先登录!",
  362. type: "warning",
  363. position: "bottom-right",
  364. offset: 60,
  365. duration: 3000,
  366. });
  367. return;
  368. }
  369. if (msg.type == "lock") {
  370. // 挂牌
  371. this.chooseList.forEach(item => {
  372. item.lockType = msg.value;
  373. })
  374. bd.windturbineControl(
  375. this.chooseList,
  376. true,
  377. '',
  378. this.controlSuccess,
  379. this.controlError
  380. );
  381. } else if (msg.type == "send") {
  382. // 发送
  383. let sendList = []
  384. if (automatic) {
  385. sendList = windturbine
  386. }
  387. else if (windturbine) {
  388. //windturbine.controlType = msg.controlType
  389. sendList.push(windturbine)
  390. } else {
  391. this.chooseList.forEach(item => {
  392. if (item.operateStyle === "Start") {
  393. item.controlType = 1
  394. } else if (item.operateStyle === "Stop") {
  395. item.controlType = 2
  396. }
  397. })
  398. sendList = this.chooseList
  399. }
  400. this.showFlag = true
  401. if (sendList.length > 0) {
  402. bd.checkout(sendList);
  403. if (automatic) {
  404. bd.windturbineControl(
  405. sendList,
  406. false,
  407. 'automatic',
  408. this.controlSuccess,
  409. this.controlError
  410. );
  411. } else {
  412. bd.windturbineControl(
  413. sendList,
  414. false,
  415. '',
  416. this.controlSuccess,
  417. this.controlError
  418. );
  419. }
  420. }
  421. } else if (msg.type == "marking") {
  422. // 标注
  423. var vvs = this.getSelectedItems();
  424. bd.marking(vvs);
  425. }
  426. this.clearSelected();
  427. },
  428. clearSelected() {
  429. this.startList.forEach(item => {
  430. item.active = false
  431. })
  432. this.stopList.forEach(item => {
  433. item.active = false
  434. })
  435. this.chooseList = []
  436. },
  437. /* 控制成功 */
  438. controlSuccess(msg) {
  439. var bd = BackgroundData.getInstance();
  440. console.log(msg);
  441. if (msg.data || msg.data !== {}) {
  442. var mss = ''; // 信息
  443. var iserror = false;// 是否有控制错误的风机
  444. for (var v in msg.data) {
  445. var val = msg.data[v];
  446. if (val.errorCode > 0) {
  447. iserror = true;
  448. mss += `${val.windturbineId} ${this.controlErorCodes[val.errorCode]}\n`;
  449. }
  450. }
  451. var tp = iserror ? "warning" : "success";
  452. var dt = iserror ? 0 : 4500;
  453. if (!iserror) {
  454. mss = "控制成功";
  455. }
  456. this.$notify({
  457. title: "控制",
  458. message: mss,
  459. type: tp,
  460. position: "bottom-right",
  461. offset: 60,
  462. duration: 3000,
  463. });
  464. } else {
  465. this.$notify({
  466. title: "控制出现错误",
  467. message: '控制失败,请重试',
  468. type: "warning",
  469. position: "bottom-right",
  470. offset: 60,
  471. duration: 3000,
  472. });
  473. }
  474. },
  475. /* 控制失败 */
  476. controlError(err) {
  477. this.$notify({
  478. title: "控制出现错误",
  479. message: err.message,
  480. type: "warning",
  481. position: "bottom-right",
  482. offset: 60,
  483. duration: 3000,
  484. });
  485. },
  486. },
  487. watch: {
  488. "$store.getters.windturbinelist": {
  489. deep: true,
  490. handler: function (json) {
  491. this.windturbinelist = json
  492. let arr = Object.keys(json).sort()
  493. this.stopList = []
  494. this.startList = []
  495. for (var id of arr) {
  496. var val = json[id];
  497. this.chooseList.forEach(item => {
  498. if (item.windturbineId === val.windturbineId) {
  499. val.active = true
  500. }
  501. })
  502. this.titleList.forEach(item => {
  503. if (item.windturbineId === val.windturbineId) {
  504. val.operateStyle = item.operateStyle
  505. if (item.operateStyle === "Start" && val.status === 2) {
  506. this.startList.push(val)
  507. } else if (item.operateStyle === "Stop" && val.status === 4) {
  508. this.stopList.push(val)
  509. }
  510. }
  511. })
  512. }
  513. let checkoutList = BackgroundData.getInstance().checkouts;
  514. checkoutList.forEach(item => {
  515. let showIndex = null
  516. let starFlag = false
  517. let stopFlag = false
  518. this.startList.forEach((param, index) => {
  519. if (item.windturbineId === param.windturbineId) {
  520. showIndex = index
  521. starFlag = true
  522. }
  523. })
  524. this.stopList.forEach((param, index) => {
  525. if (item.windturbineId === param.windturbineId) {
  526. showIndex = index
  527. stopFlag = true
  528. }
  529. })
  530. starFlag ? this.startList.splice(showIndex, 1) : '';
  531. stopFlag ? this.stopList.splice(showIndex, 1) : '';
  532. })
  533. },
  534. },
  535. "$store.getters.current": {
  536. handler: function (json) {
  537. this.current = json
  538. if (json === 0) {
  539. let dateList = []
  540. this.titleList.forEach(item => {
  541. item.operateStyle === 'Start' ? this.windturbinelist[item.windturbineId].controlType = 1 : this.windturbinelist[item.windturbineId].controlType = 2
  542. dateList.push(this.windturbinelist[item.windturbineId])
  543. })
  544. let mss = {}
  545. mss.type = 'send'
  546. this.timer = setTimeout(() => {
  547. this.menuClicked(mss, dateList, 'automatic')
  548. this.showFlag = false
  549. clearInterval(this.timer);
  550. }, 3000);
  551. }
  552. }
  553. }
  554. },
  555. }
  556. </script>
  557. <style scoped="scoped">
  558. .body {
  559. border: 1px solid #373737;
  560. width: 100%;
  561. margin-left: 15px;
  562. margin-top: 20px;
  563. }
  564. .body .scoll {
  565. height: 91%;
  566. }
  567. .title {
  568. color: #ffffff;
  569. font-size: 14px;
  570. margin-left: 32px;
  571. /* margin-top: 12px; */
  572. margin-bottom: 10px;
  573. /* width: 570px; */
  574. width: 29vw;
  575. height: 50px;
  576. display: flex;
  577. align-items: center;
  578. position: absolute;
  579. background-color: #000000;
  580. }
  581. .title::before {
  582. z-index: 1;
  583. content: '';
  584. position: absolute;
  585. left: -18px !important;
  586. /* top: 30px !important; */
  587. width: 5px;
  588. height: 5px;
  589. background-color: #54B75A;
  590. border-radius: 50%;
  591. }
  592. .logo {
  593. position: absolute;
  594. top: 12px;
  595. left: 12px;
  596. }
  597. .matrix {
  598. margin-left: 20px;
  599. margin-right: 10px;
  600. padding-bottom: 20px;
  601. border-bottom: 1px solid rgba(31, 31, 31, 1);
  602. }
  603. .problemTitle {
  604. font-size: 12px;
  605. color: #BFBFBF;
  606. margin-top: 20px;
  607. margin-bottom: 20px;
  608. margin-left: 12px;
  609. }
  610. .send {
  611. width: 86px;
  612. height: 26px;
  613. display: flex;
  614. align-items: center;
  615. justify-content: center;
  616. background-color: rgba(84, 183, 90, 1);
  617. color: #ffffff;
  618. font-size: 14px;
  619. position: absolute;
  620. bottom: 20px;
  621. right: 10px;
  622. }
  623. .success {
  624. display: flex;
  625. align-items: center;
  626. justify-content: center;
  627. width: 250px;
  628. height: 48px;
  629. position: absolute;
  630. bottom: 20px;
  631. right: 20%;
  632. border: 1px solid rgba(55, 55, 55, 1);
  633. border-radius: 10px;
  634. color: #ffffff;
  635. font-size: 14px;
  636. }
  637. </style>