Kaynağa Gözat

修改实时报警弹窗样式,修复弹窗点击响应慢问题

baiyanting 1 yıl önce
ebeveyn
işleme
3ded1d668b

+ 65 - 114
src/App.vue

@@ -83,35 +83,37 @@
       >
         <router-view />
       </div>
-      <div
+      <alarmBadge />
+      <!-- <div
         draggable="true"
         @dragstart="startDrag"
         @dragend="stopDrag"
         :style="{ left: x + 'px', top: y + 'px' }"
         style="cursor: pointer; position: absolute; z-index: 999"
-      >
+      > 
         <el-badge
           :value="warnLength"
           :class="{ active: warnLength ? false : true }"
-          @click="displayAlarm('1')"
         >
-          <div class="alarmDeligo">
-            <img src="@assets/imgs/ygj.png" v-if="warnLength" class="trans" />
-            <img src="@assets/imgs/ygj1.png" v-if="warnLength" />
-            <img src="@assets/imgs/wgj.png" v-if="!warnLength" class="trans" />
-            <img src="@assets/imgs/wgj1.png" v-if="!warnLength" />
+          <div class="alarmDeligo" @click="displayAlarm" v-if="warnLength">
+            <img src="@assets/imgs/ygj.png" class="trans" />
+            <img src="@assets/imgs/ygj1.png" />
+          </div>
+          <div class="alarmDeligo" v-if="!warnLength">
+            <img src="@assets/imgs/wgj.png" class="trans" />
+            <img src="@assets/imgs/wgj1.png" />
           </div>
         </el-badge>
       </div>
       <deligo-alarm-list
+        :dialogList="dialogList.slice(0, 12)"
         :alarmConfigArray="alarmConfigArray"
         @setConfig="getAlarmConfig"
         @confirm="playAudioEffect"
         ref="deligoChild"
-        :displayAlarms="displayAlarms"
-        @close="displayAlarm('2')"
+        @close="displayClose"
         v-if="displayAlarms == true"
-      ></deligo-alarm-list>
+      ></deligo-alarm-list> -->
     </div>
     <div v-else class="login"><login-page @onLogin="login" /></div>
   </div>
@@ -119,6 +121,7 @@
 
 <script>
 // 导入header.vue文件
+import alarmBadge from "@/components/alarm-badge/index.vue";
 import Menu from "@/views/layout/Menu.vue";
 import Header from "@/views/layout/Header.vue";
 import LoginPage from "./views/layout/login-page.vue";
@@ -136,7 +139,7 @@ export default {
     Menu,
     Header,
     LoginPage,
-    sisView,
+    alarmBadge,
     SvgIcon,
     deligoAlarmList,
   },
@@ -160,39 +163,39 @@ export default {
       },
       // websocket相关
       //升压站报警ws
-      socketObj: "", // websocket实例对象
-      //心跳检测
-      heartCheck: {
-        vueThis: this, // vue实例
-        timeout: 30000, // 超时时间
-        timeoutObj: null, // 计时器对象——向后端发送心跳检测
-        serverTimeoutObj: null, // 计时器对象——等待后端心跳检测的回复
-        // 心跳检测重置
-        reset: function () {
-          clearTimeout(this.timeoutObj);
-          clearTimeout(this.serverTimeoutObj);
-          return this;
-        },
-        // 心跳检测启动
-        start: function () {
-          this.timeoutObj && clearTimeout(this.timeoutObj);
-          this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
-          this.timeoutObj = setTimeout(() => {
-            // 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
-            this.vueThis.socketObj.send("HeartBeat");
-            console.log("发送心跳检测");
-            this.serverTimeoutObj = setTimeout(() => {
-              // 如果超过一定时间还没重置计时器,说明websocket与后端断开了
-              console.log("未收到心跳检测回复");
-              // 关闭WebSocket
-              this.vueThis.socketObj.close();
-            }, this.timeout);
-          }, this.timeout);
-        },
-      },
-      socketReconnectTimer: null, // 计时器对象——重连
-      socketReconnectLock: false, // WebSocket重连的锁
-      socketLeaveFlag: false, // 离开标记(解决 退出登录再登录 时出现的 多次相同推送 问题,出现的本质是多次建立了WebSocket连接)
+      //   socketObj: "", // websocket实例对象
+      //   //心跳检测
+      //   heartCheck: {
+      //     vueThis: this, // vue实例
+      //     timeout: 30000, // 超时时间
+      //     timeoutObj: null, // 计时器对象——向后端发送心跳检测
+      //     serverTimeoutObj: null, // 计时器对象——等待后端心跳检测的回复
+      //     // 心跳检测重置
+      //     reset: function () {
+      //       clearTimeout(this.timeoutObj);
+      //       clearTimeout(this.serverTimeoutObj);
+      //       return this;
+      //     },
+      //     // 心跳检测启动
+      //     start: function () {
+      //       this.timeoutObj && clearTimeout(this.timeoutObj);
+      //       this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
+      //       this.timeoutObj = setTimeout(() => {
+      //         // 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
+      //         this.vueThis.socketObj.send("HeartBeat");
+      //         console.log("发送心跳检测");
+      //         this.serverTimeoutObj = setTimeout(() => {
+      //           // 如果超过一定时间还没重置计时器,说明websocket与后端断开了
+      //           console.log("未收到心跳检测回复");
+      //           // 关闭WebSocket
+      //           this.vueThis.socketObj.close();
+      //         }, this.timeout);
+      //       }, this.timeout);
+      //     },
+      //   },
+      //   socketReconnectTimer: null, // 计时器对象——重连
+      //   socketReconnectLock: false, // WebSocket重连的锁
+      //   socketLeaveFlag: false, // 离开标记(解决 退出登录再登录 时出现的 多次相同推送 问题,出现的本质是多次建立了WebSocket连接)
       //实时报警弹窗ws
       socketObj1: "", // websocket实例对象
       //心跳检测
@@ -279,59 +282,7 @@ export default {
       return this.$store.state.warnList.length;
     },
   },
-  created() {
-    this.getAlarmConfig();
-    this.x = this.style.width - 82;
-    this.y = this.style.height - 82;
-    let that = this;
-    const themeName = that.$store.state.themeName;
-    $("#appBody").attr(
-      "class",
-      themeName === "dark" || themeName === "light" ? themeName : "dark"
-    );
-    let requestResult = [];
-    this.requestAlarmHistoryParams.forEach(({ alarmType, deviceType }) => {
-      requestResult.push(this.getAlarmHistory(alarmType, deviceType));
-    });
-
-    Promise.all(requestResult)
-      .then((promiseResult) => {
-        promiseResult.forEach(({ data }) => {
-          data?.records?.forEach((ele) => {
-            this.pushALarmItem(ele);
-          });
-        });
-        this.dialogList.sort((a, b) => {
-          return b.lv - a.lv;
-        });
-        this.$store.commit("changeAlarmlist", this.alarmList);
-        this.$store.commit("setWarning", this.dialogList);
-        this.socketReconnect1();
-      })
-      .catch(() => {
-        requestResult.forEach((ele, index) => {
-          ele
-            .then(({ data }) => {
-              data?.ls?.forEach((ele) => {
-                this.pushALarmItem(ele);
-              });
-            })
-            .catch((error) => {
-              ElNotification({
-                type: "error",
-                title: "查询历史未处理报警请求出错!",
-                dangerouslyUseHTMLString: true,
-                message: `<div class="currentRequestErrorNotification">
-                                <p><span>主要参数:</p>
-                                <p style="color:var(--el-color-primary)"><span class="errorTitle">alarmType:</span><span class="errorDesc">"${this.requestAlarmHistoryParams[index].alarmType}"</span></p>
-                                <p style="color:var(--el-color-primary)"><span class="errorTitle">deviceType:</span><span class="errorDesc">"${this.requestAlarmHistoryParams[index].deviceType}"</span></p>
-                                <p style="color:var(--el-color-danger)"><span class="errorTitle">错误正文:</span><span class="errorDesc">${error}</span></p>
-                             </div>`,
-              });
-            });
-        });
-      });
-  },
+  created() {},
   mounted() {
     let that = this;
     that.setScale();
@@ -339,11 +290,6 @@ export default {
     $(window).resize(() => {
       that.setScale();
     });
-    if (!this.socketLeaveFlag) {
-      // 没有离开——重连
-      // websocket重连
-      //   this.socketReconnect();
-    }
   },
   unmounted() {
     console.log("离开标记", this.socketLeaveFlag);
@@ -389,7 +335,7 @@ export default {
           return ele.lv === 5 && !ele.confirm;
         });
       }
-    //   console.log(lv1Play, lv2Play, lv3Play, lv4Play, lv5Play);
+      //   console.log(lv1Play, lv2Play, lv3Play, lv4Play, lv5Play);
       if (lv5Play && !this.seriousWarning) {
         this.seriousWarning = true;
         this.audioElement = new Audio();
@@ -506,6 +452,7 @@ export default {
         return "高级";
       }
     },
+    //查历史报警
     getAlarmHistory(alarmType, deviceType) {
       let params = {
         pageNum: 1,
@@ -541,7 +488,9 @@ export default {
         resolvent: alarmItem.resolvent,
         characteristic: alarmItem.characteristic,
         code: alarmItem.code,
-        wpName: alarmItem.stationName,
+        wpName: alarmItem.stationName
+          ? alarmItem.stationName
+          : alarmItem.wpName,
         isClose: alarmItem.isClose
           ? alarmItem.isClose
           : alarmItem.closeTime
@@ -604,7 +553,7 @@ export default {
       );
     },
 
-    // 拖拽
+    // 拖拽相关
     startDrag(event) {
       this.currentX = event.clientX;
       this.currentY = event.clientY;
@@ -625,15 +574,19 @@ export default {
         this.y = 0;
       }
     },
+    //开关列表
     displayAlarm(val) {
-      if (this.warnLength) {
-        if (val == 2) {
-          this.displayAlarms = false;
-        } else if (val == 1) {
-          this.displayAlarms = !this.displayAlarms;
-        }
+      this.displayAlarms = !this.displayAlarms;
+      if (this.displayAlarms == true) {
+        setTimeout(() => {
+          this.$refs.deligoChild &&
+            this.$refs.deligoChild.init(this.dialogList);
+        }, 0);
       }
     },
+    displayClose() {
+      this.displayAlarms = false;
+    },
     getScale() {
       const w = window.innerWidth / this.style.width;
       const h = window.innerHeight / this.style.height;
@@ -648,7 +601,6 @@ export default {
       let scale = this.getScale();
       this.style.transform =
         "scaleY(" + scale.y + ") scaleX(" + scale.x + ") translate(-50%, -50%)";
-      //   this.style.fontsize = scale.f;
     },
     // 切换子系统事件
     HeaderMenuClick(data) {
@@ -678,7 +630,6 @@ export default {
     // 获取测风塔
     async getCftlist() {
       const { data: datas } = await getApiWeatherstation();
-      console.log(datas);
       this.$store.commit("changeCft", datas.data);
     },
     login() {

+ 8 - 0
src/assets/styles/el-override/el-table.less

@@ -137,6 +137,14 @@
       background-color: #161415;
     }
     tr {
+      &.isConfirm {
+        &:hover {
+          td {
+            color: #05bb4c !important;
+            background-color: transparent !important;
+          }
+        }
+      }
       &:hover {
         td {
           color: #d35400 !important;

+ 659 - 0
src/components/alarm-badge/index.vue

@@ -0,0 +1,659 @@
+<template>
+  <div
+    draggable="true"
+    @dragstart="startDrag"
+    @dragend="stopDrag"
+    :style="{ left: x + 'px', top: y + 'px' }"
+    style="cursor: pointer; position: absolute; z-index: 999"
+  >
+    <el-badge
+      :value="warnLength"
+      :class="{ active: warnLength && !displayAlarms ? false : true }"
+    >
+      <div class="alarmDeligo" @click="displayAlarm" v-if="warnLength">
+        <img src="@assets/imgs/ygj.png" class="trans" />
+        <img src="@assets/imgs/ygj1.png" />
+      </div>
+      <div class="alarmDeligo" v-if="!warnLength">
+        <img src="@assets/imgs/wgj.png" class="trans" />
+        <img src="@assets/imgs/wgj1.png" />
+      </div>
+    </el-badge>
+    <deligo-alarm-list
+      :dialogList="dialogList.slice(0, 12)"
+      :alarmConfigArray="alarmConfigArray"
+      @setConfig="getAlarmConfig"
+      @confirm="playAudioEffect"
+      ref="deligoChild"
+      @close="displayClose"
+      v-if="displayAlarms == true"
+    ></deligo-alarm-list>
+  </div>
+</template>
+
+<script>
+import deligoAlarmList from "@/components/deligoAlarmList";
+import { ElNotification } from "element-plus";
+import { GetDeviceTableData } from "@/api/zhbj/index.js";
+import dayjs from "dayjs";
+export default {
+  name: "alarmBadge",
+  components: {
+    deligoAlarmList,
+  },
+
+  data() {
+    return {
+      //实时报警弹窗ws
+      socketObj1: "", // websocket实例对象
+      //心跳检测
+      heartCheck1: {
+        vueThis1: this, // vue实例
+        timeout1: 30000, // 超时时间
+        timeoutObj1: null, // 计时器对象——向后端发送心跳检测
+        serverTimeoutObj1: null, // 计时器对象——等待后端心跳检测的回复
+        // 心跳检测重置
+        reset: function () {
+          clearTimeout(this.timeoutObj1);
+          clearTimeout(this.serverTimeoutObj1);
+          return this;
+        },
+        // 心跳检测启动
+        start: function () {
+          this.timeoutObj1 && clearTimeout(this.timeoutObj1);
+          this.serverTimeoutObj1 && clearTimeout(this.serverTimeoutObj1);
+          this.timeoutObj1 = setTimeout(() => {
+            // 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
+            this.vueThis1.socketObj1.send("HeartBeat");
+            console.log("发送心跳检测1");
+            this.serverTimeoutObj1 = setTimeout(() => {
+              // 如果超过一定时间还没重置计时器,说明websocket与后端断开了
+              console.log("未收到心跳检测回复1");
+              // 关闭WebSocket
+              this.vueThis1.socketObj1.close();
+            }, this.timeout1);
+          }, this.timeout1);
+        },
+      },
+      socketReconnectTimer1: null, // 计时器对象——重连
+      socketReconnectLock1: false, // WebSocket重连的锁
+      socketLeaveFlag1: false, // 离开标记(解决 退出登录再登录 时出现的 多次相同推送 问题,出现的本质是多次建立了WebSocket连接)
+      alarmList: [],
+      dialogList: [],
+      //实时报警图标相关
+      x: null,
+      y: null,
+      currentX: 0,
+      currentY: 0,
+      displayAlarms: false,
+      indexNum: 0,
+      data1: 0,
+      dragging: false,
+
+      initialX: 0,
+      initialY: 0,
+      timer: null,
+      firstTime: null,
+      lastTime: null,
+      key: false,
+      //请求参数
+      requestAlarmHistoryParams: [
+        {
+          alarmType: "booststation",
+          deviceType: "",
+        },
+        {
+          alarmType: "inverter",
+          deviceType: "",
+        },
+        {
+          alarmType: "windturbine",
+          deviceType: "",
+        },
+      ],
+      alarmConfigArray: [],
+      seriousWarning: false,
+      audioElement: null,
+    };
+  },
+  computed: {
+    warnLength() {
+      return this.$store.state.warnList.length;
+    },
+    isLogined() {
+      return this.$store.state.user?.loginState;
+    },
+  },
+  created() {
+    this.getAlarmConfig();
+    this.x = window.innerWidth - 82;
+    this.y = window.innerHeight - 32;
+    let requestResult = [];
+    this.requestAlarmHistoryParams.forEach(({ alarmType, deviceType }) => {
+      requestResult.push(this.getAlarmHistory(alarmType, deviceType));
+    });
+
+    Promise.all(requestResult)
+      .then((promiseResult) => {
+        promiseResult.forEach(({ data }) => {
+          data?.records?.forEach((ele) => {
+            this.pushALarmItem(ele);
+          });
+        });
+        this.dialogList.sort((a, b) => {
+          return b.lv - a.lv;
+        });
+        this.$store.commit("changeAlarmlist", this.alarmList);
+        this.$store.commit("setWarning", this.dialogList);
+        if (!this.socketLeaveFlag) {
+          // 没有离开——重连
+          // websocket重连
+          this.socketReconnect1();
+        }
+      })
+      .catch(() => {
+        requestResult.forEach((ele, index) => {
+          ele
+            .then(({ data }) => {
+              data?.ls?.forEach((ele) => {
+                this.pushALarmItem(ele);
+              });
+            })
+            .catch((error) => {
+              ElNotification({
+                type: "error",
+                title: "查询历史未处理报警请求出错!",
+                dangerouslyUseHTMLString: true,
+                message: `<div class="currentRequestErrorNotification">
+                                <p><span>主要参数:</p>
+                                <p style="color:var(--el-color-primary)"><span class="errorTitle">alarmType:</span><span class="errorDesc">"${this.requestAlarmHistoryParams[index].alarmType}"</span></p>
+                                <p style="color:var(--el-color-primary)"><span class="errorTitle">deviceType:</span><span class="errorDesc">"${this.requestAlarmHistoryParams[index].deviceType}"</span></p>
+                                <p style="color:var(--el-color-danger)"><span class="errorTitle">错误正文:</span><span class="errorDesc">${error}</span></p>
+                             </div>`,
+              });
+            });
+        });
+      });
+  },
+  mounted() {},
+  unmounted() {
+    console.log("离开标记", this.socketLeaveFlag);
+  },
+  methods: {
+    playAudioEffect() {
+      const lv1Config = this.getConfigItem(1);
+      let lv1Play = false;
+      if (lv1Config.isAlarmSound) {
+        lv1Play = this.dialogList.some((ele) => {
+          return ele.lv === 1 && !ele.confirm;
+        });
+      }
+
+      const lv2Config = this.getConfigItem(2);
+      let lv2Play = false;
+      if (lv2Config.isAlarmSound) {
+        lv2Play = this.dialogList.some((ele) => {
+          return ele.lv === 2 && !ele.confirm;
+        });
+      }
+
+      const lv3Config = this.getConfigItem(3);
+      let lv3Play = false;
+      if (lv3Config.isAlarmSound) {
+        lv3Play = this.dialogList.some((ele) => {
+          return ele.lv === 3 && !ele.confirm;
+        });
+      }
+
+      const lv4Config = this.getConfigItem(4);
+      let lv4Play = false;
+      if (lv4Config.isAlarmSound) {
+        lv4Play = this.dialogList.some((ele) => {
+          return ele.lv === 4 && !ele.confirm;
+        });
+      }
+
+      const lv5Config = this.getConfigItem(5);
+      let lv5Play = false;
+      if (lv5Config.isAlarmSound) {
+        lv5Play = this.dialogList.some((ele) => {
+          return ele.lv === 5 && !ele.confirm;
+        });
+      }
+      //   console.log(lv1Play, lv2Play, lv3Play, lv4Play, lv5Play);
+      if (lv5Play && !this.seriousWarning) {
+        this.seriousWarning = true;
+        this.audioElement = new Audio();
+        this.audioElement.src = "./static/sound/lv5.mp3";
+        this.audioElement.loop = true;
+        this.audioElement?.play();
+      } else if (
+        (lv1Play || lv2Play || lv3Play || lv4Play) &&
+        !this.seriousWarning
+      ) {
+        this.audioElement = new Audio();
+        this.audioElement.src = "./static/sound/lv4.mp3";
+        this.audioElement.addEventListener("ended", () => {
+          this.audioElement?.removeEventListener(
+            "ended",
+            this.stopPlayAudioEffect
+          );
+        });
+        this.audioElement?.play();
+      } else {
+        if (!this.seriousWarning) {
+          this.stopPlayAudioEffect();
+        }
+      }
+    },
+
+    stopPlayAudioEffect() {
+      this.seriousWarning = false;
+      if (this.audioElement) {
+        this.audioElement.pause();
+        this.audioElement.currentTime = 0;
+        this.audioElement.loop = false;
+      }
+      this.audioElement = null;
+    },
+    //获取报警配置
+    getAlarmConfig() {
+      if (localStorage.getItem("alarmConfigArray")) {
+        this.alarmConfigArray = JSON.parse(
+          localStorage.getItem("alarmConfigArray")
+        );
+      } else {
+        this.alarmConfigArray = [
+          {
+            id: "1",
+            alarmLevel: 1,
+            isAlart: false,
+            isAlarmSound: false,
+            isContinuousAlarm: false,
+          },
+          {
+            id: "2",
+            alarmLevel: 2,
+            isAlart: false,
+            isAlarmSound: false,
+            isContinuousAlarm: false,
+          },
+          {
+            id: "3",
+            alarmLevel: 3,
+            isAlart: true,
+            isAlarmSound: false,
+            isContinuousAlarm: false,
+          },
+          {
+            id: "4",
+            alarmLevel: 4,
+            isAlart: true,
+            isAlarmSound: true,
+            isContinuousAlarm: false,
+          },
+          {
+            id: "5",
+            alarmLevel: 5,
+            isAlart: true,
+            isAlarmSound: true,
+            isContinuousAlarm: true,
+          },
+        ];
+        localStorage.setItem(
+          "alarmConfigArray",
+          JSON.stringify(this.alarmConfigArray)
+        );
+      }
+    },
+    getAlarmName(alarmItem) {
+      let alarmName = "";
+      if (alarmItem.deviceType === "booststation") {
+        alarmName = "升压站报警";
+      } else if (alarmItem.deviceType === "inverter") {
+        alarmName = "光伏报警";
+      } else if (alarmItem.deviceType === "windturbine") {
+        alarmName = "设备报警";
+      } else if (alarmItem.deviceType === "station") {
+        alarmName = "场站";
+      }
+
+      if (alarmItem.alarmType === "custom") {
+        alarmName = "自定义报警";
+      }
+      return alarmName;
+    },
+
+    getLvName(alarmItem) {
+      if (alarmItem.rank === 1) {
+        return "低级";
+      } else if (alarmItem.rank === 2) {
+        return "低中级";
+      } else if (alarmItem.rank === 3) {
+        return "中级";
+      } else if (alarmItem.rank === 4) {
+        return "中高级";
+      } else if (alarmItem.rank === 5) {
+        return "高级";
+      }
+    },
+    //查历史报警
+    getAlarmHistory(alarmType, deviceType) {
+      let params = {
+        pageNum: 1,
+        pageSize: 5000,
+        alarmId: "",
+        alarmType,
+        stationid: "",
+        deviceid: "",
+        modelId: "",
+        components: "",
+        description: "",
+        isclose: false,
+        begin: "",
+        end: "",
+      };
+      if (params.alarmType == "windturbine") {
+        params.stationid = "SXJ_KGDL_DJY_FDC_STA";
+      } else if (params.alarmType == "inverter") {
+        params.stationid = "SXJ_KGDL_JR_GDC_STA";
+      }
+      return GetDeviceTableData(params, 12000);
+    },
+    pushALarmItem(alarmItem, type) {
+      const configItem = this.getConfigItem(alarmItem.rank);
+      const alarmOption = {
+        id: alarmItem.id ? alarmItem.id : alarmItem.tbname,
+        lv: alarmItem.rank,
+        lvName: this.getLvName(alarmItem),
+        rank: alarmItem.rank,
+        class: `animate__bounceInRight lv${alarmItem.rank}`,
+        deviceId: alarmItem.deviceId,
+        faultCause: alarmItem.faultCause,
+        resolvent: alarmItem.resolvent,
+        characteristic: alarmItem.characteristic,
+        code: alarmItem.code,
+        wpName: alarmItem.stationName
+          ? alarmItem.stationName
+          : alarmItem.wpName,
+        isClose: alarmItem.isClose
+          ? alarmItem.isClose
+          : alarmItem.closeTime
+          ? true
+          : false,
+        isCloseName:
+          alarmItem.closeTime || alarmItem.isClose ? "已解除" : "未解除",
+        alarmId: alarmItem.alarmId,
+        alarmType: alarmItem.alarmType,
+        alarmName: this.getAlarmName(alarmItem),
+        description: alarmItem.description,
+        deviceType: alarmItem.deviceType,
+        oval: alarmItem.oval,
+        triggerType: alarmItem.triggerType,
+        ts: alarmItem.ts
+          ? dayjs(alarmItem.ts).valueOf()
+          : dayjs(alarmItem.lastUpdateTime).valueOf(),
+        deviceName: alarmItem.deviceName,
+        tsName: alarmItem.ts
+          ? new Date(alarmItem.ts).formatDate("MM-dd hh:mm:ss")
+          : new Date(alarmItem.lastUpdateTime).formatDate("MM-dd hh:mm:ss"),
+        fullTsName: alarmItem.ts
+          ? new Date(alarmItem.ts).formatDate("yyyy-MM-dd hh:mm:ss")
+          : new Date(alarmItem.lastUpdateTime).formatDate(
+              "yyyy-MM-dd hh:mm:ss"
+            ),
+      };
+      if (alarmItem.alarmType == "booststation") {
+        if (
+          configItem.isAlarmSound ||
+          configItem.isAlart ||
+          configItem.isContinuousAlarm
+        ) {
+          let a = {};
+          a[`${alarmItem.stationId}`] = alarmItem.closeTime ? false : true;
+          this.alarmList.push(a);
+          this.alarmList = [
+            ...new Set(this.alarmList.map((t) => JSON.stringify(t))),
+          ].map((s) => JSON.parse(s));
+        }
+      }
+      if (
+        configItem.isAlarmSound ||
+        configItem.isAlart ||
+        configItem.isContinuousAlarm
+      ) {
+        if (type && type == "ws") {
+          this.dialogList.unshift(alarmOption);
+        } else {
+          this.dialogList.push(alarmOption);
+        }
+      }
+      this.playAudioEffect();
+    },
+    getConfigItem(lv) {
+      return (
+        this.alarmConfigArray.find((ele) => {
+          return ele.alarmLevel === lv;
+        }) || {}
+      );
+    },
+
+    // 拖拽相关
+    startDrag(event) {
+      this.currentX = event.clientX;
+      this.currentY = event.clientY;
+    },
+    stopDrag(event) {
+      let x = event.clientX - this.currentX;
+      let y = event.clientY - this.currentY;
+      this.x += x;
+      if (this.x < 60) {
+        this.x = 60;
+      } else if (this.x > window.innerWidth - 20) {
+        this.x = window.innerWidth - 82;
+      }
+      this.y += y;
+      if (this.y > window.innerHeight - 20) {
+        this.y = window.innerHeight - 32;
+      } else if (this.y < 0) {
+        this.y = 0;
+      }
+    },
+    //开关列表
+    displayAlarm(val) {
+      this.displayAlarms = !this.displayAlarms;
+      if (this.displayAlarms == true) {
+        setTimeout(() => {
+          this.$refs.deligoChild &&
+            this.$refs.deligoChild.init(this.dialogList);
+        }, 0);
+      }
+    },
+    displayClose() {
+      this.displayAlarms = false;
+    },
+
+    // websocket启动
+    createWebSocket1() {
+      //   let webSocketLink = `ws://192.168.1.102:6014/websocket/${this.$store.state.user.userId}_${this.$store.state.user.authToken}`;
+      let webSocketLink1 = `ws://10.81.3.154:6014/websocket/${this.$store.state.user.userId}_${this.$store.state.user.authToken}`; // webSocket地址
+      try {
+        if ("WebSocket" in window) {
+          this.socketObj1 = new WebSocket(webSocketLink1);
+        }
+        // websocket事件绑定
+        this.socketEventBind1();
+      } catch (e) {
+        console.log("catch" + e);
+        // websocket重连
+        this.socketReconnect1();
+      }
+    },
+    // websocket事件绑定
+    socketEventBind1() {
+      // 连接成功建立的回调
+      this.socketObj1.onopen = this.onopenCallback1;
+      // 连接发生错误的回调
+      this.socketObj1.onerror = this.onerrorCallback1;
+      // 连接关闭的回调
+      this.socketObj1.onclose = this.oncloseCallback1;
+      // 向后端发送数据的回调
+      this.socketObj1.onsend = this.onsendCallback1;
+      // 接收到消息的回调
+      this.socketObj1.onmessage = this.getMessageCallback1;
+
+      //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
+      window.onbeforeunload = () => {
+        this.socketObj1.close();
+      };
+    },
+    // websocket重连
+    socketReconnect1() {
+      if (this.socketReconnectLock1) {
+        return;
+      }
+      this.socketReconnectLock1 = true;
+      this.socketReconnectTimer1 && clearTimeout(this.socketReconnectTimer1);
+      this.socketReconnectTimer1 = setTimeout(() => {
+        console.log("WebSocket1:重连中...");
+        this.socketReconnectLock1 = false;
+        // websocket启动
+        this.createWebSocket1();
+      }, 4000);
+    },
+    // 连接成功建立的回调
+    onopenCallback1: function (event) {
+      console.log("WebSocket1:已连接");
+      // 心跳检测重置
+      this.heartCheck1.reset().start();
+    },
+    // 连接发生错误的回调
+    onerrorCallback1: function (event) {
+      console.log("WebSocket1:发生错误");
+      // websocket重连
+      this.socketReconnect1();
+    },
+    // 连接关闭的回调
+    oncloseCallback1: function (event) {
+      console.log("WebSocket1:已关闭");
+      // 心跳检测重置
+      this.heartCheck1.reset();
+      if (!this.socketLeaveFlag1) {
+        // 没有离开——重连
+        // websocket重连
+        this.socketReconnect1();
+      }
+    },
+    // 向后端发送数据的回调
+    onsendCallback1: function () {
+      console.log("WebSocket1:发送信息给后端");
+    },
+    // 接收到消息的回调
+    getMessageCallback1: function (msg) {
+      //   console.log(msg);
+      if (Object.keys(msg) && msg.data == "ok") {
+        // 心跳回复——心跳检测重置
+        // 收到心跳检测回复就说明连接正常
+        console.log("收到心跳检测回复1");
+        // 心跳检测重置
+        this.heartCheck1.reset().start();
+      } else {
+        // 普通推送——正常处理
+        console.log("收到推送消息1");
+
+        let data = JSON.parse(msg.data);
+        // 相关处理
+        if (data) {
+          this.pushALarmItem(data, "ws");
+          //   this.dialogList.sort((a, b) => {
+          //     return b.lv - a.lv;
+          //   });
+          this.$store.commit("changeAlarmlist", this.alarmList);
+          this.$store.commit("setWarning", this.dialogList);
+        }
+      }
+    },
+  },
+
+  watch: {
+    isLogined: {
+      handler(res) {
+        if (!res && this.socketObj1) {
+          // 离开标记
+          this.socketLeaveFlag1 = true;
+          // 关闭WebSocket
+          this.socketObj1.close();
+        }
+      },
+      immediate: true,
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.alarmDeligo {
+  z-index: 2003;
+  position: relative;
+
+  img {
+    width: 43px;
+    max-width: 43px;
+    height: 43px;
+    z-index: 3;
+  }
+
+  img:first-child {
+    width: 53px;
+    height: 57px;
+    max-width: 53px;
+    top: -7px;
+    left: -5px;
+    position: absolute;
+    z-index: 3;
+  }
+}
+
+.el-badge {
+  &.active {
+    .el-badge__content--danger {
+      opacity: 0 !important;
+    }
+  }
+}
+.el-badge__content--danger {
+  background: #ff4e00 !important;
+  border: none !important;
+}
+.el-badge__content.is-fixed {
+  top: 7px !important;
+  right: 14px !important;
+  z-index: 2003 !important;
+}
+
+.trans {
+  animation: circleProgess 3s linear infinite;
+}
+
+@keyframes circleProgess {
+  0% {
+    transform: rotateZ(360deg);
+  }
+
+  25% {
+    transform: rotateZ(270deg);
+  }
+
+  50% {
+    transform: rotateZ(180deg);
+  }
+
+  75% {
+    transform: rotateZ(90deg);
+  }
+
+  100% {
+    transform: rotateZ(0deg);
+  }
+}
+</style>

+ 68 - 41
src/components/deligoAlarmList/index.vue

@@ -7,7 +7,7 @@
             <img src="@assets/imgs/warn-icon.png" />
           </div>
           <div class="warn-name">实时告警</div>
-          <div class="warn-num">{{ warnNum }}</div>
+          <div class="warn-num">{{ warnNum ? warnNum : 0 }}</div>
         </div>
         <div class="warn-close" @click="displayAlarm">
           <img src="@assets/imgs/warn-close.png" />
@@ -17,19 +17,15 @@
         <div class="warn-table">
           <el-table
             @selection-change="handleSelectionChange"
-            select-on-indeterminate
-            :header-cell-style="handerMethod"
             :data="warnList"
             size="mini"
             stripe
-            @select="changeSelect"
             height="100%"
             width="100%"
+            :row-class-name="tableRowClassName"
           >
             <el-table-column type="selection" width="40" align="center">
             </el-table-column>
-            <el-table-column type="index" width="45" align="center">
-            </el-table-column>
             <el-table-column
               v-for="(header, index) in tableHeader"
               :key="index"
@@ -41,10 +37,16 @@
             >
               <template #default="{ row }">
                 <div v-if="header.code == ''">
-                  {{ row["stationName"] }}{{ row["deviceName"] }}设备{{
+                  {{ row["wpName"] }}{{ row["deviceName"] }}设备{{
                     row["description"]
                   }}
                 </div>
+                <div
+                  v-else-if="header.code == 'isCloseName'"
+                  :style="`color:${row.isClose ? '#05bb4c' : '#d35400'}`"
+                >
+                  {{ row[header.code] }}
+                </div>
                 <div v-else>
                   {{ row[header.code] }}
                 </div>
@@ -53,22 +55,27 @@
           </el-table>
         </div>
         <div class="warn-btns">
+          <div class="setting svg-icon" @click="setAlarmConfig">
+            <SvgIcon svgid="svg-setting" />
+          </div>
           <el-button class="confirm-one" @click="confirm" :disabled="checkAll"
             >选择确认
           </el-button>
           <el-button class="confirm-all" @click="confirm" :disabled="!checkAll"
             >全部确认
           </el-button>
-          <i class="setting svg-icon" @click="setAlarmConfig">
-            <SvgIcon svgid="svg-setting" />
-          </i>
         </div>
       </div>
     </div>
   </div>
   <div class="setting-dialog" v-if="displaySetting">
     <div class="setting-wrapper">
-      <div class="box-title">报警配置</div>
+      <div class="box-title">
+        <div class="box-name">报警配置</div>
+        <div class="box-close" @click="cancle">
+          <img src="@assets/imgs/warn-close.png" />
+        </div>
+      </div>
       <div class="box-content">
         <el-tabs type="border-card" v-model="activeTab">
           <el-tab-pane
@@ -108,8 +115,7 @@
           </el-tab-pane>
         </el-tabs>
         <div class="btnBox">
-          <el-button @click="cancle" class="cancle">取消修改</el-button>
-          <el-button @click="save">保存规则</el-button>
+          <el-button @click="save">保存配置</el-button>
         </div>
       </div>
     </div>
@@ -119,20 +125,18 @@
 <script>
 import { confirmAlart } from "@/api/zhbj/index.js";
 import SvgIcon from "@com/coms/icon/svg-icon.vue";
-// import alarmMore from "../alarmMore";
-// import {
-//   GetRecordByAlarmId,
-//   GetyPowerstationId,
-// } from "../../api/factoryMonitor";
+import { nextTick } from "vue";
 
 export default {
   name: "byPase", //首页标题栏
-  //   components: { alarmMore },
   props: {
     alarmConfigArray: {
       type: Array,
       required: true,
     },
+    dialogList: {
+      type: Array,
+    },
   },
   components: { SvgIcon },
   data() {
@@ -147,20 +151,22 @@ export default {
       checkAll: false,
       activeTab: "",
       configArray: [],
+      warnList: [],
     };
   },
 
   created() {
     this.activeTab = this.activeTab || this.alarmConfigArray?.[0]?.id;
+    this.warnList = this.dialogList;
   },
   mounted() {},
   computed: {
     warnNum() {
       return this.$store.state.warnList.length;
     },
-    warnList() {
-      return this.$store.state.warnList;
-    },
+    // warnList() {
+    //   return this.$store.state.warnList;
+    // },
   },
   watch: {
     alarmConfigArray: {
@@ -174,6 +180,16 @@ export default {
     },
   },
   methods: {
+    init(list) {
+      this.warnList = list;
+    },
+    tableRowClassName({ row }) {
+      if (row.isClose) {
+        return "isConfirm";
+      } else {
+        return "";
+      }
+    },
     cancle() {
       this.configArray = this.alarmConfigArray;
       this.displaySetting = false;
@@ -194,6 +210,8 @@ export default {
       this.checkedRow = rows;
       if (this.checkedRow.length == this.warnNum) {
         this.checkAll = true;
+      } else {
+        this.checkAll = false;
       }
     },
     displayAlarm() {
@@ -261,17 +279,21 @@ export default {
 
 <style lang="less" scoped>
 .warn-dialog {
-  position: fixed;
-  right: 0;
-  bottom: 2px;
+  position: absolute;
+  right: -12px;
+  bottom: -6px;
   z-index: 1000;
+  width: 540px;
+  height: 510px;
   .warn-wrapper {
-    width: 540px;
-    height: 510px;
-    position: absolute;
-    bottom: 25px;
-    right: 17px;
+    width: 100%;
+    height: 100%;
+    // position: absolute;
+    // bottom: 25px;
+    // right: 17px;
+    border-radius: 6px;
     background: url("~@/assets/imgs/warn-border.png") no-repeat;
+    background-color: #000;
     background-size: 100% 100%;
 
     .warn-top {
@@ -341,17 +363,18 @@ export default {
           &.confirm-one {
             width: 100px;
             background: url("~@/assets/imgs/confirmone.png") no-repeat;
+            transform: translateX(50%);
           }
           &.confirm-all {
             width: 160px;
             background: url("~@/assets/imgs/confirmall.png") no-repeat;
-            transform: translateX(50%);
+            transform: translateX(75%);
           }
         }
         .setting {
           position: absolute;
           top: 55%;
-          right: 22px;
+          left: 10px;
           transform: translateY(-50%);
           cursor: pointer;
         }
@@ -360,16 +383,16 @@ export default {
   }
 }
 .setting-dialog {
-  position: fixed;
-  right: 0;
-  bottom: 2px;
+  position: absolute;
+  right: -12px;
+  bottom: -6px;
   z-index: 1001;
+  width: 540px;
+  height: 510px;
   .setting-wrapper {
-    width: 540px;
-    height: 510px;
-    position: absolute;
-    bottom: 25px;
-    right: 17px;
+    width: 100%;
+    height: 100%;
+    border-radius: 6px;
     background: url("~@/assets/imgs/warn-border.png") no-repeat;
     background-size: 100% 100%;
     .box-title {
@@ -389,7 +412,6 @@ export default {
       height: calc(100% - 60px);
       padding: 0 10px;
       .btnBox {
-        text-align: right;
         .el-button ::v-deep {
           width: 100px;
           background: url("~@/assets/imgs/confirmone.png") no-repeat;
@@ -440,6 +462,11 @@ export default {
     border-left-color: transparent !important;
   }
 }
+.el-form::v-deep {
+  .el-form-item__label {
+    color: #ccc;
+  }
+}
 .el-switch::v-deep {
   &.is-checked .el-switch__core {
     border-color: #fd7f00;