瀏覽代碼

设备预警历史修改-提交

lxh 7 月之前
父節點
當前提交
cf732649d5

+ 3 - 0
src/assets/icons/yjtz.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="25.995" height="25.995" viewBox="0 0 25.995 25.995">
+  <path id="路径_56239" data-name="路径 56239" d="M55.359,74.855V64.2a8.838,8.838,0,0,1,17.677,0V74.855h3.9a.261.261,0,0,1,.26.26v1.82a.261.261,0,0,1-.26.26H51.46a.261.261,0,0,1-.26-.26v-1.82a.261.261,0,0,1,.26-.26Zm2.34,0h13V64.2a6.5,6.5,0,0,0-13,0ZM63.579,51.2h1.235a.261.261,0,0,1,.26.26v2.6a.261.261,0,0,1-.26.26H63.579a.261.261,0,0,1-.26-.26v-2.6A.262.262,0,0,1,63.579,51.2ZM51.3,58.993l.617-1.069a.26.26,0,0,1,.355-.1l2.251,1.3a.26.26,0,0,1,.1.355L54,60.552a.26.26,0,0,1-.355.1l-2.251-1.3A.26.26,0,0,1,51.3,58.993Zm25.188-1.069.618,1.069a.26.26,0,0,1-.1.355l-2.251,1.3a.26.26,0,0,1-.355-.1l-.617-1.069a.26.26,0,0,1,.1-.355l2.251-1.3A.259.259,0,0,1,76.483,57.924ZM56.395,53.441l1.069-.617a.26.26,0,0,1,.355.1l1.3,2.251a.26.26,0,0,1-.1.355l-1.069.618a.26.26,0,0,1-.355-.1L56.3,53.8A.261.261,0,0,1,56.395,53.441Zm14.524-.617,1.069.617a.26.26,0,0,1,.1.355l-1.3,2.251a.26.26,0,0,1-.355.1l-1.069-.617a.26.26,0,0,1-.1-.355l1.3-2.251a.26.26,0,0,1,.355-.1ZM64.2,73.036a1.3,1.3,0,1,1,1.3-1.3,1.3,1.3,0,0,1-1.3,1.3Zm-.78-11.958h1.56a.261.261,0,0,1,.26.26v7.8a.261.261,0,0,1-.26.26h-1.56a.261.261,0,0,1-.26-.26v-7.8A.261.261,0,0,1,63.418,61.078Z" transform="translate(-51.2 -51.2)" fill="#fff"/>
+</svg>

二進制
src/assets/images/aqjc.png


二進制
src/assets/images/dust-fc.png


二進制
src/assets/images/fire-fz.png


二進制
src/assets/images/gas-ws.png


二進制
src/assets/images/his-one.png


二進制
src/assets/images/vent-tf.png


二進制
src/assets/images/warn-dialog-bg.png


+ 210 - 176
src/layouts/default/header/components/MessageBroadcast.vue

@@ -1,5 +1,5 @@
 <template>
-  <div style="position: fixed; z-index: 999; right: 95px; top: 18px; color: #fff">
+  <div style="position: fixed; z-index: 999; right: 120px; top: 20px; color: #fff">
     <div class="btn" @click="showWarningBroad">
       <a-badge :dot="isWarningDot">
         <BellOutlined style="font-size: 22px; color: #fff; margin-right: 20px" />
@@ -9,24 +9,23 @@
       <div class="title">
         <div class="message-title">预警通知</div>
         <div class="badge-box">
-          <SoundOutlined :class="{ 'no-play': !isBroad }" style="font-size: 20px; color: #000" @click="handleBroad" />
+          <SoundOutlined :class="{ 'no-play': !isBroad }" style="font-size: 16px; color: #fff" @click="handleBroad" />
+         
         </div>
       </div>
       <div class="broadcast-context">
         <div class="context-tab">
-          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 0 }" @click="toSelectList(0)">全部</div>
-          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 1 }" @click="toSelectList(1)">未读</div>
-          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 2 }" @click="toSelectList(2)">已读</div>
+          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 0 }" @click="toSelectList(0)">
+            全部</div>
+          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 1 }" @click="toSelectList(1)">
+            未读</div>
+          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 2 }" @click="toSelectList(2)">
+            已读</div>
         </div>
         <div class="context-box">
           <div v-if="broadcastList.length == 0" class="no-context">暂无内容</div>
-          <div
-            class="context-detail"
-            v-else
-            v-for="(item, index) in broadcastList"
-            :key="index"
-            :style="{ color: item['isok'] == 0 ? 'red' : '#000' }"
-          >
+          <div class="context-detail" v-else v-for="(item, index) in broadcastList" :key="index"
+            :style="{ color: item['isok'] == 0 ? 'red' : '#eee' }">
             <div>{{ item['createTime'] }}</div>
             <div>{{ item['devicekind_dictText'] }}</div>
             <div>{{ item['wardescrip'] || item['nwartype_dictText'] }}</div>
@@ -39,197 +38,232 @@
   </div>
 </template>
 <script lang="ts">
-  import { Tooltip, Badge } from 'ant-design-vue';
-  import { SoundOutlined, BellOutlined, WarningOutlined } from '@ant-design/icons-vue';
-  import Icon from '/@/components/Icon';
-  import { defineComponent, ref, unref, onMounted } from 'vue';
-  import { defHttp } from '/@/utils/http/axios';
-  import { useRouter } from 'vue-router';
-  import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
-  import { getToken } from '/@/utils/auth';
-  import { useUserStore } from '/@/store/modules/user';
-  import { useGlobSetting } from '/@/hooks/setting';
-  import SpeakVoice from './notify/speakVoice';
-
-  export default defineComponent({
-    name: 'VoiceBroadcast',
-    components: { Icon, Tooltip, Badge, SoundOutlined, BellOutlined, WarningOutlined },
-
-    setup() {
-      const speakVoice = new SpeakVoice();
-      const userStore = useUserStore();
-      const glob = useGlobSetting();
-      const router = useRouter();
-      const list = (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params });
-      const activeKey = ref(0);
-      const isShowWarningBroad = ref(false);
-      const isBroad = ref(true);
-      const isWarningDot = ref(false);
-      const broadcastList = ref([]);
-      function showWarningBroad() {
-        isShowWarningBroad.value = !isShowWarningBroad.value;
-        if (isShowWarningBroad.value) {
-          toSelectList(0);
-        }
-      }
+import { Tooltip, Badge } from 'ant-design-vue';
+import { SoundOutlined, BellOutlined, WarningOutlined } from '@ant-design/icons-vue';
+import Icon from '/@/components/Icon';
+import { defineComponent, ref, unref, onMounted } from 'vue';
+import { defHttp } from '/@/utils/http/axios';
+import { useRouter } from 'vue-router';
+import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
+import { getToken } from '/@/utils/auth';
+import { useUserStore } from '/@/store/modules/user';
+import { useGlobSetting } from '/@/hooks/setting';
+import SpeakVoice from './notify/speakVoice';
 
-      function handleBroad() {
-        isBroad.value = !isBroad.value;
-      }
+export default defineComponent({
+  name: 'VoiceBroadcast',
+  components: { Icon, Tooltip, Badge, SoundOutlined, BellOutlined, WarningOutlined },
 
-      async function toSelectList(key) {
-        activeKey.value = key;
-        const res = await list({ pageSize: 20, devicetype: '', isok: key == 1 ? 0 : key == 2 ? 1 : null });
-        broadcastList.value = res['records'];
-        // const isHasWarning = broadcastList.value.findIndex((item) => !item['isok']);
-        // isWarningDot.value = isHasWarning > -1 ? true : false;
+  setup() {
+    const speakVoice = new SpeakVoice();
+    const userStore = useUserStore();
+    const glob = useGlobSetting();
+    const router = useRouter();
+    const list = (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params });
+    const activeKey = ref(0);
+    const isShowWarningBroad = ref(false);
+    const isBroad = ref(true);
+    const isWarningDot = ref(false);
+    const broadcastList = ref([]);
+    function showWarningBroad() {
+      isShowWarningBroad.value = !isShowWarningBroad.value;
+      if (isShowWarningBroad.value) {
+        toSelectList(0);
       }
+    }
 
-      async function toMore() {
-        await router.push({ path: '/monitorChannel/device-monitor/warningHistory' });
-        showWarningBroad();
-      }
+    function handleBroad() {
+      isBroad.value = !isBroad.value;
+    }
 
-      // 初始化 WebSocket
-      function initWebSocket() {
-        let token = getToken();
-        //将登录token生成一个短的标识
-        // let wsClientId = md5(token);
-        // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
-        let userId = unref(userStore.getUserInfo).id + '?token=' + token;
-        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
-        let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
-        connectWebSocket(url);
-        onWebSocket(onWebSocketMessage);
-      }
+    async function toSelectList(key) {
+      activeKey.value = key;
+      const res = await list({ pageSize: 20, devicetype: '', isok: key == 1 ? 0 : key == 2 ? 1 : null });
+      broadcastList.value = res['records'];
+      // const isHasWarning = broadcastList.value.findIndex((item) => !item['isok']);
+      // isWarningDot.value = isHasWarning > -1 ? true : false;
+    }
 
-      function onWebSocketMessage(data) {
-        // console.log('WebSocket 监测消息--------------》', data);
-        if (data.topic === 'warn' || data.cmd === 'user') {
-          if (isBroad.value) {
-            const messageText = data['warndata'];
-            // const messageText = '这是一个测试';
-            speakVoice.handleReply(messageText);
-          }
-          if (!isShowWarningBroad.value) {
-            isWarningDot.value = true;
-          } else {
-            isWarningDot.value = false;
-          }
-          setTimeout(() => {
-            if (isShowWarningBroad.value) {
-              toSelectList(0);
-            }
-          }, 0);
+    async function toMore() {
+      await router.push({ path: '/monitorChannel/device-monitor/warningHistory' });
+      showWarningBroad();
+    }
+
+    // 初始化 WebSocket
+    function initWebSocket() {
+      let token = getToken();
+      //将登录token生成一个短的标识
+      // let wsClientId = md5(token);
+      // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
+      let userId = unref(userStore.getUserInfo).id + '?token=' + token;
+      // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
+      let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
+      connectWebSocket(url);
+      onWebSocket(onWebSocketMessage);
+    }
+
+    function onWebSocketMessage(data) {
+      // console.log('WebSocket 监测消息--------------》', data);
+      if (data.topic === 'warn' || data.cmd === 'user') {
+        if (isBroad.value) {
+          const messageText = data['warndata'];
+          // const messageText = '这是一个测试';
+          speakVoice.handleReply(messageText);
         }
+        if (!isShowWarningBroad.value) {
+          isWarningDot.value = true;
+        } else {
+          isWarningDot.value = false;
+        }
+        setTimeout(() => {
+          if (isShowWarningBroad.value) {
+            toSelectList(0);
+          }
+        }, 0);
       }
-      onMounted(() => {
-        initWebSocket();
-      });
+    }
+    onMounted(() => {
+      initWebSocket();
+    });
 
-      return { showWarningBroad, isShowWarningBroad, activeKey, toSelectList, broadcastList, toMore, isBroad, handleBroad, isWarningDot };
-    },
-  });
+    return { showWarningBroad, isShowWarningBroad, activeKey, toSelectList, broadcastList, toMore, isBroad, handleBroad, isWarningDot };
+  },
+});
 </script>
 <style lang="less" scoped>
-  .btn {
-    line-height: 30px;
-    margin-right: 20px;
-    cursor: pointer;
-    display: flex;
-  }
-  .no-play {
-    background: linear-gradient(
-      to bottom left,
+.btn {
+  line-height: 30px;
+  margin-right: 20px;
+  cursor: pointer;
+  display: flex;
+}
+
+.no-play {
+  background: linear-gradient(to bottom left,
       transparent 0%,
       transparent calc(50% - 1px),
       #000000 50%,
       transparent calc(50% + 1px),
-      transparent 100%
-    );
-  }
-  .broadcast {
-    width: 400px;
-    height: 250px;
-    border-radius: 4px;
-    position: fixed;
-    top: 42px;
-    right: 20px;
-    background-color: rgb(255, 255, 255);
-    z-index: 9999999;
-    color: #000;
-    .title {
-      height: 48px;
-      padding: 0 20px;
-      box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
-      :deep(.ant-badge:not(.ant-badge-status)) {
-        margin-right: 40px !important;
-      }
+      transparent 100%);
+}
+
+.broadcast {
+  width: 400px;
+  height: 250px;
+  border-radius: 4px;
+  position: fixed;
+  top: 50px;
+  right: 20px;
+  background-color: rgb(255, 255, 255);
+  background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
+  background-size: 100% 100%;
+  z-index: 9999999;
+  color: #FFF;
+
+  .title {
+    height: 32px;
+    padding: 0 20px;
+
+    :deep(.ant-badge:not(.ant-badge-status)) {
+      margin-right: 40px !important;
+    }
+
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 5px;
+
+    .message-title {
+      font-size: 16px;
+    }
+
+    .badge-box {
       display: flex;
       align-items: center;
-      justify-content: space-between;
-      margin-bottom: 5px;
-      .message-title {
-        font-size: 20px;
-        // font-weight: 600;
+
+      .badge-title {
+        display: inline-block;
+        width: 62px;
+        line-height: 32px;
+        background-color: #2174f0;
+        border-radius: 26px;
+        text-align: center;
+        color: #fff;
+        padding-bottom: 2px;
       }
-      .badge-box {
-        display: flex;
-        align-items: center;
-        .badge-title {
-          display: inline-block;
-          width: 62px;
-          line-height: 24px;
-          background-color: #2174f0;
-          border-radius: 26px;
-          text-align: center;
-          color: #fff;
-          padding-bottom: 2px;
-        }
+    }
+  }
+
+  .broadcast-context {
+    .context-tab {
+      display: flex;
+
+      .context-tab-item {
+        line-height: 24px;
+        background-color: #6b6b6b;
+        border-radius: 24px;
+        text-align: center;
+        padding: 0 10px;
+        color: #fff;
+        margin: 5px;
+        cursor: pointer;
+        font-size: 14px;
+      }
+
+      .context-tab-item-active {
+        background-color: #2174f0;
       }
     }
-    .broadcast-context {
-      .context-tab {
+
+    .context-box {
+      flex: 1;
+      padding: 0 10px;
+      height: 178px;
+      overflow-y: auto;
+
+      .no-context {
         display: flex;
-        .context-tab-item {
-          line-height: 30px;
-          background-color: #6b6b6b;
-          border-radius: 26px;
-          text-align: center;
-          padding: 0 10px;
-          color: #fff;
-          margin: 5px;
-          cursor: pointer;
-        }
-        .context-tab-item-active {
-          background-color: #2174f0;
-        }
+        justify-content: center;
+        padding-top: 30px;
+        font-size: 16px;
       }
-      .context-box {
-        flex: 1;
-        padding: 0 10px;
-        height: 150px;
-        overflow-y: auto;
-        .no-context {
-          display: flex;
-          justify-content: center;
-          padding-top: 30px;
-          font-size: 16px;
-        }
-        .context-detail {
+
+      .context-detail {
+        display: flex;
+        justify-content: space-between;
+        line-height: 24px;
+        padding: 0px 3px;
+
+        div {
           display: flex;
-          div {
-            padding: 0 3px;
-            line-height: 24px;
+          justify-content: flex-start;
+
+          &:nth-child(1) {
+            width: 40%;
           }
-        }
-        .more {
-          cursor: pointer;
-          &:hover {
-            color: #2174f0;
+
+          &:nth-child(2) {
+            width: 20%;
           }
+
+          &:nth-child(3) {
+            width: 25%;
+          }
+
+          &:nth-child(4) {
+            width: 15%;
+          }
+        }
+      }
+
+      .more {
+        cursor: pointer;
+
+        &:hover {
+          color: #2174f0;
         }
       }
     }
   }
+}
 </style>

+ 209 - 176
src/layouts/default/header/components/VoiceBroadcast.vue

@@ -1,5 +1,5 @@
 <template>
-  <div style="position: fixed; z-index: 999; right: 95px; top: 18px; color: #fff">
+  <div style="position: fixed; z-index: 999; right: 120px; top: 20px; color: #fff">
     <div class="btn" @click="showWarningBroad">
       <!-- <div>语音播报</div>
     <a-badge :count="10">
@@ -14,24 +14,22 @@
       <div class="title">
         <div class="message-title">预警通知</div>
         <div class="badge-box">
-          <SoundOutlined :class="{ 'no-play': !isBroad }" style="font-size: 20px; color: #000" @click="handleBroad" />
+          <SoundOutlined :class="{ 'no-play': !isBroad }" style="font-size: 16px; color: #fff" @click="handleBroad" />
         </div>
       </div>
       <div class="broadcast-context">
         <div class="context-tab">
-          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 0 }" @click="toSelectList(0)">全部</div>
-          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 1 }" @click="toSelectList(1)">未解决</div>
-          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 2 }" @click="toSelectList(2)">已解决</div>
+          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 0 }" @click="toSelectList(0)">
+            全部</div>
+          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 1 }" @click="toSelectList(1)">
+            未解决</div>
+          <div class="context-tab-item" :class="{ 'context-tab-item-active': activeKey == 2 }" @click="toSelectList(2)">
+            已解决</div>
         </div>
         <div class="context-box">
           <div v-if="broadcastList.length == 0" class="no-context">暂无内容</div>
-          <div
-            class="context-detail"
-            v-else
-            v-for="(item, index) in broadcastList"
-            :key="index"
-            :style="{ color: item['isok'] == 0 ? 'red' : '#000' }"
-          >
+          <div class="context-detail" v-else v-for="(item, index) in broadcastList" :key="index"
+            :style="{ color: item['isok'] == 0 ? 'red' : '#eee' }">
             <div>{{ item['createTime'] }}</div>
             <div>{{ item['devicekind_dictText'] }}</div>
             <div>{{ item['wardescrip'] || item['nwartype_dictText'] }}</div>
@@ -44,197 +42,232 @@
   </div>
 </template>
 <script lang="ts">
-  import { Tooltip, Badge } from 'ant-design-vue';
-  import { SoundOutlined, BellOutlined, WarningOutlined } from '@ant-design/icons-vue';
-  import Icon from '/@/components/Icon';
-  import { defineComponent, ref, unref, onMounted } from 'vue';
-  import { defHttp } from '/@/utils/http/axios';
-  import { useRouter } from 'vue-router';
-  import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
-  import { getToken } from '/@/utils/auth';
-  import { useUserStore } from '/@/store/modules/user';
-  import { useGlobSetting } from '/@/hooks/setting';
-  import SpeakVoice from './notify/speakVoice';
-
-  export default defineComponent({
-    name: 'VoiceBroadcast',
-    components: { Icon, Tooltip, Badge, SoundOutlined, BellOutlined, WarningOutlined },
-
-    setup() {
-      const speakVoice = new SpeakVoice();
-      const userStore = useUserStore();
-      const glob = useGlobSetting();
-      const router = useRouter();
-      const list = (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params });
-      const activeKey = ref(0);
-      const isShowWarningBroad = ref(false);
-      const isBroad = ref(true);
-      const isWarningDot = ref(false);
-      const broadcastList = ref([]);
-      function showWarningBroad() {
-        isShowWarningBroad.value = !isShowWarningBroad.value;
-        if (isShowWarningBroad.value) {
-          toSelectList(0);
-        }
-      }
+import { Tooltip, Badge } from 'ant-design-vue';
+import { SoundOutlined, BellOutlined, WarningOutlined } from '@ant-design/icons-vue';
+import Icon from '/@/components/Icon';
+import { defineComponent, ref, unref, onMounted } from 'vue';
+import { defHttp } from '/@/utils/http/axios';
+import { useRouter } from 'vue-router';
+import { connectWebSocket, onWebSocket } from '/@/hooks/web/useWebSocket';
+import { getToken } from '/@/utils/auth';
+import { useUserStore } from '/@/store/modules/user';
+import { useGlobSetting } from '/@/hooks/setting';
+import SpeakVoice from './notify/speakVoice';
 
-      function handleBroad() {
-        isBroad.value = !isBroad.value;
-      }
+export default defineComponent({
+  name: 'VoiceBroadcast',
+  components: { Icon, Tooltip, Badge, SoundOutlined, BellOutlined, WarningOutlined },
 
-      async function toSelectList(key) {
-        activeKey.value = key;
-        const res = await list({ pageSize: 20, devicetype: '', isok: key == 1 ? 0 : key == 2 ? 1 : null });
-        broadcastList.value = res['records'];
-        // const isHasWarning = broadcastList.value.findIndex((item) => !item['isok']);
-        // isWarningDot.value = isHasWarning > -1 ? true : false;
+  setup() {
+    const speakVoice = new SpeakVoice();
+    const userStore = useUserStore();
+    const glob = useGlobSetting();
+    const router = useRouter();
+    const list = (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params });
+    const activeKey = ref(0);
+    const isShowWarningBroad = ref(false);
+    const isBroad = ref(true);
+    const isWarningDot = ref(false);
+    const broadcastList = ref([]);
+    function showWarningBroad() {
+      isShowWarningBroad.value = !isShowWarningBroad.value;
+      if (isShowWarningBroad.value) {
+        toSelectList(0);
       }
+    }
 
-      async function toMore() {
-        await router.push({ path: '/monitorChannel/device-monitor/warningHistory' });
-        showWarningBroad();
-      }
+    function handleBroad() {
+      isBroad.value = !isBroad.value;
+    }
 
-      // 初始化 WebSocket
-      function initWebSocket() {
-        let token = getToken();
-        //将登录token生成一个短的标识
-        // let wsClientId = md5(token);
-        // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
-        let userId = unref(userStore.getUserInfo).id + '?token=' + token;
-        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
-        let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
-        connectWebSocket(url);
-        onWebSocket(onWebSocketMessage);
-      }
+    async function toSelectList(key) {
+      activeKey.value = key;
+      const res = await list({ pageSize: 20, devicetype: '', isok: key == 1 ? 0 : key == 2 ? 1 : null });
+      broadcastList.value = res['records'];
+      // const isHasWarning = broadcastList.value.findIndex((item) => !item['isok']);
+      // isWarningDot.value = isHasWarning > -1 ? true : false;
+    }
 
-      function onWebSocketMessage(data) {
-        // console.log('WebSocket 监测消息--------------》', data);
-        if (data.topic === 'warn' || data.cmd === 'user') {
-          if (isBroad.value) {
-            const messageText = data['warndata'];
-            // const messageText = '这是一个测试';
-            speakVoice.handleReply(messageText);
-          }
-          if (!isShowWarningBroad.value) {
-            isWarningDot.value = true;
-          } else {
-            isWarningDot.value = false;
-          }
-          setTimeout(() => {
-            if (isShowWarningBroad.value) {
-              toSelectList(0);
-            }
-          }, 0);
+    async function toMore() {
+      await router.push({ path: '/monitorChannel/device-monitor/warningHistory' });
+      showWarningBroad();
+    }
+
+    // 初始化 WebSocket
+    function initWebSocket() {
+      let token = getToken();
+      //将登录token生成一个短的标识
+      // let wsClientId = md5(token);
+      // let userId = unref(userStore.getUserInfo).id + '_' + wsClientId;
+      let userId = unref(userStore.getUserInfo).id + '?token=' + token;
+      // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
+      let url = glob.wsUrl?.replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId;
+      connectWebSocket(url);
+      onWebSocket(onWebSocketMessage);
+    }
+
+    function onWebSocketMessage(data) {
+      // console.log('WebSocket 监测消息--------------》', data);
+      if (data.topic === 'warn' || data.cmd === 'user') {
+        if (isBroad.value) {
+          const messageText = data['warndata'];
+          // const messageText = '这是一个测试';
+          speakVoice.handleReply(messageText);
         }
+        if (!isShowWarningBroad.value) {
+          isWarningDot.value = true;
+        } else {
+          isWarningDot.value = false;
+        }
+        setTimeout(() => {
+          if (isShowWarningBroad.value) {
+            toSelectList(0);
+          }
+        }, 0);
       }
-      onMounted(() => {
-        initWebSocket();
-      });
+    }
+    onMounted(() => {
+      initWebSocket();
+    });
 
-      return { showWarningBroad, isShowWarningBroad, activeKey, toSelectList, broadcastList, toMore, isBroad, handleBroad, isWarningDot };
-    },
-  });
+    return { showWarningBroad, isShowWarningBroad, activeKey, toSelectList, broadcastList, toMore, isBroad, handleBroad, isWarningDot };
+  },
+});
 </script>
 <style lang="less" scoped>
-  .btn {
-    line-height: 30px;
-    margin-right: 20px;
-    cursor: pointer;
-    display: flex;
-  }
-  .no-play {
-    background: linear-gradient(
-      to bottom left,
+.btn {
+  line-height: 30px;
+  margin-right: 20px;
+  cursor: pointer;
+  display: flex;
+}
+
+.no-play {
+  background: linear-gradient(to bottom left,
       transparent 0%,
       transparent calc(50% - 1px),
       #000000 50%,
       transparent calc(50% + 1px),
-      transparent 100%
-    );
-  }
-  .broadcast {
-    width: 400px;
-    height: 250px;
-    border-radius: 4px;
-    position: fixed;
-    top: 42px;
-    right: 20px;
-    background-color: rgb(255, 255, 255);
-    z-index: 9999999;
-    color: #000;
-    .title {
-      height: 48px;
-      padding: 0 20px;
-      box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
-      :deep(.ant-badge:not(.ant-badge-status)) {
-        margin-right: 40px !important;
-      }
+      transparent 100%);
+}
+
+.broadcast {
+  width: 400px;
+  height: 250px;
+  border-radius: 4px;
+  position: fixed;
+  top: 50px;
+  right: 20px;
+  background-color: rgb(255, 255, 255);
+  background: url('../../../../assets/images/warn-dialog-bg.png') no-repeat center;
+  background-size: 100% 100%;
+  z-index: 9999999;
+  color: #FFF;
+
+  .title {
+    height: 32px;
+    padding: 0 20px;
+
+    :deep(.ant-badge:not(.ant-badge-status)) {
+      margin-right: 40px !important;
+    }
+
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    margin-bottom: 5px;
+
+    .message-title {
+      font-size: 16px;
+    }
+
+    .badge-box {
       display: flex;
       align-items: center;
-      justify-content: space-between;
-      margin-bottom: 5px;
-      .message-title {
-        font-size: 20px;
-        // font-weight: 600;
+
+      .badge-title {
+        display: inline-block;
+        width: 62px;
+        line-height: 32px;
+        background-color: #2174f0;
+        border-radius: 26px;
+        text-align: center;
+        color: #fff;
+        padding-bottom: 2px;
       }
-      .badge-box {
-        display: flex;
-        align-items: center;
-        .badge-title {
-          display: inline-block;
-          width: 62px;
-          line-height: 24px;
-          background-color: #2174f0;
-          border-radius: 26px;
-          text-align: center;
-          color: #fff;
-          padding-bottom: 2px;
-        }
+    }
+  }
+
+  .broadcast-context {
+    .context-tab {
+      display: flex;
+
+      .context-tab-item {
+        line-height: 24px;
+        background-color: #6b6b6b;
+        border-radius: 24px;
+        text-align: center;
+        padding: 0 10px;
+        color: #fff;
+        margin: 5px;
+        cursor: pointer;
+        font-size: 14px;
+      }
+
+      .context-tab-item-active {
+        background-color: #2174f0;
       }
     }
-    .broadcast-context {
-      .context-tab {
+
+    .context-box {
+      flex: 1;
+      padding: 0 10px;
+      height: 178px;
+      overflow-y: auto;
+
+      .no-context {
         display: flex;
-        .context-tab-item {
-          line-height: 30px;
-          background-color: #6b6b6b;
-          border-radius: 26px;
-          text-align: center;
-          padding: 0 10px;
-          color: #fff;
-          margin: 5px;
-          cursor: pointer;
-        }
-        .context-tab-item-active {
-          background-color: #2174f0;
-        }
+        justify-content: center;
+        padding-top: 30px;
+        font-size: 16px;
       }
-      .context-box {
-        flex: 1;
-        padding: 0 10px;
-        height: 150px;
-        overflow-y: auto;
-        .no-context {
-          display: flex;
-          justify-content: center;
-          padding-top: 30px;
-          font-size: 16px;
-        }
-        .context-detail {
+
+      .context-detail {
+        display: flex;
+        justify-content: space-between;
+        line-height: 24px;
+        padding: 0px 3px;
+
+        div {
           display: flex;
-          div {
-            padding: 0 3px;
-            line-height: 24px;
+          justify-content: flex-start;
+
+          &:nth-child(1) {
+            width: 40%;
           }
-        }
-        .more {
-          cursor: pointer;
-          &:hover {
-            color: #2174f0;
+
+          &:nth-child(2) {
+            width: 20%;
           }
+
+          &:nth-child(3) {
+            width: 25%;
+          }
+
+          &:nth-child(4) {
+            width: 15%;
+          }
+        }
+      }
+
+      .more {
+        cursor: pointer;
+
+        &:hover {
+          color: #2174f0;
         }
       }
     }
   }
+}
 </style>

+ 335 - 222
src/views/vent/monitorManager/warningMonitor/index.vue

@@ -1,5 +1,21 @@
 <template>
-  <div class="data-statistics"> </div>
+  <div class="data-statistics">
+    <div class="statistics-box" v-for="(item, index) in statisticsList" :key="index">
+      <div class="left-box">
+        <div class="box-title">{{ item.title }}</div>
+      </div>
+      <div class="right-box">
+        <div class="box-text">
+          <div class="text-label">监测数量</div>
+          <div class="text-value">{{ item.valueT }}</div>
+        </div>
+        <div class="box-text">
+          <div class="text-label">预警状态</div>
+          <div class="text-value">{{ item.valueB }}</div>
+        </div>
+      </div>
+    </div>
+  </div>
   <div class="alarm-history-table">
     <BasicTable ref="alarmHistory" @register="registerTable">
       <template #form-onExportXls>
@@ -10,239 +26,336 @@
 </template>
 
 <script lang="ts" name="system-user" setup>
-  //ts语法
-  import { watch, ref, defineExpose, inject, onMounted } from 'vue';
-  import { BasicTable } from '/@/components/Table';
-  import { useListPage } from '/@/hooks/system/useListPage';
-  import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
-  import { defHttp } from '/@/utils/http/axios';
-  import dayjs from 'dayjs';
-  import { getAutoScrollContainer } from '/@/utils/common/compUtils';
-  import { list } from './warning.api';
-
-  const props = defineProps({
-    deviceListApi: {
-      type: Function,
-    },
-    designScope: {
-      type: String,
-    },
-    sysId: {
-      type: String,
-    },
-    list: {
-      type: Function,
-      default: (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params }),
-    },
-  });
-
-  const alarmHistory = ref();
-  const columns = getTableHeaderColumns('alarm_history');
-
-  // 列表页面公共参数、方法
-  const { tableContext, onExportXls } = useListPage({
-    tableProps: {
-      api: list,
-      columns: columns,
-      canResize: true,
-      showTableSetting: false,
-      showActionColumn: false,
-      bordered: false,
-      size: 'small',
-      formConfig: {
-        labelAlign: 'left',
-        showAdvancedButton: false,
-        // autoAdvancedCol: 2,
-        schemas: [
-          {
-            label: '是否解决',
-            field: 'isok',
-            component: 'Select',
-            componentProps: {
-              options: [
-                {
-                  label: '未解决',
-                  value: '0',
-                },
-                {
-                  label: '已解决',
-                  value: '1',
-                },
-              ],
-            },
-            colProps: { span: 4 },
+//ts语法
+import { watch, ref, defineExpose, inject, onMounted, reactive } from 'vue';
+import { BasicTable } from '/@/components/Table';
+import { useListPage } from '/@/hooks/system/useListPage';
+import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
+import { defHttp } from '/@/utils/http/axios';
+import dayjs from 'dayjs';
+import { getAutoScrollContainer } from '/@/utils/common/compUtils';
+import { list } from './warning.api';
+
+const props = defineProps({
+  deviceListApi: {
+    type: Function,
+  },
+  designScope: {
+    type: String,
+  },
+  sysId: {
+    type: String,
+  },
+  list: {
+    type: Function,
+    default: (params) => defHttp.get({ url: '/safety/ventanalyAlarmLog/list', params }),
+  },
+});
+
+let statisticsList = reactive<any[]>([
+  { title: '通风', valueT: '4854', valueB: '低风险' },
+  { title: '粉尘', valueT: '4854', valueB: '低风险' },
+  { title: '瓦斯', valueT: '4854', valueB: '低风险' },
+  { title: '火灾', valueT: '4854', valueB: '低风险' },
+  { title: '安全监测', valueT: '4854', valueB: '低风险' },
+])
+const alarmHistory = ref();
+const columns = getTableHeaderColumns('alarm_history');
+
+// 列表页面公共参数、方法
+const { tableContext, onExportXls } = useListPage({
+  tableProps: {
+    api: list,
+    columns: columns,
+    canResize: true,
+    showTableSetting: false,
+    showActionColumn: false,
+    bordered: false,
+    size: 'small',
+    formConfig: {
+      labelAlign: 'left',
+      showAdvancedButton: false,
+      // autoAdvancedCol: 2,
+      schemas: [
+        {
+          label: '是否解决',
+          field: 'isok',
+          component: 'Select',
+          componentProps: {
+            options: [
+              {
+                label: '未解决',
+                value: '0',
+              },
+              {
+                label: '已解决',
+                value: '1',
+              },
+            ],
           },
-          {
-            label: '所属系统',
-            field: 'kindtype',
-            component: 'Select',
-            componentProps: {
-              options: [
-                {
-                  label: '通风',
-                  value: 'ventS',
-                },
-                {
-                  label: '防灭火',
-                  value: 'fireS',
-                },
-                {
-                  label: '防尘',
-                  value: 'dustS',
-                },
-                {
-                  label: '瓦斯',
-                  value: 'gasS',
-                },
-              ],
-            },
-            colProps: { span: 4 },
+          colProps: { span: 4 },
+        },
+        {
+          label: '所属系统',
+          field: 'kindtype',
+          component: 'Select',
+          componentProps: {
+            options: [
+              {
+                label: '通风',
+                value: 'ventS',
+              },
+              {
+                label: '防灭火',
+                value: 'fireS',
+              },
+              {
+                label: '防尘',
+                value: 'dustS',
+              },
+              {
+                label: '瓦斯',
+                value: 'gasS',
+              },
+            ],
           },
+          colProps: { span: 4 },
+        },
 
-          {
-            field: 'startTime',
-            label: '开始时间',
-            component: 'DatePicker',
-            defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD HH:mm:ss'),
-            required: true,
-            componentProps: {
-              showTime: true,
-              valueFormat: 'YYYY-MM-DD HH:mm:ss',
-              getPopupContainer: getAutoScrollContainer,
-            },
-            colProps: {
-              span: 4,
-            },
+        {
+          field: 'startTime',
+          label: '开始时间',
+          component: 'DatePicker',
+          defaultValue: dayjs().add(-30, 'day').format('YYYY-MM-DD HH:mm:ss'),
+          required: true,
+          componentProps: {
+            showTime: true,
+            valueFormat: 'YYYY-MM-DD HH:mm:ss',
+            getPopupContainer: getAutoScrollContainer,
           },
-          {
-            field: 'endTime',
-            label: '结束时间',
-            component: 'DatePicker',
-            defaultValue: dayjs(),
-            required: true,
-            componentProps: {
-              showTime: true,
-              valueFormat: 'YYYY-MM-DD HH:mm:ss',
-              getPopupContainer: getAutoScrollContainer,
-            },
-            colProps: {
-              span: 4,
-            },
+          colProps: {
+            span: 4,
           },
-        ],
-      },
-      fetchSetting: {
-        listField: 'records',
-      },
-      pagination: {
-        current: 1,
-        pageSize: 10,
-        pageSizeOptions: ['10', '30', '50', '100'],
-      },
-      beforeFetch(params) {
-        // params.devicetype = params.devicetype ? params.devicetype + '*' : '';
-        if (props.sysId) {
-          params.sysId = props.sysId;
-        }
-      },
+        },
+        {
+          field: 'endTime',
+          label: '结束时间',
+          component: 'DatePicker',
+          defaultValue: dayjs(),
+          required: true,
+          componentProps: {
+            showTime: true,
+            valueFormat: 'YYYY-MM-DD HH:mm:ss',
+            getPopupContainer: getAutoScrollContainer,
+          },
+          colProps: {
+            span: 4,
+          },
+        },
+      ],
+    },
+    fetchSetting: {
+      listField: 'records',
     },
-    exportConfig: {
-      name: '预警历史列表',
-      url: '/safety/ventanalyAlarmLog/exportXls',
+    pagination: {
+      current: 1,
+      pageSize: 10,
+      pageSizeOptions: ['10', '30', '50', '100'],
     },
-  });
-  //注册table数据
-  const [registerTable, { reload, setLoading, getForm }] = tableContext;
+    beforeFetch(params) {
+      // params.devicetype = params.devicetype ? params.devicetype + '*' : '';
+      if (props.sysId) {
+        params.sysId = props.sysId;
+      }
+    },
+  },
+  exportConfig: {
+    name: '预警历史列表',
+    url: '/safety/ventanalyAlarmLog/exportXls',
+  },
+});
+//注册table数据
+const [registerTable, { reload, setLoading, getForm }] = tableContext;
 
-  onMounted(async () => {});
+onMounted(async () => { });
 
-  defineExpose({ setLoading });
+defineExpose({ setLoading });
 </script>
 
 <style scoped lang="less">
-  @ventSpace: zxm;
-  :deep(.zxm-table-container) {
-    max-height: 720px !important;
-  }
-  :deep(.ventSpace-table-body) {
-    height: auto !important;
-  }
-  :deep(.zxm-picker) {
-    height: 30px !important;
-  }
-  :deep(.@{ventSpace}-picker-dropdown) {
-    position: absolute !important;
-    top: 35px !important;
-    left: 0 !important;
-  }
-  .data-statistics {
-    height: 200px;
-    padding: 20px;
-    margin-top: 20px;
-    background-color: #0ebbff15;
-  }
-  // .tab-button-group {
-  //   // line-height: 60px;
-  //   margin-top: 16px;
-  //   display: flex;
-  //   pointer-events: auto;
-  //   position: relative;
-  //   &::after {
-  //     position: absolute;
-  //     content: '';
-  //     width: calc(100% + 10px);
-  //     height: 2px;
-  //     top: 44px;
-  //     left: -10px;
-  //     border-bottom: 1px solid #0efcff;
-  //   }
-  //   .tab-button {
-  //     padding: 10px 30px;
-  //     position: relative;
-  //     display: flex;
-  //     justify-content: center;
-  //     align-items: center;
-  //     font-size: 16px;
-  //     color: #fff;
-  //     cursor: pointer;
-  //     margin-right: 10px;
-  //     background-color: rgba(0, 103, 103, 0.253);
-  //     &::before {
-  //       content: '';
-  //       position: absolute;
-  //       top: 0;
-  //       right: 0;
-  //       bottom: 0;
-  //       left: 0;
-  //       border: 1px solid #2bb2c4;
-  //       // transform: skewX(-38deg);
-  //       // background-color: rgba(0, 77, 103, 85%);
-  //       z-index: 0;
-  //     }
-  //     &::after {
-  //       background-color: rgba(0, 77, 103, 85%);
-  //     }
-  //   }
-  //   .active {
-  //     &::before {
-  //       border-color: #46fcff;
-  //       box-shadow: 1px 1px 10px 2px #0efcff99 inset;
-  //     }
-  //   }
-  // }
-  .alarm-history-table {
-    width: 100%;
-    background-color: #0ebbff15;
-    position: relative;
-    margin-top: 10px;
-    &::after {
-      position: absolute;
-      content: '';
-      width: calc(100% + 10px);
-      height: 2px;
-      top: 0px;
-      left: -10px;
-      border-bottom: 1px solid #0efcff99;
+@ventSpace: zxm;
+
+:deep(.zxm-table-container) {
+  max-height: 720px !important;
+}
+
+:deep(.ventSpace-table-body) {
+  height: auto !important;
+}
+
+:deep(.zxm-picker) {
+  height: 30px !important;
+}
+
+:deep(.@{ventSpace}-picker-dropdown) {
+  position: absolute !important;
+  top: 35px !important;
+  left: 0 !important;
+}
+
+.data-statistics {
+  height: 200px;
+  padding: 20px;
+  margin-top: 20px;
+  background-color: #0ebbff15;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+
+  .statistics-box {
+    display: flex;
+    flex: 1;
+    height: 100%;
+    justify-content: center;
+    align-items: center;
+
+    .left-box {
+      position: relative;
+      width: 138px;
+      height: 100%;
+
+      .box-title {
+        position: absolute;
+        left: 50%;
+        bottom: 18px;
+        transform: translate(-50%, 0);
+        color: #fff;
+      }
+    }
+
+    &:nth-child(1) .left-box {
+      background: url('../../../../assets/images/vent-tf.png') no-repeat center;
+      background-size: 100% auto
+    }
+
+    &:nth-child(2) .left-box {
+      background: url('../../../../assets/images/dust-fc.png') no-repeat center;
+      background-size: 100% auto
+    }
+
+    &:nth-child(3) .left-box {
+      background: url('../../../../assets/images/gas-ws.png') no-repeat center;
+      background-size: 100% auto
     }
+
+    &:nth-child(4) .left-box {
+      background: url('../../../../assets/images/fire-fz.png') no-repeat center;
+      background-size: 100% auto
+    }
+
+    &:nth-child(5) .left-box {
+      background: url('../../../../assets/images/aqjc.png') no-repeat center;
+      background-size: 100% auto
+    }
+
+    .right-box {
+      position: relative;
+      width: 215px;
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-around;
+      align-items: center;
+
+      .box-text {
+        position: relative;
+        width: 100%;
+        height: 40px;
+        color: #fff;
+        background: url('../../../../assets/images/his-one.png') no-repeat center;
+        background-size: 100% 100%;
+
+        .text-label {
+          position: absolute;
+          left: 20px;
+          top: 50%;
+          transform: translate(0, -50%);
+        }
+
+        .text-value {
+          position: absolute;
+          left: 130px;
+          top: 50%;
+          transform: translate(0, -50%);
+        }
+      }
+    }
+  }
+}
+
+// .tab-button-group {
+//   // line-height: 60px;
+//   margin-top: 16px;
+//   display: flex;
+//   pointer-events: auto;
+//   position: relative;
+//   &::after {
+//     position: absolute;
+//     content: '';
+//     width: calc(100% + 10px);
+//     height: 2px;
+//     top: 44px;
+//     left: -10px;
+//     border-bottom: 1px solid #0efcff;
+//   }
+//   .tab-button {
+//     padding: 10px 30px;
+//     position: relative;
+//     display: flex;
+//     justify-content: center;
+//     align-items: center;
+//     font-size: 16px;
+//     color: #fff;
+//     cursor: pointer;
+//     margin-right: 10px;
+//     background-color: rgba(0, 103, 103, 0.253);
+//     &::before {
+//       content: '';
+//       position: absolute;
+//       top: 0;
+//       right: 0;
+//       bottom: 0;
+//       left: 0;
+//       border: 1px solid #2bb2c4;
+//       // transform: skewX(-38deg);
+//       // background-color: rgba(0, 77, 103, 85%);
+//       z-index: 0;
+//     }
+//     &::after {
+//       background-color: rgba(0, 77, 103, 85%);
+//     }
+//   }
+//   .active {
+//     &::before {
+//       border-color: #46fcff;
+//       box-shadow: 1px 1px 10px 2px #0efcff99 inset;
+//     }
+//   }
+// }
+.alarm-history-table {
+  width: 100%;
+  background-color: #0ebbff15;
+  position: relative;
+  margin-top: 10px;
+
+  &::after {
+    position: absolute;
+    content: '';
+    width: calc(100% + 10px);
+    height: 2px;
+    top: 0px;
+    left: -10px;
+    border-bottom: 1px solid #0efcff99;
   }
+}
 </style>