areaCard.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /* 自定义tabs */
  2. <template>
  3. <!-- <transition>
  4. <div :class='areaClass' @mouseover="hover = false" @mouseleave="hover = false" onselectstart="return false">
  5. <div :class="headerClass">
  6. <div :class='circleClass'></div>
  7. <span class="gy-card-title">{{ title }}</span>
  8. <img class="gy-card-decoration01" src="../../assets/img/controlcenter/decoration01.png">
  9. <img class="gy-card-decoration02" src="../../assets/img/controlcenter/decoration02.png">
  10. </div>
  11. <div :class='contentClass'>
  12. <el-scrollbar style="height: 100%">
  13. <slot></slot>
  14. </el-scrollbar>
  15. </div>
  16. </div>
  17. </transition> -->
  18. <div class="body" :style="style">
  19. <img class="logo" src="../../assets/img/logo.png" alt="">
  20. <div class="title">{{ title }}</div>
  21. <div style="margin-top: 50px; height: 94%;" @contextmenu="contextmenu">
  22. <el-scrollbar>
  23. <div class="scoll">
  24. <div class="matrix" v-if="faultList.length>0">
  25. <div class="problemTitle">故障</div>
  26. <MatrixBlock area="problem" @problem-click="handleClick" @on-click="handleDetails"
  27. :dataList="faultList"></MatrixBlock>
  28. </div>
  29. <div class="matrix" v-if="maintainList.length>0">
  30. <div class="problemTitle">维护</div>
  31. <MatrixBlock area="problem" @problem-click="handleClick" @on-click="handleDetails"
  32. :dataList="maintainList"></MatrixBlock>
  33. </div>
  34. <div class="matrix" v-if="offlineList.length>0">
  35. <div class="problemTitle">离线</div>
  36. <MatrixBlock area="problem" @problem-click="handleClick" @on-click="handleDetails"
  37. :dataList="offlineList"></MatrixBlock>
  38. </div>
  39. <div class="matrix" v-if="listedList.length>0">
  40. <div class="problemTitle">挂牌</div>
  41. <MatrixBlock area="problem" @problem-click="handleClick" @on-click="handleDetails"
  42. :dataList="listedList"></MatrixBlock>
  43. </div>
  44. </div>
  45. </el-scrollbar>
  46. </div>
  47. </div>
  48. <WindturbineDetailPages v-model="dialogVisible" :showSvg="showSvg" @close="handleClose"
  49. :windturbine="currentWindturbine"></WindturbineDetailPages>
  50. </template>
  51. <script>
  52. import BackgroundData from 'utils/BackgroundData'
  53. import WindturbineDetailPages from "../WindturbineDetailPages.vue";
  54. import MatrixBlock from "../matrixBlock.vue";
  55. export default {
  56. name: 'gy-card',
  57. components: {
  58. WindturbineDetailPages,
  59. MatrixBlock
  60. },
  61. emits: ["parentRun"],
  62. props: {
  63. title: {
  64. type: String,
  65. default: '校验区',
  66. required: true
  67. },
  68. height: {
  69. type: Number,
  70. default: 200,
  71. },
  72. areaStyle: {
  73. type: String,
  74. default: 'check',
  75. required: true
  76. },
  77. circleStyle: {
  78. type: String,
  79. default: 'green',
  80. required: true
  81. },
  82. contentStyle: {
  83. type: String,
  84. default: '44',
  85. required: true
  86. },
  87. showFlag: {
  88. type: Boolean,
  89. default: false,
  90. }
  91. },
  92. data() {
  93. return {
  94. aaa: '3',
  95. dialogVisible: false,
  96. currentWindturbine: {},
  97. values: [],
  98. hover: false,
  99. big: false,
  100. current: 0,
  101. faultList: [],
  102. maintainList: [],
  103. offlineList: [],
  104. listedList: [],
  105. chooseList: [],
  106. titleList: [
  107. {
  108. id: 0,
  109. title: '麻黄山',
  110. },
  111. {
  112. id: 1,
  113. title: '牛首山',
  114. },
  115. {
  116. id: 2,
  117. title: '青山',
  118. },
  119. {
  120. id: 3,
  121. title: '石板泉',
  122. },
  123. {
  124. id: 4,
  125. title: '香山',
  126. },
  127. ],
  128. currentWindturbine: {},
  129. showSvg: false,
  130. controlErorCodes: [
  131. "控制成功",
  132. "控制命令发送失败",
  133. "无效的控制地址",
  134. "被控设备异常",
  135. "网络连接错误,检查场站通信",
  136. "控制结果读取超时",
  137. "未知错误",
  138. "控制命令错误",
  139. "收到无法识别数据",
  140. "未读取到数据包",
  141. "未知错误",
  142. "风机操作过频繁",
  143. "风机被挂牌",
  144. "风机操作与风机状态不符",
  145. "需要登录",
  146. ],
  147. }
  148. },
  149. computed: {
  150. style() {
  151. return `width: 100%; height: ${this.height}vh;`
  152. },
  153. areaClass() {
  154. if (this.big) {
  155. return `gy-card-area-big`;
  156. } else {
  157. return `gy-card-area-${this.areaStyle}`;
  158. }
  159. },
  160. circleClass() {
  161. return `gy-card-circle gy-card-circle-${this.circleStyle}`;
  162. },
  163. contentClass() {
  164. if (this.big) {
  165. return `gy-card-content-big`;
  166. } else {
  167. return `gy-card-content-${this.contentStyle}`;
  168. }
  169. },
  170. headerClass() {
  171. if (this.hover) {
  172. return `gy-card-header-hover`;
  173. } else {
  174. return `gy-card-header`;
  175. }
  176. }
  177. },
  178. created() {
  179. this.deal()
  180. },
  181. methods: {
  182. deal() {
  183. let json = this.$store.state.windturbinelist
  184. this.faultList = []
  185. this.maintainList = []
  186. this.offlineList = []
  187. this.listedList = []
  188. let arr = Object.keys(json).sort()
  189. for (var id of arr) {
  190. var val = json[id];
  191. this.chooseList.forEach(item => {
  192. if (item.windturbineId === val.windturbineId) {
  193. val.active = true
  194. }
  195. })
  196. switch (val.status) {
  197. case 5:
  198. this.faultList.push(val)
  199. break;
  200. case 6:
  201. this.maintainList.push(val)
  202. break;
  203. case 7:
  204. this.offlineList.push(val)
  205. break;
  206. }
  207. if (val.lockValue > 0) {
  208. this.listedList.push(val)
  209. }
  210. }
  211. },
  212. handleClick(values) {
  213. if (values.active) {
  214. let showIndex = null
  215. this.chooseList.forEach((item, index) => {
  216. if (item.windturbineId === values.windturbineId) {
  217. showIndex = index
  218. }
  219. })
  220. this.chooseList.splice(showIndex, 1);
  221. } else {
  222. this.chooseList.push(values)
  223. }
  224. let flag = false
  225. this.faultList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active, flag = true } })
  226. flag ? '' : this.maintainList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active, flag = true } })
  227. flag ? '' : this.offlineList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active, flag = true } })
  228. flag ? '' : this.listedList.forEach(item => { if (item.windturbineId === values.windturbineId) { item.active = !item.active } })
  229. },
  230. /* 右键菜单 */
  231. contextmenu() {
  232. const { remote } = require("electron");
  233. var that = this;
  234. const menuTemplate = [
  235. // {
  236. // label: "标注",
  237. // click() {
  238. // that.menuClicked({ type: "marking" });
  239. // },
  240. // },
  241. {
  242. label: "挂牌",
  243. submenu: [
  244. {
  245. label: "检修",
  246. click() {
  247. that.menuClicked({ type: "lock", value: "CheckLock" });
  248. },
  249. },
  250. {
  251. label: "故障维修",
  252. click() {
  253. that.menuClicked({ type: "lock", value: "FaultLock" });
  254. },
  255. },
  256. {
  257. label: "场内受累检修",
  258. click() {
  259. that.menuClicked({ type: "lock", value: "StationCheckLock" });
  260. },
  261. },
  262. {
  263. label: "场内受累故障",
  264. click() {
  265. that.menuClicked({ type: "lock", value: "StationFaulLock" });
  266. },
  267. },
  268. {
  269. label: "场外受累电网",
  270. click() {
  271. that.menuClicked({ type: "lock", value: "StationPowerLineLock" });
  272. },
  273. },
  274. {
  275. label: "场外受累天气",
  276. click() {
  277. that.menuClicked({ type: "lock", value: "StationWeatherLock" });
  278. },
  279. },
  280. ],
  281. },
  282. {
  283. label: "取消挂牌",
  284. click() {
  285. that.menuClicked({ type: "lock", value: "UnLock" });
  286. },
  287. },
  288. ];
  289. const menu = remote.Menu.buildFromTemplate(menuTemplate);
  290. menu.popup(remote.getCurrentWindow());
  291. },
  292. menuClicked(msg) {
  293. var bd = BackgroundData.getInstance();
  294. if (!bd.LoginUser) {
  295. this.$notify({
  296. title: "请登录",
  297. message: "控制风机需要先登录!",
  298. type: "warning",
  299. position: "bottom-right",
  300. offset: 60,
  301. duration: 3000,
  302. });
  303. return;
  304. }
  305. if (msg.type == "lock") {
  306. // 挂牌
  307. this.chooseList.forEach(item => {
  308. item.lockType = msg.value;
  309. })
  310. bd.windturbineControl(
  311. this.chooseList,
  312. true,
  313. '',
  314. this.controlSuccess,
  315. this.controlError
  316. );
  317. } else if (msg.type == "send") {
  318. // 发送
  319. bd.checkout(this.chooseList);
  320. bd.windturbineControl(
  321. this.chooseList,
  322. false,
  323. '',
  324. this.controlSuccess,
  325. this.controlError
  326. );
  327. } else if (msg.type == "marking") {
  328. // 标注
  329. bd.marking(this.chooseList);
  330. }
  331. this.clearSelected();
  332. },
  333. /* 清除所有选择 */
  334. clearSelected() {
  335. this.chooseList = [];
  336. },
  337. /* 控制成功 */
  338. controlSuccess(msg) {
  339. console.log(msg);
  340. var mss = ''; // 信息
  341. var iserror = false;// 是否有控制错误的风机
  342. for (var v in msg.data) {
  343. var val = msg.data[v];
  344. if (val.errorCode > 0) {
  345. iserror = true;
  346. mss += `${val.windturbineId} ${this.controlErorCodes[val.errorCode]}\n`;
  347. }
  348. }
  349. var tp = iserror ? "warning" : "success";
  350. var dt = iserror ? 0 : 4500;
  351. if (!iserror) {
  352. mss = "控制成功";
  353. }
  354. this.$notify({
  355. title: "控制",
  356. message: mss,
  357. type: tp,
  358. position: "bottom-right",
  359. offset: 60,
  360. duration: 3000,
  361. });
  362. },
  363. /* 控制失败 */
  364. controlError(err) {
  365. this.$notify({
  366. title: "控制出现错误",
  367. message: err.message,
  368. type: "warning",
  369. position: "bottom-right",
  370. offset: 60,
  371. duration: 3000,
  372. });
  373. },
  374. filter(value, windturbineId) {
  375. var array = [];
  376. var flag = false;
  377. for (var i = 0; i < value.length; i++) {
  378. if (value[i].windturbineId == windturbineId) {
  379. flag = true;
  380. array.push(flag); // 风机是否已经存在
  381. array.push(i); // 风机在values数组的位置
  382. array.push(value[i].active); // 当前风机是否被选中
  383. break;
  384. }
  385. }
  386. return array;
  387. },
  388. changeTitle(id) {
  389. this.current = id
  390. this.$refs.malfunction.dateClick(id)
  391. },
  392. addCard(val) {
  393. var active = false;
  394. var array = this.filter(this.values, val.windturbineId);
  395. if (!array[0]) {
  396. // 维护
  397. val.active = active;
  398. if (val.modelId.indexOf("105") >= 0) {
  399. val.rollSpeed *= 9.55;
  400. }
  401. this.values.push(val);
  402. } else {
  403. val.active = array[2];
  404. this.values.splice(array[1], 1, val);
  405. }
  406. console.log(this.values)
  407. },
  408. handleDetails(itm) {
  409. this.dialogVisible = true;
  410. this.currentWindturbine = itm;
  411. },
  412. handleClose() {
  413. this.dialogVisible = false
  414. this.showSvg = false
  415. },
  416. },
  417. watch: {
  418. "$store.getters.windturbinelist": {
  419. deep: true,
  420. handler: function (json) {
  421. this.faultList = []
  422. this.maintainList = []
  423. this.offlineList = []
  424. this.listedList = []
  425. let arr = Object.keys(json).sort()
  426. for (var id of arr) {
  427. var val = json[id];
  428. this.chooseList.forEach(item => {
  429. if (item.windturbineId === val.windturbineId) {
  430. val.active = true
  431. }
  432. })
  433. switch (val.status) {
  434. case 5:
  435. this.faultList.push(val)
  436. break;
  437. case 6:
  438. this.maintainList.push(val)
  439. break;
  440. case 7:
  441. this.offlineList.push(val)
  442. break;
  443. }
  444. if (val.lockValue > 0) {
  445. this.listedList.push(val)
  446. }
  447. }
  448. console.log(this.faultList);
  449. },
  450. },
  451. },
  452. }
  453. </script>
  454. <style scoped="scoped">
  455. .body {
  456. border: 1px solid #373737;
  457. width: 100%;
  458. margin-left: 15px;
  459. margin-top: 20px;
  460. }
  461. .body .scoll {
  462. height: 91%;
  463. }
  464. .title {
  465. color: #ffffff;
  466. font-size: 14px;
  467. margin-left: 32px;
  468. /* margin-top: 12px; */
  469. margin-bottom: 10px;
  470. /* width: 570px; */
  471. width: 29vw;
  472. height: 50px;
  473. display: flex;
  474. align-items: center;
  475. position: absolute;
  476. background-color: #000000;
  477. }
  478. .title::before {
  479. z-index: 1;
  480. content: '';
  481. position: absolute;
  482. left: -18px !important;
  483. /* top: 30px !important; */
  484. width: 5px;
  485. height: 5px;
  486. background-color: #54B75A;
  487. border-radius: 50%;
  488. }
  489. .logo {
  490. position: absolute;
  491. top: 12px;
  492. left: 12px;
  493. }
  494. .matrix {
  495. margin-left: 20px;
  496. margin-right: 10px;
  497. padding-bottom: 20px;
  498. border-bottom: 1px solid rgba(31, 31, 31, 1);
  499. }
  500. .problemTitle {
  501. font-size: 12px;
  502. color: #BFBFBF;
  503. margin-top: 20px;
  504. margin-bottom: 20px;
  505. margin-left: 12px;
  506. }
  507. </style>