Browse Source

增加一键110弹窗;防爆扩音弹窗;站内人员弹窗

fan 4 months ago
parent
commit
6722c6ebe5

+ 2 - 2
README.md

@@ -1,6 +1,6 @@
-# ISMS-Visualization-XNGD-NN-NNYK
+# ISMS-Visualization-BJGD-TKT
 
-## 南宁油库风险管控平台
+## 托克托综合安防平台
 
 ### Project setup
 

+ 10 - 6
public/js/config.js

@@ -130,7 +130,7 @@ const MQTT_CONFIG = {
    * 订阅主题 单字符串or字符串数组
    */
   topic: [
-    'Positioning/#',
+    // 'Positioning/#',
     'Alarm/List',
     'Message/New',
     'Perimeter/#',
@@ -142,8 +142,8 @@ const MQTT_CONFIG = {
 }
 //后台管理根路径
 const ISMSAdminWeb = {
-  // path: "http://172.168.0.62:8080/#/",
-  path: `http://192.168.195.136:8080/#/`,
+  path: "http://172.168.0.62:8080/#/",
+  // path: `http://192.168.195.136:8080/#/`,
   // path: `http://${window.location.hostname}:8080/#/`,
 }
 
@@ -636,9 +636,13 @@ const GY_JGYT_CONFIG = [
         name: '托克托压气站',
         children: [
           {
-            id: '1',
-            // id: '660856349529219072',
-            name: '云台1',
+            id: '786542179467141120',
+            name: '激光检测1',
+            ndTag: 'DY_Leak_PTZ_Concn',
+          },
+          {
+            id: '786542180738015232',
+            name: '激光检测2',
             ndTag: 'DY_Leak_PTZ_Concn',
           },
         ],

+ 5 - 5
src/router/index.js

@@ -107,11 +107,11 @@ router.beforeEach(async (to, from, next) => {
     token = localStorage.getItem('token')
   }
   if (!token && to.name !== 'Login') {
-    /*Message({
-      message: "无访问权限,请先登录!",
-      type: "error",
-      duration: 800
-    });*/
+    // Message({
+    //   message: "无访问权限,请先登录!",
+    //   type: "error",
+    //   duration: 800
+    // });
     next('/login')
   } else {
     console.log(to.name)

+ 3 - 0
src/store/getters.js

@@ -9,6 +9,9 @@ const getters = {
   yuanID: (state) => state.home.yuanID,
   alarmDataCount: (state) => state.globalConfig.alarmDataCount,
   alarmAudio: (state) => state.globalConfig.alarmAudio,//全局报警声音
+  oneKey110: (state) => state.globalConfig.oneKey110,//一键110
+  soundDialog: (state) => state.globalConfig.soundDialog,//防爆扩音
+  personListDialog: (state) => state.globalConfig.personListDialog,//站内人员统计
   rtTag: (state) => state.globalConfig.RTTag,
   rtData: (state) => state.globalConfig.RTData,
   netWorkList: (state) => state.globalConfig.netWorkList,

+ 21 - 0
src/store/modules/globalConfig.js

@@ -7,6 +7,9 @@ const state = {
   alarmDataObj: {}, //所有报警信息的集合,用以实时更新lebel标签的数据,以及初次报警标签的显示
   alarmDataCount: 0,
   alarmAudio: { show: false, alarmType: "all" },
+  oneKey110: { show: false, dialogMsg: {}, type: "all" },
+  soundDialog: { show: false, dialogMsg: {}, type: "all" },
+  personListDialog: { show: false, dialogMsg: [], type: "all" },
   RTTag: {
     //"layer_id":["tag1","tag2"]
   },
@@ -40,6 +43,15 @@ const mutations = {
   SET_ALARMAUDIO(state, data) {
     state.alarmAudio = data;
   },
+  SET_ONEKEY110(state, data) {
+    state.oneKey110 = data;
+  },
+  SET_SOUNDDIALOG(state, data) {
+    state.soundDialog = data;
+  },
+  SET_PERSONLISTDIALOG(state, data) {
+    state.personListDialog = data;
+  },
   SET_SWITCHCONFIG(state, data) {
     // const types = state.switchConfig.map((e) => e.type)
     // data.forEach((item, index) => {
@@ -140,6 +152,15 @@ const actions = {
   setAlarmAudio({ commit }, data) {
     commit("SET_ALARMAUDIO", data);
   },
+  setOneKey110({ commit }, data) {
+    commit("SET_ONEKEY110", data);
+  },
+  setSoundDialog({ commit }, data) {
+    commit("SET_SOUNDDIALOG", data);
+  },
+  setPersonListDialog({ commit }, data) {
+    commit("SET_PERSONLISTDIALOG", data);
+  },
   setSwitchConfig({ commit }, data) {
     commit('SET_SWITCHCONFIG', data)
   },

+ 2 - 2
src/utils/index.js

@@ -43,8 +43,8 @@ export function _locate(xDist, yDist, c = { x: 108.4416707584088, y: 22.86248482
   // console.log(c, xDist, yDist);
   // console.log(c)
   const radius = 6378137 //坐标系球的半径  WGS84是6378137
-  let xOffset = -2700 //x偏移量 单位mm  -7400;// 400 tkt  -700 duyun
-  let yOffset = 2000 //y偏移量 单位mm   1800;// 100 tkt  1600 duyun
+  let xOffset = -2700 //x偏移量 单位mm  -7400;// -2700 tkt  -700 duyun
+  let yOffset = 2000 //y偏移量 单位mm   1800;// 2000 tkt  1600 duyun
   //console.log("before", xDist, yDist)
   xDist = +xDist + xOffset
   yDist = +yDist + yOffset

+ 18 - 4
src/views/Home.vue

@@ -9,13 +9,19 @@
     <!-- 底部背景 -->
     <div class="footer" v-show="hasToken && !fullScreen"></div>
     <!-- 应急选项卡列表 -->
-    <card-list-dialog />
+    <!-- <card-list-dialog /> -->
     <!-- 应急选项卡详情 -->
-    <card-detail-dialog />
+    <!-- <card-detail-dialog /> -->
     <!-- 联系人弹窗 -->
-    <contact-info-dialog />
+    <!-- <contact-info-dialog /> -->
     <!-- 报警详情弹窗 由vuex控制 -->
     <alarm-detail-dialog />
+    <!-- 一键报警弹窗 由vuex控制 -->
+    <onekey-110-dialog />
+    <!-- 防爆扩音弹窗 由vuex控制 -->
+    <sound-dialog />
+    <!-- 人员列表弹窗 由vuex控制 -->
+    <person-list-dialog />
     <!-- 全局声音播放器 由vuex控制 -->
     <alarm-audio-dialog :dialogConfig="alarmAudio" />
     <!-- <preview-PDF /> -->
@@ -49,6 +55,9 @@ import BaseHeader from "@/views/components/baseHeader/left.vue";
 import CardListDialog from "@/views/components/emergency/CardListDialog";
 import CardDetailDialog from "@/views/components/emergency/CardDetailDialog";
 import ContactInfoDialog from "@/views/components/emergency/ContactInfoDialog";
+import PersonListDialog from "@/views/components/dialog/PersonListDialog";
+import Onekey110Dialog from "@/views/components/dialog/Onekey110Dialog";
+import SoundDialog from "@/views/components/dialog/SoundDialog";
 import AlarmDetailDialog from "@/views/components/dialog/AlarmDetailDialog";
 import AlarmAudioDialog from "@/views/components/dialog/AlarmAudioDialog";
 import RiskTipDialog from "@/views/components/dialog/RiskTipDialog";
@@ -69,9 +78,12 @@ export default {
     CardDetailDialog,
     ContactInfoDialog,
     AlarmDetailDialog,
+    Onekey110Dialog,
+    PersonListDialog,
+    SoundDialog,
     AlarmAudioDialog,
     RiskTipDialog,
-    BaseBlankDialog,
+    BaseBlankDialog
   },
   computed: {
     ...mapGetters([
@@ -79,6 +91,8 @@ export default {
       "blankDialogs",
       "alarmDetailDialog",
       "alarmAudio",
+      "oneKey110",
+      "personListDialog",
     ]),
   },
   watch: {

+ 5 - 6
src/views/basePage/mixins/LoadLayer/JGYT.js

@@ -45,7 +45,6 @@ export default {
   data() {
     return {
       jgytTagsData: [],
-      jgytLayerShow: false,
       jgytConfig: [
         // 激光云台配置信息
       ],
@@ -80,11 +79,11 @@ export default {
     },
     buildId: {
       handler(val) {
-        console.log('激光云台图层建筑变化', val)
+        // console.log('激光云台图层建筑变化', val)
         if (!val) return
         setTimeout(() => {
           this.getJGYTTagsData()
-        }, 3000)
+        }, 1000)
         // setTimeout(() => {
         //   this.pushJGYTStatus(mockAlarmData)
         // }, 5000)
@@ -143,15 +142,15 @@ export default {
 
         let res = await getTagList(p)
         let content = res.data.content || []
-        // console.log('激光云台', res)
-        // const curStationJGYT = content.filter(n => n?.buildId == this.buildId) // 过滤当前建筑的激光云台
+        // console.log('激光云台', res, this.buildId)
+        const curStationJGYT = content.filter(n => n?.buildId == this.buildInfo.positioningBuildId) // 过滤当前建筑的激光云台
         // console.log('激光云台', curStationJGYT)
         // 在不改变原有数据结构的情况下,添加激光云台和建筑id的绑定
         this.jgytTagsData = content.map(n => {
           const videoConfig = {
             // cameraID: '0',
             type: 'jgyt',
-            ptzEnable: false,
+            ptzEnable: true,
             tags: { ndTag: n.concentrationTag, gqTag: n.lightIntensityTag, spTag: n.panTag, czTag: n.tileTag },
           }
           // if (n.cameraID == '0') {

+ 3 - 2
src/views/basePage/mixins/LoadLayer/camera.js

@@ -69,8 +69,9 @@ export default {
     },
     addCameraTags() {
       let dataSource = addNewDatasource('layer_' + this.cameraDataSourceName)
-      this.cameraTagsData.forEach(d => {
-        d.GPSPoints = this.transPosition([{ x: d.location.x, y: d.location.y, z: 5 }])
+      // console.log("摄像头基础信息", this.cameraTagsData);
+      this.cameraTagsData.filter(e => !e.canHide).forEach(d => {
+        d.GPSPoints = this.transPosition([{ x: d.location.x, y: d.location.y, z: d.height }])
         dataSource.entities.add(
           new Entity({
             id: d.id,

+ 0 - 1
src/views/basePage/mixins/LoadLayer/perimeter.js

@@ -74,7 +74,6 @@ export default {
   data() {
     return {
       perimeterTagsData: [],
-      perimeterTagsShow: false,
       perimeterAlarmIds: [],
       clonePerimeterTagsData: [],
       testSegmentId: '545274088122228739',

+ 3 - 1
src/views/basePage/panels/Overview.vue

@@ -177,7 +177,7 @@ export default {
     gotoAlarmList(category, index) {
       console.log("params", category, index);
 
-      if (category.startsWith("0")) return;
+      if (category && category.startsWith("0")) return;
       let dealStatus = undefined;
       let confirmStatus = undefined;
       if (index === 0) {
@@ -199,6 +199,8 @@ export default {
         .replace(/:/g, "=")
         .replace(/\":\"/g, "=")
         .replace(/\"/g, "");
+      console.log("报警列表参数", query);
+
       this.$router.push("/alarmlist?" + query);
     },
   },

+ 35 - 7
src/views/basePage/panels/PersonStatistics.vue

@@ -12,7 +12,10 @@
         >
           <div class="item" v-for="item of personList" :key="item.id">
             <div class="left">
-              <img src="~@/assets/imgs/stationMap/img_无照片.png" />
+              <img
+                src="~@/assets/imgs/stationMap/img_无照片.png"
+                @click="openPersonInfo"
+              />
             </div>
             <div class="divider"></div>
             <div class="right">
@@ -60,6 +63,7 @@
             <img
               :src="require('@/assets/imgs/panels/img_personnel_01@2x.png')"
               alt=""
+              @click="openPersonList()"
             />
             <span class="totle">{{ total }}</span>
             <span class="text">总数</span>
@@ -113,7 +117,7 @@ export default {
   components: { BaseTitle, VueSeamless },
   data() {
     return {
-      total: 0,
+      total: 4,
       personTypeCount: [
         {
           name: "员工",
@@ -152,7 +156,7 @@ export default {
       ],
       scrollOption: {
         limitMoveNum: 2,
-        singleHeight: 180,
+        singleHeight: 173,
         waitTime: 5000,
       },
       personList: [
@@ -163,8 +167,9 @@ export default {
           type: "值班干部",
           posi: "主任",
           personType: "员工",
-          comp:'XXXXX公司',
+          comp: "XXXXX公司",
           phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
         },
         {
           id: "2",
@@ -173,8 +178,9 @@ export default {
           type: "值班门卫",
           posi: "运维操作工",
           personType: "员工",
-          comp:'XXXXX公司',
+          comp: "XXXXX公司",
           phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
         },
         {
           id: "3",
@@ -182,9 +188,21 @@ export default {
           pic: "",
           type: "施工人员",
           posi: "门卫",
-          personType: "工",
-          comp:'XXXXX公司',
+          personType: "工",
+          comp: "XXXXX公司",
           phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
+        },
+        {
+          id: "4",
+          name: "高某某",
+          pic: "",
+          type: "访客",
+          posi: "工程师",
+          personType: "访客",
+          comp: "XXXXX公司",
+          phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
         },
       ],
     };
@@ -195,6 +213,16 @@ export default {
     // this.startMqtt();
   },
   methods: {
+    openPersonInfo() {
+
+    },
+    openPersonList() {
+      this.$store.dispatch("globalConfig/setPersonListDialog", {
+        show: true,
+        dialogMsg: this.personList,
+        type: "All",
+      });
+    },
     async getPersonTypeList() {
       try {
         const p = {};

+ 11 - 11
src/views/basePage/panels/RiskStatistics/index.vue

@@ -26,20 +26,20 @@ export default {
   data() {
     return {
       searchType: "1",
-      // levelTrendData: {
-      //   name: ["11.30", "12.1", "12.2", "12.3", "12.4", "12.5", "12.6"],
-      //   legend: ["一级", "二级", "三级"],
-      //   data: [
-      //     ["1", "0", "1", "0", "1", "1", "0"],
-      //     ["1", "1", "0", "1", "1", "0", "1"],
-      //     ["3", "2", "2", "1", "1", "2", "1"],
-      //   ],
-      // },
       levelTrendData: {
-        name: [],
+        name: ["11.30", "12.1", "12.2", "12.3", "12.4", "12.5", "12.6"],
         legend: ["一级", "二级", "三级"],
-        data: [],
+        data: [
+          ["1", "0", "1", "0", "1", "1", "0"],
+          ["1", "1", "0", "1", "1", "0", "1"],
+          ["3", "2", "2", "1", "1", "2", "1"],
+        ],
       },
+      // levelTrendData: {
+      //   name: [],
+      //   legend: ["一级", "二级", "三级"],
+      //   data: [],
+      // },
     };
   },
 

+ 22 - 31
src/views/components/baseHeader/left.vue

@@ -70,18 +70,21 @@
             <el-dropdown-item disabled>
               <!-- <div>{{ username }}</div> -->
             </el-dropdown-item>
-            <el-dropdown-item @click.native="goToLogout">
-              <span style="display: block">退出登录</span>
+            <el-dropdown-item @click.native="test2">
+              <span style="display: block">110一键报警</span>
+            </el-dropdown-item>
+            <el-dropdown-item @click.native="test3">
+              <span style="display: block">防爆扩音</span>
             </el-dropdown-item>
             <!-- <el-dropdown-item @click.native="test">
-              <span style="display: block">报警声音弹窗测试</span>
+              <span style="display: block">报警声音弹窗</span>
             </el-dropdown-item>
             <el-dropdown-item @click.native="test1">
-              <span style="display: block">动画开关测试</span>
-            </el-dropdown-item>
-            <el-dropdown-item @click.native="test2">
-              <span style="display: block">报警详情弹窗测试</span>
+              <span style="display: block">入场动画开关</span>
             </el-dropdown-item> -->
+            <el-dropdown-item @click.native="goToLogout">
+              <span style="display: block">退出登录</span>
+            </el-dropdown-item>
           </el-dropdown-menu>
         </el-dropdown>
       </div>
@@ -214,33 +217,13 @@ export default {
       const diff = now.diff(startTime, "day");
       return startDay + diff;
     },
-    // backButtonShow() {
-    //   // 解析根路由
-    //   const rootRouter = this.$router.resolve({ path: "/" });
-    //   // 获取根路径
-    //   const rootPath = rootRouter.route.fullPath;
-    //   // 获取当前路由的路径和查询参数
-    //   const { path, query } = this.$route;
-    //   // 从查询参数中获取departmentId
-    //   const { departmentId: routeDepartmentId } = query;
-
-    //   // 判断当前路径是否为根路径
-    //   if (path === rootPath) {
-    //     // 从localStorage中获取departmentId
-    //     const localDepartmentId = localStorage.getItem("departmentId");
-    //     // 返回条件:没有routeDepartmentId或者routeDepartmentId等于localDepartmentId
-    //     return !routeDepartmentId || routeDepartmentId === localDepartmentId;
-    //   }
-    //   // 如果不是根路径,返回false
-    //   return false;
-    // },
   },
   watch: {
     alarmDataCount: {
       handler(newVal) {
         this.alarmCount = newVal;
       },
-      deep: true,
+      deep: true, 
     },
     mapMode: {
       handler(val, oldVal) {
@@ -280,12 +263,20 @@ export default {
   },
   methods: {
     setShouldAnimation,
+    test3() {
+      console.log("防爆扩音");
+      this.$store.dispatch("globalConfig/setSoundDialog", {
+        show: true,
+        dialogMsg: {},
+        type: "All",
+      });
+    },
     test2() {
-      console.log("效果测试");
-      this.$store.dispatch("dialog/openAlarmDetailDialog", {
+      console.log("一键报警");
+      this.$store.dispatch("globalConfig/setOneKey110", {
         show: true,
         dialogMsg: {},
-        type: "handle",
+        type: "All",
       });
     },
     test1() {

+ 182 - 0
src/views/components/dialog/Onekey110Dialog.vue

@@ -0,0 +1,182 @@
+<template>
+  <base-drag-bg-dialog
+    :dialogConfig="baseDialogConfig"
+    @handleClose="closeDialog"
+    @onActivated="onActivated"
+  >
+    <!-- 弹窗内容 -->
+    <div class="dialog_box">
+      <!-- 内容 -->
+      <div class="dialog_content_box">
+        <div class="detail-box">
+          <el-row>
+            <el-col :span="24">
+              <span class="detail-label">设备名称:{{ deviceInfo.name }}</span>
+            </el-col>
+            <el-col :span="24">
+              <span class="detail-label"
+                >所在位置:{{ deviceInfo.position }}</span
+              >
+            </el-col>
+          </el-row>
+          <div class="btn-box" v-show="oneKey110.type === 'All'">
+            <el-button class="btn-cancel" size="medium" @click="closeDialog"
+              >关闭</el-button
+            >
+            <el-button
+              class="btn-handle"
+              type="danger"
+              size="medium"
+              @click="open"
+              >110一键报警</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+  </base-drag-bg-dialog>
+</template>
+<script>
+import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
+import { dealAlarm } from "@/API/common";
+import { mapGetters } from "vuex";
+export default {
+  name: "oneKey110Dialog",
+  components: { BaseDragBgDialog },
+  watch: {
+    "oneKey110.show": {
+      handler(newVal) {
+        this.baseDialogConfig.show = newVal;
+      },
+      // deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      BASE_URL,
+      baseDialogConfig: {
+        dialogId: "oneKey110",
+        show: false,
+        title: "一键报警页面",
+        width: 420,
+        height: 240,
+        center: true,
+        zIndex: 10,
+      },
+      deviceInfo: {
+        name: "门卫室110一键报警设备",
+        position: "门卫室",
+      },
+    };
+  },
+  computed: {
+    ...mapGetters(["oneKey110"]),
+  },
+  mounted() {},
+  methods: {
+    closeDialog() {
+      this.$store.dispatch("globalConfig/setOneKey110", {
+        show: false,
+        dialogMsg: {},
+        type: "All",
+      });
+    },
+    async handleDeal() {
+      try {
+        await dealAlarm({
+          id: this.oneKey110.dialogMsg.id,
+          dealContent: this.oneKey110.dialogMsg.dealContent,
+        });
+        this.closeDialog();
+        // 刷新报警列表页
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    open() {
+      this.$confirm(
+        this.deviceInfo.name + "即将启动 110报警 ,是否继续?",
+        "提示",
+        {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+          center: true,
+        }
+      )
+        .then(() => {
+          // this.handleDeal()
+          this.$message({
+            type: "success",
+            message: "启动110报警!",
+          });
+        })
+        .catch(() => {
+          this.$message({
+            type: "info",
+            message: "报警取消",
+          });
+        });
+    },
+    onActivated() {
+      // console.log("aaa");
+      this.$nextTick(() => {
+        this.$refs.dealContent.focus();
+      });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.dialog_box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  position: absolute;
+  z-index: 0;
+  .dialog_content_box {
+    padding: 0.104167rem /* 20/192 */;
+    color: #fff;
+    font-size: large;
+    .detail-box {
+      .el-row {
+        .detail-label {
+          vertical-align: top;
+          display: inline-block;
+          text-align: right;
+          padding-right: 0.052083rem /* 10/192 */;
+          padding-bottom: 0.052083rem /* 10/192 */;
+        }
+      }
+      .btn-box {
+        width: 100%;
+        text-align: center;
+        position: absolute;
+        bottom: 70px /* 30/192 */;
+        left: 50%;
+        transform: translate(-55%, 0);
+        .el-button {
+          width: 0.6125rem /* 78/192 */;
+          height: 0.291666rem /* 28/192 */;
+          box-sizing: border-box;
+          margin-top: 0.015625rem /* 3/192 */;
+          color: #fff;
+          padding: 0;
+          border-color: #fff9de;
+          border-radius: 10;
+          &:hover {
+            border-color: #ccc;
+          }
+        }
+        .btn-handle.el-button {
+          background: rgba(194, 18, 18, 0.6);
+        }
+        .btn-cancel.el-button {
+          background: rgba(13, 35, 64, 0.1);
+        }
+      }
+    }
+  }
+}
+</style>

+ 221 - 0
src/views/components/dialog/PersonListDialog.vue

@@ -0,0 +1,221 @@
+<template>
+  <base-drag-bg-dialog
+    :dialogConfig="baseDialogConfig"
+    @handleClose="closeDialog"
+    @onActivated="onActivated"
+  >
+    <!-- 弹窗内容 -->
+    <div class="dialog_box">
+      <!-- 内容 -->
+      <div class="dialog_content_box">
+        <div class="person-box">
+          <el-row v-if="personList.length">
+            <el-col :span="4">
+              <div class="person-type-title">本作业区员工</div>
+              <div class="person-type-value">{{ personList.length }}人</div>
+            </el-col>
+            <el-col :span="20">
+              <div class="person-info">
+                <span v-for="(item, index) in personList" :key="index">
+                  <div class="person-info-pic">
+                    <img
+                      src="~@/assets/imgs/stationMap/img_无照片.png"
+                      alt=""
+                    />
+                  </div>
+                  <div class="person-info-name">{{ item.name }}</div>
+                </span>
+              </div>
+            </el-col>
+          </el-row>
+          <el-row v-if="workerList.length">
+            <el-col :span="4">
+              <div class="person-type-title">外来施工员工</div>
+              <div class="person-type-value">{{ workerList.length }}人</div>
+            </el-col>
+            <el-col :span="20">
+              <div class="person-info">
+                <span v-for="(item, index) in workerList" :key="index">
+                  <div class="person-info-pic">
+                    <img
+                      src="~@/assets/imgs/stationMap/img_无照片.png"
+                      alt=""
+                    />
+                  </div>
+                  <div class="person-info-name">{{ item.name }}</div>
+                </span>
+              </div>
+            </el-col>
+          </el-row>
+          <el-row v-if="registerList.length">
+            <el-col :span="4">
+              <div class="person-type-title">外来访客人员</div>
+              <div class="person-type-value">{{ registerList.length }}人</div>
+            </el-col>
+            <el-col :span="20">
+              <div class="person-info">
+                <span v-for="(item, index) in registerList" :key="index">
+                  <div class="person-info-pic">
+                    <img
+                      src="~@/assets/imgs/stationMap/img_无照片.png"
+                      alt=""
+                    />
+                  </div>
+                  <div class="person-info-name">{{ item.name }}</div>
+                </span>
+              </div>
+            </el-col>
+          </el-row>
+        </div>
+      </div>
+    </div>
+  </base-drag-bg-dialog>
+</template>
+<script>
+import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
+import { mapGetters } from "vuex";
+export default {
+  name: "personListDialog",
+  components: { BaseDragBgDialog },
+  watch: {
+    "personListDialog.show": {
+      handler(newVal) {
+        this.baseDialogConfig.show = newVal;
+      },
+      // deep: true,
+      immediate: true,
+    },
+    "personListDialog.dialogMsg": {
+      handler(newVal) {
+        // console.log(newVal);
+        this.list = newVal;
+        this.personList = this.list.filter((e) => e.personType === "员工");
+        this.registerList = this.list.filter((e) => e.personType === "访客");
+        this.workerList = this.list.filter((e) => e.personType === "施工");
+      },
+      // deep: true,
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      BASE_URL,
+      list: [],
+      personList: [
+        {
+          id: "2",
+          name: "王某某",
+          pic: "",
+          type: "值班门卫",
+          posi: "运维操作工",
+          personType: "员工",
+          comp: "XXXXX公司",
+          phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
+        },
+      ],
+      registerList: [
+        {
+          id: "4",
+          name: "高某某",
+          pic: "",
+          type: "访客",
+          posi: "工程师",
+          personType: "访客",
+          comp: "XXXXX公司",
+          phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
+        },
+      ],
+      workerList: [
+        {
+          id: "3",
+          name: "李某某",
+          pic: "",
+          type: "施工人员",
+          posi: "门卫",
+          personType: "施工",
+          comp: "XXXXX公司",
+          phone: 15500001111,
+          imgUrl: "~@/assets/imgs/stationMap/img_无照片.png",
+        },
+      ],
+      baseDialogConfig: {
+        dialogId: "personListDialog",
+        show: false,
+        title: "站内人员统计",
+        width: 1000,
+        height: 670,
+        center: true,
+        zIndex: 10,
+      },
+    };
+  },
+  computed: {
+    ...mapGetters(["personListDialog"]),
+  },
+  mounted() {},
+  methods: {
+    closeDialog() {
+      this.$store.dispatch("globalConfig/setPersonListDialog", {
+        show: false,
+        dialogMsg: [],
+        type: "All",
+      });
+    },
+    onActivated() {
+      // console.log("aaa");
+      this.$nextTick(() => {
+        this.$refs.dealContent.focus();
+      });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.dialog_box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  position: absolute;
+  z-index: 0;
+  .dialog_content_box {
+    color: #fff;
+    font-size: large;
+    .person-box {
+      .el-row {
+        width: 96%;
+        padding-top: 8px;
+        border-bottom: 1.5px dotted #2d6fd3;
+        .person-type-title {
+          font-size: 20px;
+          vertical-align: top;
+          text-align: center;
+          margin-top: 0.308334rem /* 40/192 */;
+          margin-left: -0.104167rem /* 20/192 */;
+        }
+        .person-type-value {
+          font-size: 14px;
+          vertical-align: top;
+          text-align: center;
+          margin-left: -0.104167rem /* 20/192 */;
+        }
+        .person-info {
+          display: flex;
+          justify-content: flex-start;
+          .person-info-pic {
+            width: 100%;
+            text-align: left;
+            padding-right: 0.0260415rem /* 5/192 */;
+          }
+          .person-info-name {
+            vertical-align: top;
+            text-align: center;
+            padding-bottom: 0.0260415rem /* 5/192 */;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 223 - 0
src/views/components/dialog/SoundDialog.vue

@@ -0,0 +1,223 @@
+<template>
+  <base-drag-bg-dialog
+    :dialogConfig="baseDialogConfig"
+    @handleClose="closeDialog"
+    @onActivated="onActivated"
+  >
+    <!-- 弹窗内容 -->
+    <div class="dialog_box">
+      <!-- 内容 -->
+      <div class="detail-table-box">
+        <base-table-list
+          :tableConfig="tableConfig"
+          @handleClick="handleTableClick"
+        />
+      </div>
+    </div>
+  </base-drag-bg-dialog>
+</template>
+<script>
+import BaseTableList from "@/views/components/base/BaseTableList";
+import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
+import { dealAlarm } from "@/API/common";
+import { getElementList } from "@/API/visual";
+import { mapGetters } from "vuex";
+export default {
+  name: "soundDialog",
+  components: { BaseDragBgDialog, BaseTableList },
+  watch: {
+    "soundDialog.show": {
+      handler(newVal) {
+        this.baseDialogConfig.show = newVal;
+      },
+      // deep: true,
+      immediate: true,
+    },
+    dataList: {
+      handler(newValue, oldValue) {
+        this.filterKey = "";
+        this.tableConfig.tableData = newValue;
+      },
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      BASE_URL,
+      dataList: [
+        {
+          id: "",
+          name: "",
+        },
+      ],
+      baseDialogConfig: {
+        dialogId: "soundDialog",
+        show: false,
+        title: "防爆扩音",
+        width: 640,
+        height: 540,
+        center: true,
+        zIndex: 10,
+      },
+      tableConfig: {
+        needIndex: true,
+        height: 456,
+        header: [
+          { title: "名称", prop: "name", width: "" },
+          { title: "描述", prop: "desc", width: "" },
+          {
+            title: "操作",
+            prop: "operation",
+            width: "",
+            btns: [
+              { btnName: "打开", btnType: "open" },
+              { btnName: "关闭", btnType: "close" },
+            ],
+          },
+        ],
+        tableData: [],
+        rowClick: this.location,
+      },
+    };
+  },
+  created() {
+    this.initSoundList();
+  },
+  computed: {
+    ...mapGetters(["soundDialog"]),
+  },
+  mounted() {},
+  methods: {
+    async initSoundList() {
+      try {
+        const res = await getElementList({ id: "784748250065281024" });
+        this.dataList = res.data.content;
+        console.log("防爆扩音列表", this.dataList);
+        // content.forEach((d) => {
+        //   d.GPSPoints = this.transPosition(d.pointList);
+        // });
+        // elementData.push(...content)
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    closeDialog() {
+      this.$store.dispatch("globalConfig/setSoundDialog", {
+        show: false,
+        dialogMsg: {},
+        type: "All",
+      });
+    },
+    async handleDeal() {
+      try {
+        await dealAlarm({
+          id: this.soundDialog.dialogMsg.id,
+          dealContent: this.soundDialog.dialogMsg.dealContent,
+        });
+        this.closeDialog();
+        // 刷新报警列表页
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    handleTableClick(data, btnType) {
+      if (btnType === "open") {
+        console.log("打开扩音", data);
+      }
+      if (btnType === "close") {
+        console.log("关闭扩音", data);
+      }
+      // const tableData = this.$parent.$parent.alarmLiveData.filter((item) => {
+      //   return item.Category == "100001" && item.ObjectID == data.id;
+      // });
+      // this.$store.dispatch("dialog/openLayerDetailDialog", {
+      //   id: data.id,
+      //   type: "rail",
+      //   name: "围栏",
+      //   detail: {
+      //     id: data.id,
+      //     name: data.name,
+      //     tableData,
+      //   },
+      // });
+    },
+    onActivated() {
+      // console.log("aaa");
+      this.$nextTick(() => {
+        this.$refs.dealContent.focus();
+      });
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.dialog_box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  .dialog_content_box {
+    height: 2.083333rem /* 400/192 */;
+    padding: 0.104167rem /* 20/192 */ 0;
+    box-sizing: border-box;
+    color: #fff;
+    .detail-box {
+      .el-row {
+        margin-top: 0.052083rem /* 10/192 */;
+        line-height: 0.145833rem /* 28/192 */;
+        .detail-label {
+          vertical-align: top;
+          display: inline-block;
+          width: 0.520833rem /* 100/192 */;
+          text-align: right;
+          padding-right: 0.052083rem /* 10/192 */;
+        }
+        .el-input {
+          width: 1.302083rem /* 250/192 */;
+          height: 0.145833rem /* 28/192 */;
+        }
+        .el-textarea {
+          width: 3.385417rem /* 650/192 */;
+        }
+
+        .image-box {
+          display: inline-block;
+          max-width: 1.666667rem /* 320/192 */;
+          height: 0.9375rem /* 180/192 */;
+          .el-image {
+            height: 100%;
+          }
+        }
+      }
+      .btn-box {
+        width: 100%;
+        height: 0.15625rem /* 30/192 */;
+        text-align: center;
+        position: absolute;
+        bottom: 0.15625rem /* 30/192 */;
+        left: 50%;
+        transform: translate(-50%, 0);
+        .el-button {
+          width: 0.40625rem /* 78/192 */;
+          height: 0.145833rem /* 28/192 */;
+          box-sizing: border-box;
+          margin-top: 0.015625rem /* 3/192 */;
+          color: #fff;
+          padding: 0;
+          border-color: #fff9de;
+          border-radius: 0;
+          &:hover {
+            border-color: #ccc;
+          }
+        }
+        .btn-handle.el-button {
+          // background: url('../../../../assets/out/imgs/popup/button_bg.png') center no-repeat;
+          background: rgba(4, 42, 47, 0.6);
+        }
+        .btn-cancel.el-button {
+          background: rgba(13, 35, 64, 0.1);
+        }
+      }
+    }
+  }
+}
+</style>

+ 2 - 0
src/views/videoMonitor/index.vue

@@ -265,6 +265,8 @@ export default {
   padding: 110px 90px 0;
   // background: #001012;
   pointer-events: auto;
+  position: absolute;
+  z-index: 0;
   &.full {
     padding: 0;
     .videoMonitor-main {