3 Commits 3ccfb43084 ... d556d913f9

Author SHA1 Message Date
  fan d556d913f9 底部菜单增加弹窗脚本;增加门禁弹窗;增加激光云台弹窗;调整防爆扩音弹窗 3 months ago
  fan 8bfd9fb4be 驾驶舱监视页面,报警,风险统计,风险提示按不同场站监视数据切换;监视页面收起展开按钮与功能同步 3 months ago
  fan ac323e03d5 报警记录管理同页面传参刷新;视频监视同页面传参刷新;模型加载延迟时间调整;今日报警,风险分级,风险统计数据初始化;调度系统API与request.js初始化与请求参数测试 4 months ago
51 changed files with 4416 additions and 460 deletions
  1. 21 2
      package-lock.json
  2. 1 0
      package.json
  3. 185 39
      public/js/config.js
  4. 1 1
      public/js/mapModeConfig.js
  5. 17 0
      src/API/JGYT.js
  6. 26 0
      src/API/accessControl.js
  7. 11 0
      src/API/ddxt.js
  8. BIN
      src/assets/imgs/fold/button_收起面板_pre.png
  9. BIN
      src/assets/imgs/fold/button_收起面板_sel.png
  10. 1 1
      src/components/BaseMap/index.vue
  11. 0 0
      src/plugins/tr-webrtc.min.js
  12. 7 1
      src/router/index.js
  13. 3 0
      src/store/getters.js
  14. 14 0
      src/store/modules/globalConfig.js
  15. 18 0
      src/store/modules/model.js
  16. 2 2
      src/utils/index.js
  17. 8 6
      src/utils/mapUtil.js
  18. 6 5
      src/utils/request.js
  19. 63 0
      src/utils/requestDDXT.js
  20. 2 0
      src/utils/webRTU.js
  21. 8 0
      src/views/Home.vue
  22. 357 183
      src/views/alarm/alarmList/index.vue
  23. 2 2
      src/views/basePage/components/layerControl/index.vue
  24. 16 0
      src/views/basePage/index.vue
  25. 3 3
      src/views/basePage/mixins/LoadBuilding/LoadBuilding.js
  26. 1 1
      src/views/basePage/mixins/LoadBuilding/LoadLayer.js
  27. 19 15
      src/views/basePage/mixins/LoadLayer/JGYT.js
  28. 1 1
      src/views/basePage/mixins/LoadLayer/perimeter.js
  29. 1 1
      src/views/basePage/mixins/MapEvent.js
  30. 119 0
      src/views/basePage/panels/Fold.vue
  31. 113 76
      src/views/basePage/panels/IntelligentVideo/index.vue
  32. 52 0
      src/views/basePage/panels/Overview.vue
  33. 56 2
      src/views/basePage/panels/RiskHint.vue
  34. 13 13
      src/views/basePage/panels/RiskStatistics/index.vue
  35. 83 26
      src/views/components/baseFooter/FooterNavigation.vue
  36. 38 6
      src/views/components/baseHeader/left.vue
  37. 523 0
      src/views/components/dialog/AccessControlDialog.vue
  38. 289 0
      src/views/components/dialog/JGYTControlDialog/VideoControl.vue
  39. 453 0
      src/views/components/dialog/JGYTControlDialog/index.vue
  40. 241 68
      src/views/components/dialog/SoundDialog.vue
  41. 1 1
      src/views/components/dialog/VideoImageWindow.vue
  42. 2 0
      src/views/page1/index.vue
  43. 1 1
      src/views/stationMapTKT/components/BaseImgMap/StationPoint.vue
  44. 242 0
      src/views/videoMonitorType/components/StationSelect.vue
  45. 238 0
      src/views/videoMonitorType/components/VideoConfig.vue
  46. 201 0
      src/views/videoMonitorType/components/VideoControl.vue
  47. 284 0
      src/views/videoMonitorType/components/VideoForensics.vue
  48. 151 0
      src/views/videoMonitorType/components/VideoWindow.vue
  49. 166 0
      src/views/videoMonitorType/components/videoContent.vue
  50. 346 0
      src/views/videoMonitorType/index.vue
  51. 10 4
      vue.config.js

+ 21 - 2
package-lock.json

@@ -3400,6 +3400,11 @@
       "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=",
       "integrity": "sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=",
       "dev": true
       "dev": true
     },
     },
+    "charenc": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmmirror.com/charenc/-/charenc-0.0.2.tgz",
+      "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="
+    },
     "check-types": {
     "check-types": {
       "version": "8.0.3",
       "version": "8.0.3",
       "resolved": "https://registry.nlark.com/check-types/download/check-types-8.0.3.tgz",
       "resolved": "https://registry.nlark.com/check-types/download/check-types-8.0.3.tgz",
@@ -4237,6 +4242,11 @@
         }
         }
       }
       }
     },
     },
+    "crypt": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmmirror.com/crypt/-/crypt-0.0.2.tgz",
+      "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="
+    },
     "crypto-browserify": {
     "crypto-browserify": {
       "version": "3.12.0",
       "version": "3.12.0",
       "resolved": "https://registry.nlark.com/crypto-browserify/download/crypto-browserify-3.12.0.tgz",
       "resolved": "https://registry.nlark.com/crypto-browserify/download/crypto-browserify-3.12.0.tgz",
@@ -7132,8 +7142,7 @@
     "is-buffer": {
     "is-buffer": {
       "version": "1.1.6",
       "version": "1.1.6",
       "resolved": "https://registry.nlark.com/is-buffer/download/is-buffer-1.1.6.tgz",
       "resolved": "https://registry.nlark.com/is-buffer/download/is-buffer-1.1.6.tgz",
-      "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
-      "dev": true
+      "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4="
     },
     },
     "is-callable": {
     "is-callable": {
       "version": "1.2.4",
       "version": "1.2.4",
@@ -7933,6 +7942,16 @@
         "zousan": "^2.3.3"
         "zousan": "^2.3.3"
       }
       }
     },
     },
+    "md5": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz",
+      "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+      "requires": {
+        "charenc": "0.0.2",
+        "crypt": "0.0.2",
+        "is-buffer": "~1.1.6"
+      }
+    },
     "md5.js": {
     "md5.js": {
       "version": "1.3.5",
       "version": "1.3.5",
       "resolved": "https://registry.npmmirror.com/md5.js/download/md5.js-1.3.5.tgz",
       "resolved": "https://registry.npmmirror.com/md5.js/download/md5.js-1.3.5.tgz",

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "linq": "^4.0.0",
     "linq": "^4.0.0",
     "lodash-es": "^4.17.21",
     "lodash-es": "^4.17.21",
     "maptalks": "^0.49.5",
     "maptalks": "^0.49.5",
+    "md5": "^2.3.0",
     "mqtt": "^4.3.5",
     "mqtt": "^4.3.5",
     "vue": "^2.6.11",
     "vue": "^2.6.11",
     "vue-drag-resize": "^1.5.4",
     "vue-drag-resize": "^1.5.4",

+ 185 - 39
public/js/config.js

@@ -9,7 +9,7 @@ const BASE_URL = '/yapi' //开发接口代理
  */
  */
 const HOME_DATA = {
 const HOME_DATA = {
   startDate: '2024-11-27',
   startDate: '2024-11-27',
-  curStation: '托克托',
+  curStation: '都匀',
 }
 }
 
 
 /**
 /**
@@ -17,7 +17,7 @@ const HOME_DATA = {
  */
  */
 const STATION_LIST = [
 const STATION_LIST = [
   {
   {
-    name: '托克托',
+    name: '都匀',
     configUrl: '/json/glyConfig.json',
     configUrl: '/json/glyConfig.json',
     cameraUrl: '/json/glyCamera.json',
     cameraUrl: '/json/glyCamera.json',
   },
   },
@@ -28,7 +28,7 @@ const STATION_LIST = [
 /**
 /**
  * 页面内标题 已生效
  * 页面内标题 已生效
  */
  */
-const SYSTEM_TITLE = '托克托压气站综合安防平台'//托克托
+const SYSTEM_TITLE = '都匀作业区智慧融合平台'
 /**
 /**
  * 设置浏览器标题 已生效
  * 设置浏览器标题 已生效
  */
  */
@@ -72,9 +72,8 @@ const MODULE_ENABLED = {
  * key3:f3ddf0996b8f5b1c876094cdcb35faab  自己的
  * key3:f3ddf0996b8f5b1c876094cdcb35faab  自己的
  */
  */
 const MAP_CONFIG = {
 const MAP_CONFIG = {
-  // url: 'http://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles&tk=c7074dacd421b3e1ba311392c4b6923f',
-  // url: 'http://127.0.0.1:9950/YG/tkt/{z}/{x}/{y}.png',
-  url: 'static/tkt/{z}/{x}/{y}.png',
+  url: 'http://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles&tk=c7074dacd421b3e1ba311392c4b6923f',
+  // url: 'static/tkt/{z}/{x}/{y}.png',
   maximumLevel: 18,
   maximumLevel: 18,
   subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
   subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
 }
 }
@@ -139,16 +138,20 @@ const MQTT_CONFIG = {
     'Risk/New',
     'Risk/New',
     'dashboard/risk/drawrisktime',
     'dashboard/risk/drawrisktime',
     'Visualization/DataComm/NewAlarm',
     'Visualization/DataComm/NewAlarm',
+    'Visualization/Number/RecentlyLevelByDate'
   ],
   ],
 }
 }
 //后台管理根路径
 //后台管理根路径
 const ISMSAdminWeb = {
 const ISMSAdminWeb = {
-  path: "http://172.168.0.62:8080/#/",
-  // path: `http://192.168.195.136:8080/#/`,
+  // path: "http://localhost:9528/#/",
+  // path: "http://11.100.46.218:8080/#/",
+  path: `http://192.168.195.134:8080/#/`,
   // path: `http://${window.location.hostname}:8080/#/`,
   // path: `http://${window.location.hostname}:8080/#/`,
 }
 }
 
 
-//房顶配置
+//都匀调度系统access_key配置
+ACCESS_KEY = ''
+SECRET_KEY = ''
 //房顶配置
 //房顶配置
 const MODEL_ROOF_LIST = [{ model: 'JHFSZ', part: ['门卫室-顶', '办公区屋顶'] }]
 const MODEL_ROOF_LIST = [{ model: 'JHFSZ', part: ['门卫室-顶', '办公区屋顶'] }]
 
 
@@ -591,35 +594,117 @@ const LAYER_CONFIG = {
 }
 }
 
 
 const GY_STATIONS = [
 const GY_STATIONS = [
+  // {
+  //   id: '591282080239853568',
+  //   name: '贵阳输气站',
+  //   code: 'GYSQZ',
+  //   direction: 'left',
+  //   buildId: '594099860043472896',
+  //   positioningBuildId: '001001',
+  //   position: [106.62629510834513, 26.65059748734631, 1.4679041606626673],
+  //   layers: ['周界', '泄漏', '摄像头'],
+  // },
+  // {
+  //   id: '655065301053874176',
+  //   name: '白云输气站',
+  //   code: 'BYSQZ',
+  //   direction: 'right',
+  //   buildId: '639402700261302272', //用于跳转模型
+  //   positioningBuildId: '001002', //用于跳转模型判断
+  //   position: [106.62629633504537, 26.65060908351062, 1.4819172693521345],
+  //   layers: ['风险区域', '周界', '泄漏', '摄像头'],
+  // },
   {
   {
-    id: '784104499768729600',
-    name: '托克托',
-    code: 'TKT',
-    buildId: '784102618438836224',
-    positioningBuildId: '100001',
+    id: '657316479015854080',
+    name: '都匀输气站',
+    code: 'DYSQZ',
+    buildId: '657317980832538624',
+    positioningBuildId: '002001',
     direction: 'right',
     direction: 'right',
-    position: [106.6263209022603, 26.650585399041464, 1.4657059185197159],
+    position: [106.62632139900707, 26.650595691076745, 1.4650695463064403],
+    layers: ['周界', '泄漏', '摄像头'],
+  },
+  {
+    id: '657316634284793856',
+    name: '云雾首站',
+    code: 'YWSZ',
+    buildId: '657319107443564544',
+    positioningBuildId: '002004',
+    direction: 'left',
+    position: [106.62630660166043, 26.650596074566966, 1.4660467809229363],
     layers: ['周界', '泄漏', '摄像头'],
     layers: ['周界', '泄漏', '摄像头'],
   },
   },
   {
   {
-    id: '784131093203787776',
-    name: '托克托压气站',
-    code: 'TKT',
-    buildId: '784102618438836224',
-    positioningBuildId: '100001',
+    id: '657316533462114304',
+    name: '凯口清管站',
+    code: 'KKQGZ',
+    buildId: '657318695416111104',
+    positioningBuildId: '002002',
+    direction: 'right',
+    position: [106.62631864686837, 26.650589347228493, 1.4654720522226603],
+    layers: ['周界', '泄漏', '摄像头'],
+  },
+  {
+    id: '657316587124039680',
+    name: '独山首站',
+    code: 'DSSZ',
+    buildId: '657318879332147200',
+    positioningBuildId: '002003',
     direction: 'right',
     direction: 'right',
     position: [106.6263209022603, 26.650585399041464, 1.4657059185197159],
     position: [106.6263209022603, 26.650585399041464, 1.4657059185197159],
     layers: ['周界', '泄漏', '摄像头'],
     layers: ['周界', '泄漏', '摄像头'],
   },
   },
+  {
+    id: '',
+    name: '荔波首站',
+    code: 'LBSZ',
+    buildId: '',
+    positioningBuildId: '',
+    direction: 'right',
+    position: [106.6263329708765, 26.65057999393088, 1.4648986180330343],
+    layers: ['周界', '泄漏', '摄像头'],
+  },
+  // {
+  //   id: '784104499768729600',
+  //   name: '托克托',
+  //   code: 'TKT',
+  //   buildId: '784102618438836224',
+  //   positioningBuildId: '100001',
+  //   direction: 'right',
+  //   position: [106.6263209022603, 26.650585399041464, 1.4657059185197159],
+  //   layers: ['周界', '泄漏', '摄像头'],
+  // },
+  // {
+  //   id: '784131093203787776',
+  //   name: '托克托压气站',
+  //   code: 'TKT',
+  //   buildId: '784102618438836224',
+  //   positioningBuildId: '100001',
+  //   direction: 'right',
+  //   position: [106.6263209022603, 26.650585399041464, 1.4657059185197159],
+  //   layers: ['周界', '泄漏', '摄像头'],
+  // },
 ]
 ]
 
 
 const GY_ZYQS = [
 const GY_ZYQS = [
+  // {
+  //   id: '784131018197049344',
+  //   name: '托克托作业区',
+  //   code: 'TKTZYQ',
+  //   buildId: '654044537953460225',
+  // },
   {
   {
-    id: '784131018197049344',
-    name: '托克托作业区',
-    code: 'TKTZYQ',
+    id: '657316430240292865',
+    name: '都匀作业区',
+    code: 'DYSQZ',
     buildId: '654044537953460225',
     buildId: '654044537953460225',
   },
   },
+  // {
+  //   id: '591281556996235264',
+  //   name: '贵阳作业区',
+  //   code: 'GYSQZ',
+  //   buildId: '654044537953460224',
+  // },
 ]
 ]
 
 
 /**
 /**
@@ -627,35 +712,96 @@ const GY_ZYQS = [
  * 已启用
  * 已启用
  * 后续改成接口获取
  * 后续改成接口获取
  */
  */
+// const GY_JGYT_CONFIG = [
+// {
+//   id: '1',
+//   name: '托克托作业区',
+//   children: [
+//     {
+//       id: '101',
+//       name: '托克托压气站',
+//       children: [
+//         {
+//           id: '1',
+//           // id: '660856349529219072',
+//           name: '云台1',
+//           ndTag: 'DY_Leak_PTZ_Concn',
+//         },
+//       ],
+//     },]
+// }]
+
 const GY_JGYT_CONFIG = [
 const GY_JGYT_CONFIG = [
   {
   {
     id: '1',
     id: '1',
-    name: '托克托作业区',
+    name: '都匀作业区',
     children: [
     children: [
       {
       {
         id: '101',
         id: '101',
-        name: '托克托压气站',
+        name: '都匀站',
+        departmentId: '657316479015854080',
+        buildId: '657317980832538624',
         children: [
         children: [
           {
           {
-            id: '786542179467141120',
-            name: '激光检测1',
-            ndTag: 'JGYT1_ND',
+            id: '1',
+            // id: '660856349529219072',
+            name: '云台1',
+            ndTag: 'DY_Leak_PTZ_Concn',
           },
           },
+        ],
+      },
+      {
+        id: '102',
+        name: '独山首站',
+        departmentId: '657316587124039680',
+        buildId: '657318879332147200',
+        children: [
           {
           {
-            id: '786542180738015232',
-            name: '激光检测2',
-            ndTag: 'JGYT2_ND',
+            id: '2',
+            // id: '660856349529219074',
+            name: '云台1',
+            ndTag: 'DS_JGYT_01_DATA_ND',
+          },
+          {
+            id: '3',
+            // id: '660856349529219076',
+            name: '云台2',
+            ndTag: 'DS_JGYT_02_DATA_ND',
+          },
+        ],
+      },
+      {
+        id: '103',
+        name: '凯口站',
+        departmentId: '657316533462114304',
+        buildId: '657318695416111104',
+        children: [
+          {
+            id: '4',
+            // id: '660856349529219073',
+            name: '云台1',
+            ndTag: 'KK_Leak_PTZ_Concn',
+          },
+        ],
+      },
+      {
+        id: '104',
+        name: '云雾首站',
+        departmentId: '657316634284793856',
+        buildId: '657319107443564544',
+        children: [
+          {
+            id: '5',
+            // id: '660856349529219075',
+            name: '云台1',
+            ndTag: 'YW_Leak_PTZ_Concn',
           },
           },
         ],
         ],
-      },]
-  }]
+      },
+    ],
+  },
+]
 
 
-const TKT_PERSON_NUMS = {
-  total: 4,
-  person: 4,
-  register: 4,
-  Worker: 4,
-}
 /**
 /**
  * mqtt地址
  * mqtt地址
  * 判断是否被iframe嵌套
  * 判断是否被iframe嵌套

+ 1 - 1
public/js/mapModeConfig.js

@@ -1,5 +1,5 @@
 const MAP_MODE_LIST = {
 const MAP_MODE_LIST = {
-  home: {
+  "home": {
     perspective: {
     perspective: {
       destination: {
       destination: {
         x: -1860663.5421133842,
         x: -1860663.5421133842,

+ 17 - 0
src/API/JGYT.js

@@ -20,3 +20,20 @@ export const getAlarmList = data =>
     data,
     data,
     notShowLoading: true,
     notShowLoading: true,
   })
   })
+
+// 获取激光云台设备列表
+export const getJGYTList = data =>
+  $http({
+    method: 'POST',
+    url: `/Leak/LaserPtz/Config/GetList`,
+    data,
+    notShowLoading: true,
+  })
+// 获取激光云台报警数据列表
+export const getJGYTAlarmList = data =>
+  $http({
+    method: 'POST',
+    url: `/Leak/LaserPtz/Alarm/GetList`,
+    data,
+    notShowLoading: true,
+  })

+ 26 - 0
src/API/accessControl.js

@@ -0,0 +1,26 @@
+import $http from '@/utils/request'
+
+// 获取门禁信息
+export const getAccessInfo = data =>
+  $http({
+    method: 'POST',
+    url: '/AccessControl/Config/GetEntity',
+    data,
+    notShowLoading: true,
+  })
+// 获取门禁列表信息
+export const getAccessInfoList = data =>
+  $http({
+    method: 'POST',
+    url: '/AccessControl/Config/GetList',
+    data,
+    notShowLoading: true,
+  })
+// 获取门禁列表信息
+export const getAccessLogList = data =>
+  $http({
+    method: 'POST',
+    url: '/AccessControl/Log/GetList',
+    data,
+    notShowLoading: true,
+  })

+ 11 - 0
src/API/ddxt.js

@@ -0,0 +1,11 @@
+import request from '@/utils/requestDDXT'
+
+// 开始广播
+export function getTestList(data) {
+  return request({
+    url: 'ddxt-api/broadcast/task/play',
+    method: 'post',
+    data,
+    notShowLoading: true,
+  })
+}

BIN
src/assets/imgs/fold/button_收起面板_pre.png


BIN
src/assets/imgs/fold/button_收起面板_sel.png


+ 1 - 1
src/components/BaseMap/index.vue

@@ -119,7 +119,7 @@ export default {
         // });
         // });
         updateViewer(viewer);
         updateViewer(viewer);
         setTimeout(() => {
         setTimeout(() => {
-          this.addBaseImagery();
+          // this.addBaseImagery();//都匀不加载//托克托加载
           //this.addLabelImagery();
           //this.addLabelImagery();
         }, 10);
         }, 10);
         //初始飞行定位
         //初始飞行定位

File diff suppressed because it is too large
+ 0 - 0
src/plugins/tr-webrtc.min.js


+ 7 - 1
src/router/index.js

@@ -11,7 +11,8 @@ const routes = [
   },
   },
   {
   {
     path: '/',
     path: '/',
-    redirect: '/stationMapTKT',
+    // redirect: '/stationMapTKT',//托克托
+    redirect: '/basePage',//都匀
   },
   },
   {
   {
     path: '/stationMap',
     path: '/stationMap',
@@ -33,6 +34,11 @@ const routes = [
     name: 'videoMonitor',
     name: 'videoMonitor',
     component: () => import('@/views/videoMonitor/index.vue'),
     component: () => import('@/views/videoMonitor/index.vue'),
   },
   },
+  {
+    path: '/videoMonitorType',
+    name: 'videoMonitorType',
+    component: () => import('@/views/videoMonitorType/index.vue'),
+  },
   {
   {
     path: '/page1',
     path: '/page1',
     name: 'page1',
     name: 'page1',

+ 3 - 0
src/store/getters.js

@@ -11,6 +11,8 @@ const getters = {
   alarmAudio: (state) => state.globalConfig.alarmAudio,//全局报警声音
   alarmAudio: (state) => state.globalConfig.alarmAudio,//全局报警声音
   oneKey110: (state) => state.globalConfig.oneKey110,//一键110
   oneKey110: (state) => state.globalConfig.oneKey110,//一键110
   soundDialog: (state) => state.globalConfig.soundDialog,//防爆扩音
   soundDialog: (state) => state.globalConfig.soundDialog,//防爆扩音
+  accessControlDialog: (state) => state.globalConfig.accessControlDialog,//门禁控制
+  jgytControlDialog: (state) => state.globalConfig.jgytControlDialog,//激光云台
   personListDialog: (state) => state.globalConfig.personListDialog,//站内人员统计
   personListDialog: (state) => state.globalConfig.personListDialog,//站内人员统计
   rtTag: (state) => state.globalConfig.RTTag,
   rtTag: (state) => state.globalConfig.RTTag,
   rtData: (state) => state.globalConfig.RTData,
   rtData: (state) => state.globalConfig.RTData,
@@ -30,6 +32,7 @@ const getters = {
   layerDetailDialog: (state) => state.dialog.layerDetailDialog,
   layerDetailDialog: (state) => state.dialog.layerDetailDialog,
 
 
   //模型部分
   //模型部分
+  departmentId: (state) => state.model.departmentId,
   buildId: (state) => state.model.buildId,
   buildId: (state) => state.model.buildId,
   buildInfo: (state) => state.model.buildInfo,
   buildInfo: (state) => state.model.buildInfo,
   modelList: (state) => state.model.modelList,
   modelList: (state) => state.model.modelList,

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

@@ -9,6 +9,8 @@ const state = {
   alarmAudio: { show: false, alarmType: "all" },
   alarmAudio: { show: false, alarmType: "all" },
   oneKey110: { show: false, dialogMsg: {}, type: "all" },
   oneKey110: { show: false, dialogMsg: {}, type: "all" },
   soundDialog: { show: false, dialogMsg: {}, type: "all" },
   soundDialog: { show: false, dialogMsg: {}, type: "all" },
+  accessControlDialog: { show: false, dialogMsg: {}, type: "all" },
+  jgytControlDialog: { show: false, dialogMsg: {}, type: "all" },
   personListDialog: { show: false, dialogMsg: [], type: "all" },
   personListDialog: { show: false, dialogMsg: [], type: "all" },
   RTTag: {
   RTTag: {
     //"layer_id":["tag1","tag2"]
     //"layer_id":["tag1","tag2"]
@@ -49,6 +51,12 @@ const mutations = {
   SET_SOUNDDIALOG(state, data) {
   SET_SOUNDDIALOG(state, data) {
     state.soundDialog = data;
     state.soundDialog = data;
   },
   },
+  SET_ACCESSCONTROLDIALOG(state, data) {
+    state.accessControlDialog = data;
+  },
+  SET_JGYTCONTROLDIALOG(state, data) {
+    state.jgytControlDialog = data;
+  },
   SET_PERSONLISTDIALOG(state, data) {
   SET_PERSONLISTDIALOG(state, data) {
     state.personListDialog = data;
     state.personListDialog = data;
   },
   },
@@ -158,6 +166,12 @@ const actions = {
   setSoundDialog({ commit }, data) {
   setSoundDialog({ commit }, data) {
     commit("SET_SOUNDDIALOG", data);
     commit("SET_SOUNDDIALOG", data);
   },
   },
+  setAccessControlDialog({ commit }, data) {
+    commit("SET_ACCESSCONTROLDIALOG", data);
+  },
+  setJGYTControlDialog({ commit }, data) {
+    commit("SET_JGYTCONTROLDIALOG", data);
+  },
   setPersonListDialog({ commit }, data) {
   setPersonListDialog({ commit }, data) {
     commit("SET_PERSONLISTDIALOG", data);
     commit("SET_PERSONLISTDIALOG", data);
   },
   },

+ 18 - 0
src/store/modules/model.js

@@ -2,6 +2,7 @@ import { getBuildEntity } from '@/API/model'
 import { cloneDeep } from 'lodash-es'
 import { cloneDeep } from 'lodash-es'
 const state = {
 const state = {
   //当前场景对应的建筑id
   //当前场景对应的建筑id
+  departmentId: '',
   buildId: '',
   buildId: '',
   buildInfo: {},
   buildInfo: {},
   // 建筑id对应的模型列表,对应数据库
   // 建筑id对应的模型列表,对应数据库
@@ -11,6 +12,10 @@ const state = {
   underGround: false,
   underGround: false,
 }
 }
 const mutations = {
 const mutations = {
+  SET_DEPARTMENTID(state, data) {
+    state.departmentId = data
+    // console.log(data);
+  },
   SET_BUILDID(state, data) {
   SET_BUILDID(state, data) {
     state.buildId = data
     state.buildId = data
     // console.log(data);
     // console.log(data);
@@ -37,6 +42,9 @@ const mutations = {
   },
   },
 }
 }
 const actions = {
 const actions = {
+  setDepartmentId({ commit }, data) {
+    commit('SET_DEPARTMENTID', data)
+  },
   setBuildId({ commit }, data) {
   setBuildId({ commit }, data) {
     commit('SET_BUILDID', data)
     commit('SET_BUILDID', data)
   },
   },
@@ -59,6 +67,16 @@ const actions = {
           const resData = res.data || {}
           const resData = res.data || {}
           commit('SET_BUILD_INFO', resData)
           commit('SET_BUILD_INFO', resData)
           commit('SET_BUILDID', buildId)
           commit('SET_BUILDID', buildId)
+          for (let i = 0; i < GY_STATIONS.length; i++) {
+            const e = GY_STATIONS[i];
+            if (e.buildId && e.buildId === buildId) {
+              commit('SET_DEPARTMENTID', e.id)
+            }
+          }
+          if (buildId == '654044537953460225') {
+            commit('SET_DEPARTMENTID', '')
+
+          }
           // 缓存中存入buildId
           // 缓存中存入buildId
           localStorage.setItem('buildId', buildId)
           localStorage.setItem('buildId', buildId)
           resolve(resData)
           resolve(resData)

+ 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, xDist, yDist);
   // console.log(c)
   // console.log(c)
   const radius = 6378137 //坐标系球的半径  WGS84是6378137
   const radius = 6378137 //坐标系球的半径  WGS84是6378137
-  let xOffset = -2700 //x偏移量 单位mm  -7400;// -2700 tkt  -700 duyun   tkt2  0
-  let yOffset = 2000 //y偏移量 单位mm   1800;// 2000 tkt  1600 duyun  tkt2 1000 
+  let xOffset = -700 //x偏移量 单位mm  -7400;// -2700 tkt  -700 duyun   tkt2  0
+  let yOffset = 1600 //y偏移量 单位mm   1800;// 2000 tkt  1600 duyun  tkt2 1000 
   // let xOffset = 0 //x偏移量 单位mm  -7400;// -2700 tkt  -700 duyun   tkt2  0
   // let xOffset = 0 //x偏移量 单位mm  -7400;// -2700 tkt  -700 duyun   tkt2  0
   // let yOffset = 1000 //y偏移量 单位mm   1800;// 2000 tkt  1600 duyun  tkt2 1000 
   // let yOffset = 1000 //y偏移量 单位mm   1800;// 2000 tkt  1600 duyun  tkt2 1000 
   //console.log("before", xDist, yDist)
   //console.log("before", xDist, yDist)

+ 8 - 6
src/utils/mapUtil.js

@@ -251,15 +251,17 @@ export const setLayer = id => {
  * @param {飞行参数} t
  * @param {飞行参数} t
  * @param {飞行回调} e
  * @param {飞行回调} e
  */
  */
-export const flyToPerspective = (t, e) => {
-  //_map3d_flyToPerspective(data);
+export const flyToPerspective = ({ duration = 1, ...rest }, callback) => {
   const viewer = getViewer()
   const viewer = getViewer()
-  // console.log(viewer.camera);
-  // console.log(viewer.scene.camera);
+  if (!viewer) {
+    console.error('Viewer is not available.')
+    return
+  }
   viewer.camera.flyTo({
   viewer.camera.flyTo({
-    ...t,
+    duration,
+    ...rest,
     complete: () => {
     complete: () => {
-      e && e()
+      callback && callback()
     },
     },
   })
   })
 }
 }

+ 6 - 5
src/utils/request.js

@@ -67,11 +67,12 @@ $http.interceptors.response.use(
     if ((res.code + "").startsWith("2")) {
     if ((res.code + "").startsWith("2")) {
       return res;
       return res;
     } else {
     } else {
-      Message({
-        message: res?.msg || "连接错误",
-        type: "error",
-        duration: 800,
-      });
+      // Message({
+      //   message: res?.msg || "连接错误",
+      //   type: "error",
+      //   duration: 800,
+      // });
+      // console.log("ERROR:", res);
       return Promise.reject(res);
       return Promise.reject(res);
     }
     }
   },
   },

+ 63 - 0
src/utils/requestDDXT.js

@@ -0,0 +1,63 @@
+import axios from 'axios'
+import { Message } from 'element-ui'
+import md5 from 'md5'
+
+const access_key = ACCESS_KEY
+const secret_key = SECRET_KEY
+const timestamp = new Date().getTime()
+const sign = md5(access_key + timestamp + secret_key)
+
+// create an axios instance
+const service = axios.create({
+  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
+  // baseURL: process.env.YAPI_BASE_API, //本地yapi模拟接口
+  // withCredentials: true, // send cookies when cross-domain requests
+  timeout: 10000, // request timeout
+})
+
+// request interceptor
+service.interceptors.request.use(
+  (config) => {
+    // do something before request is sent
+    // console.log('request参数', access_key, timestamp, secret_key, sign);
+    config.headers["Content-Type"] = "multipart/form-data";
+    config.headers["access_key"] = access_key;
+    config.headers["sign"] = sign;
+    config.headers["timestamp"] = timestamp;
+    return config
+  },
+  (error) => {
+    console.log('请求错误', error) // for debug
+    return Promise.reject(error)
+  }
+)
+
+// response interceptor
+service.interceptors.response.use(
+  (response) => {
+    // const res = jsonKeysToCase(response.data)
+    const res = response.data
+    //console.log(response)
+    if (res.code !== 200) {
+      Message({
+        message: res.msg || 'Error',
+        type: 'error',
+        duration: 20 * 1000,
+      })
+      return Promise.reject(new Error(res.msg || 'Error'))
+    } else {
+      return res
+    }
+  },
+  (error) => {
+    console.error('响应错误', error)
+    // Message({
+    //   message: error.message,
+    //   type: 'error',
+    //   duration: 5 * 1000,
+    // })
+    return Promise.reject(error)
+  }
+)
+
+export default service

+ 2 - 0
src/utils/webRTU.js

@@ -0,0 +1,2 @@
+import { rtcHelperWithLogging } from './plugins/tr-webrtc.min.js';
+let rtcHelper = rtcHelperWithLogging;

+ 8 - 0
src/views/Home.vue

@@ -21,6 +21,10 @@
     <onekey-110-dialog />
     <onekey-110-dialog />
     <!-- 防爆扩音弹窗 由vuex控制 -->
     <!-- 防爆扩音弹窗 由vuex控制 -->
     <sound-dialog />
     <sound-dialog />
+    <!-- 门禁弹窗 由vuex控制 -->
+    <access-control-dialog />
+    <!-- 激光云台 由vuex控制 -->
+    <j-g-y-t-control-dialog />
     <!-- 人员列表弹窗 由vuex控制 -->
     <!-- 人员列表弹窗 由vuex控制 -->
     <person-list-dialog />
     <person-list-dialog />
     <!-- 全局声音播放器 由vuex控制 -->
     <!-- 全局声音播放器 由vuex控制 -->
@@ -60,6 +64,8 @@ import ContactInfoDialog from "@/views/components/emergency/ContactInfoDialog";
 import PersonListDialog from "@/views/components/dialog/PersonListDialog";
 import PersonListDialog from "@/views/components/dialog/PersonListDialog";
 import Onekey110Dialog from "@/views/components/dialog/Onekey110Dialog";
 import Onekey110Dialog from "@/views/components/dialog/Onekey110Dialog";
 import SoundDialog from "@/views/components/dialog/SoundDialog";
 import SoundDialog from "@/views/components/dialog/SoundDialog";
+import AccessControlDialog from "@/views/components/dialog/AccessControlDialog";
+import JGYTControlDialog from "@/views/components/dialog/JGYTControlDialog";
 import AlarmDetailDialog from "@/views/components/dialog/AlarmDetailDialog";
 import AlarmDetailDialog from "@/views/components/dialog/AlarmDetailDialog";
 import AlarmAudioDialog from "@/views/components/dialog/AlarmAudioDialog";
 import AlarmAudioDialog from "@/views/components/dialog/AlarmAudioDialog";
 import RiskTipDialog from "@/views/components/dialog/RiskTipDialog";
 import RiskTipDialog from "@/views/components/dialog/RiskTipDialog";
@@ -84,6 +90,8 @@ export default {
     Onekey110Dialog,
     Onekey110Dialog,
     PersonListDialog,
     PersonListDialog,
     SoundDialog,
     SoundDialog,
+    AccessControlDialog,
+    JGYTControlDialog,
     AlarmAudioDialog,
     AlarmAudioDialog,
     RiskTipDialog,
     RiskTipDialog,
     BaseBlankDialog,
     BaseBlankDialog,

+ 357 - 183
src/views/alarm/alarmList/index.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
   <div class="alarmList-container">
   <div class="alarmList-container">
     <!-- 弹窗内容 -->
     <!-- 弹窗内容 -->
-    <div class="dialog_box">
+    <div class="dialog_box" :key="timer">
       <div class="search-box">
       <div class="search-box">
         <div class="search-item">
         <div class="search-item">
           <span class="search-label">时间:</span>
           <span class="search-label">时间:</span>
@@ -54,7 +54,12 @@
         </div>
         </div>
         <div class="search-item">
         <div class="search-item">
           <span class="search-label">报警分类:</span>
           <span class="search-label">报警分类:</span>
-          <el-select size="mini" v-model="query.category" clearable @change="searchData()">
+          <el-select
+            size="mini"
+            v-model="query.category"
+            clearable
+            @change="searchData()"
+          >
             <el-option
             <el-option
               v-for="item in categoryOptions"
               v-for="item in categoryOptions"
               :key="item.dictKey"
               :key="item.dictKey"
@@ -65,7 +70,12 @@
         </div>
         </div>
         <div class="search-item">
         <div class="search-item">
           <span class="search-label"> 报警级别:</span>
           <span class="search-label"> 报警级别:</span>
-          <el-select size="mini" v-model="query.level" clearable @change="searchData">
+          <el-select
+            size="mini"
+            v-model="query.level"
+            clearable
+            @change="searchData"
+          >
             <el-option :value="'024001'" label="一级报警"></el-option>
             <el-option :value="'024001'" label="一级报警"></el-option>
             <el-option :value="'024002'" label="二级报警"></el-option>
             <el-option :value="'024002'" label="二级报警"></el-option>
             <el-option :value="'024003'" label="三级报警"></el-option>
             <el-option :value="'024003'" label="三级报警"></el-option>
@@ -75,39 +85,64 @@
       <div class="search-box">
       <div class="search-box">
         <div class="search-item">
         <div class="search-item">
           <span class="search-label">确认状态:</span>
           <span class="search-label">确认状态:</span>
-          <el-select size="mini" v-model="query.confirmStatus" clearable @change="searchData">
+          <el-select
+            size="mini"
+            v-model="query.confirmStatus"
+            clearable
+            @change="searchData"
+          >
             <el-option :value="'1'" label="已确认"></el-option>
             <el-option :value="'1'" label="已确认"></el-option>
             <el-option :value="'0'" label="未确认"></el-option>
             <el-option :value="'0'" label="未确认"></el-option>
           </el-select>
           </el-select>
         </div>
         </div>
         <div class="search-item">
         <div class="search-item">
           <span class="search-label"> 处理状态:</span>
           <span class="search-label"> 处理状态:</span>
-          <el-select size="mini" v-model="query.dealStatus" clearable @change="searchData">
+          <el-select
+            size="mini"
+            v-model="query.dealStatus"
+            clearable
+            @change="searchData"
+          >
             <el-option :value="'1'" label="已处理"></el-option>
             <el-option :value="'1'" label="已处理"></el-option>
             <el-option :value="'0'" label="未处理"></el-option>
             <el-option :value="'0'" label="未处理"></el-option>
           </el-select>
           </el-select>
         </div>
         </div>
         <div class="search-item">
         <div class="search-item">
           <span class="search-label">恢复状态:</span>
           <span class="search-label">恢复状态:</span>
-          <el-select size="mini" v-model="query.recoveryStatus" clearable @change="searchData">
+          <el-select
+            size="mini"
+            v-model="query.recoveryStatus"
+            clearable
+            @change="searchData"
+          >
             <el-option :value="'1'" label="已恢复"></el-option>
             <el-option :value="'1'" label="已恢复"></el-option>
             <el-option :value="'0'" label="未恢复"></el-option>
             <el-option :value="'0'" label="未恢复"></el-option>
           </el-select>
           </el-select>
         </div>
         </div>
         <div class="search-btn" @click="searchData">
         <div class="search-btn" @click="searchData">
-          <img :src="require('@/assets/imgs/dialog/icon_close.png')" alt="查询" />
+          <img
+            :src="require('@/assets/imgs/dialog/icon_close.png')"
+            alt="查询"
+          />
         </div>
         </div>
         <div class="search-btn" @click="handleReset">
         <div class="search-btn" @click="handleReset">
-          <img :src="require('@/assets/imgs/dialog/icon_reset.png')" alt="重置" />
+          <img
+            :src="require('@/assets/imgs/dialog/icon_reset.png')"
+            alt="重置"
+          />
         </div>
         </div>
         <div class="search-btn2" @click="exportData">
         <div class="search-btn2" @click="exportData">
           <el-button size="mini" type="success">导出</el-button>
           <el-button size="mini" type="success">导出</el-button>
         </div>
         </div>
         <div class="search-btn2">
         <div class="search-btn2">
-          <el-button size="mini" type="success" @click="handleConfirmMulti">批量确认</el-button>
+          <el-button size="mini" type="success" @click="handleConfirmMulti"
+            >批量确认</el-button
+          >
         </div>
         </div>
         <div class="search-btn2">
         <div class="search-btn2">
-          <el-button size="mini" type="success" @click="handleDealMulti">批量处理</el-button>
+          <el-button size="mini" type="success" @click="handleDealMulti"
+            >批量处理</el-button
+          >
         </div>
         </div>
       </div>
       </div>
       <!-- 内容 -->
       <!-- 内容 -->
@@ -129,7 +164,11 @@
             transition: 'width 0.8s',
             transition: 'width 0.8s',
           }"
           }"
         >
         >
-          <img class="split-line" :src="require('@/assets/imgs/btn_take back@2x.png')" @click="hideDetail" />
+          <img
+            class="split-line"
+            :src="require('@/assets/imgs/btn_take back@2x.png')"
+            @click="hideDetail"
+          />
           <div class="detail-content-box">
           <div class="detail-content-box">
             <div class="detail-title">
             <div class="detail-title">
               <img :src="require('@/assets/imgs/img_round@2x.png')" />
               <img :src="require('@/assets/imgs/img_round@2x.png')" />
@@ -138,7 +177,9 @@
             <div class="detail-content">
             <div class="detail-content">
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">报警位号:</span>
                 <span class="detail-label">报警位号:</span>
-                <span class="detail-text">{{ curAlarmDetail.alarmTagName }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.alarmTagName
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">报警内容:</span>
                 <span class="detail-label">报警内容:</span>
@@ -150,7 +191,9 @@
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">报警类型:</span>
                 <span class="detail-label">报警类型:</span>
-                <span class="detail-text">{{ curAlarmDetail.categoryStr }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.categoryStr
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">报警时间:</span>
                 <span class="detail-label">报警时间:</span>
@@ -158,19 +201,27 @@
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">确认状态:</span>
                 <span class="detail-label">确认状态:</span>
-                <span class="detail-text">{{ curAlarmDetail.confirmStatusStr }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.confirmStatusStr
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">确认时间:</span>
                 <span class="detail-label">确认时间:</span>
-                <span class="detail-text">{{ curAlarmDetail.confirmTime }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.confirmTime
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">确认人:</span>
                 <span class="detail-label">确认人:</span>
-                <span class="detail-text">{{ curAlarmDetail.confirmPersonName }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.confirmPersonName
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">处理状态:</span>
                 <span class="detail-label">处理状态:</span>
-                <span class="detail-text">{{ curAlarmDetail.dealStatusStr }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.dealStatusStr
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">处理时间:</span>
                 <span class="detail-label">处理时间:</span>
@@ -178,24 +229,38 @@
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">处理人:</span>
                 <span class="detail-label">处理人:</span>
-                <span class="detail-text">{{ curAlarmDetail.dealPersonName }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.dealPersonName
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">恢复状态:</span>
                 <span class="detail-label">恢复状态:</span>
-                <span class="detail-text">{{ curAlarmDetail.recoveryStatusStr }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.recoveryStatusStr
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">恢复时间:</span>
                 <span class="detail-label">恢复时间:</span>
-                <span class="detail-text">{{ curAlarmDetail.recoveryTime }}</span>
+                <span class="detail-text">{{
+                  curAlarmDetail.recoveryTime
+                }}</span>
               </div>
               </div>
               <div class="detail-item">
               <div class="detail-item">
                 <span class="detail-label">处理方式:</span>
                 <span class="detail-label">处理方式:</span>
                 <span class="detail-text">
                 <span class="detail-text">
                   <el-radio-group v-model="curAlarmDetail.dataType">
                   <el-radio-group v-model="curAlarmDetail.dataType">
-                    <el-radio :label="0" style="color: #fff !important">正常</el-radio>
-                    <el-radio :label="1" style="color: #fff !important">误报</el-radio>
-                    <el-radio :label="2" style="color: #fff !important">测试</el-radio>
-                    <el-radio :label="3" style="color: #fff !important">抑制</el-radio>
+                    <el-radio :label="0" style="color: #fff !important"
+                      >正常</el-radio
+                    >
+                    <el-radio :label="1" style="color: #fff !important"
+                      >误报</el-radio
+                    >
+                    <el-radio :label="2" style="color: #fff !important"
+                      >测试</el-radio
+                    >
+                    <el-radio :label="3" style="color: #fff !important"
+                      >抑制</el-radio
+                    >
                   </el-radio-group>
                   </el-radio-group>
                 </span>
                 </span>
               </div>
               </div>
@@ -216,8 +281,16 @@
                 <div class="image-box">
                 <div class="image-box">
                   <el-image
                   <el-image
                     fit="contain"
                     fit="contain"
-                    :src="`${BASE_URL}${curAlarmDetail.imageUrl.replace('\/\/', '/')}`"
-                    :preview-src-list="[`${BASE_URL}${curAlarmDetail.imageUrl.replace('\/\/', '/')}`]"
+                    :src="`${BASE_URL}${curAlarmDetail.imageUrl.replace(
+                      '\/\/',
+                      '/'
+                    )}`"
+                    :preview-src-list="[
+                      `${BASE_URL}${curAlarmDetail.imageUrl.replace(
+                        '\/\/',
+                        '/'
+                      )}`,
+                    ]"
                   />
                   />
                 </div>
                 </div>
               </div>
               </div>
@@ -231,20 +304,34 @@
               >
               >
                 确认
                 确认
               </el-button>
               </el-button>
-              <el-button class="btn-handle" size="mini" @click="handleDeal" v-show="curAlarmDetail.dealStatus == '0'">
+              <el-button
+                class="btn-handle"
+                size="mini"
+                @click="handleDeal"
+                v-show="curAlarmDetail.dealStatus == '0'"
+              >
                 处理
                 处理
               </el-button>
               </el-button>
-              <el-button class="btn-cancel" size="mini" @click="handleClose">取消</el-button>
+              <el-button class="btn-cancel" size="mini" @click="handleClose"
+                >取消</el-button
+              >
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
       </div>
       </div>
       <div class="page-box">
       <div class="page-box">
-        <base-pagination :pageInfo="pageConfig" @pageChange="getAlarmDataList"></base-pagination>
+        <base-pagination
+          :pageInfo="pageConfig"
+          @pageChange="getAlarmDataList"
+        ></base-pagination>
       </div>
       </div>
     </div>
     </div>
-    <deal-multi-dialog :dialogConfig="dealMultiDialogConfig"></deal-multi-dialog>
-    <confirm-multi-dialog :dialogConfig="confirmMultiDialogConfig"></confirm-multi-dialog>
+    <deal-multi-dialog
+      :dialogConfig="dealMultiDialogConfig"
+    ></deal-multi-dialog>
+    <confirm-multi-dialog
+      :dialogConfig="confirmMultiDialogConfig"
+    ></confirm-multi-dialog>
   </div>
   </div>
 </template>
 </template>
 <script>
 <script>
@@ -257,18 +344,18 @@ import {
   getDepartmentByPid,
   getDepartmentByPid,
   download,
   download,
   exportData,
   exportData,
-} from '@/API/alarm'
-import { getDictDetailByType } from '@/API/dict'
-import { downloadFile } from '@/utils/index'
-import Dayjs from 'dayjs'
-import BaseTableList from '@/views/components/base/BaseTableList.vue'
-import BasePagination from '@/views/components/base/BasePagination.vue'
-import DealMultiDialog from '@/views/alarm/alarmList/components/DealMultiDialog.vue'
-import ConfirmMultiDialog from '@/views/alarm/alarmList/components/ConfirmMultiDialog.vue'
-import { calendarShortcuts } from '@/utils/shortcuts'
-import { add } from 'lodash-es'
+} from "@/API/alarm";
+import { getDictDetailByType } from "@/API/dict";
+import { downloadFile } from "@/utils/index";
+import Dayjs from "dayjs";
+import BaseTableList from "@/views/components/base/BaseTableList.vue";
+import BasePagination from "@/views/components/base/BasePagination.vue";
+import DealMultiDialog from "@/views/alarm/alarmList/components/DealMultiDialog.vue";
+import ConfirmMultiDialog from "@/views/alarm/alarmList/components/ConfirmMultiDialog.vue";
+import { calendarShortcuts } from "@/utils/shortcuts";
+import { add } from "lodash-es";
 export default {
 export default {
-  name: 'AlarmList',
+  name: "AlarmList",
   components: {
   components: {
     BaseTableList,
     BaseTableList,
     BasePagination,
     BasePagination,
@@ -277,20 +364,21 @@ export default {
   },
   },
   data() {
   data() {
     return {
     return {
+      timer: new Date().getTime(),
       query: {
       query: {
         time: [
         time: [
-          Dayjs(new Date()).subtract(1, 'month').format('YYYY-MM-DD HH:mm:ss'),
-          Dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'),
+          Dayjs(new Date()).subtract(1, "month").format("YYYY-MM-DD HH:mm:ss"),
+          Dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
         ],
         ],
-        category: '',
-        level: '',
-        dealStatus: '',
-        confirmStatus: '',
-        type: '',
-        key: '',
-        tag: '',
-        recoveryStatus: '',
-        departmentId: '',
+        category: "",
+        level: "",
+        dealStatus: "",
+        confirmStatus: "",
+        type: "",
+        key: "",
+        tag: "",
+        recoveryStatus: "",
+        departmentId: "",
       },
       },
       pageConfig: {
       pageConfig: {
         pageNo: 1,
         pageNo: 1,
@@ -303,18 +391,18 @@ export default {
         // rowHeight: 42,
         // rowHeight: 42,
         // rowSpacing: 12,
         // rowSpacing: 12,
         header: [
         header: [
-          { title: '报警时间', prop: 'eventTime', width: '' },
-          { title: '报警位号', prop: 'alarmTagName', width: '' },
-          { title: '报警分类', prop: 'categoryStr', width: '' },
-          { title: '报警级别', prop: 'levelStr', width: '' },
-          { title: '报警内容', prop: 'content', width: '40%' },
-          { title: '确认状态', prop: 'confirmStatusStr', width: '' },
-          { title: '处理状态', prop: 'dealStatusStr', width: '' },
-          { title: '恢复状态', prop: 'recoveryStatusStr', width: '' },
+          { title: "报警时间", prop: "eventTime", width: "" },
+          { title: "报警位号", prop: "alarmTagName", width: "" },
+          { title: "报警分类", prop: "categoryStr", width: "" },
+          { title: "报警级别", prop: "levelStr", width: "" },
+          { title: "报警内容", prop: "content", width: "40%" },
+          { title: "确认状态", prop: "confirmStatusStr", width: "" },
+          { title: "处理状态", prop: "dealStatusStr", width: "" },
+          { title: "恢复状态", prop: "recoveryStatusStr", width: "" },
         ],
         ],
         tableData: [],
         tableData: [],
-        rowClick: row => {
-          this.showDetail(row)
+        rowClick: (row) => {
+          this.showDetail(row);
         },
         },
       },
       },
       categoryOptions: [],
       categoryOptions: [],
@@ -327,59 +415,140 @@ export default {
       curAlarmDetail: {},
       curAlarmDetail: {},
       dealMultiDialogConfig: {},
       dealMultiDialogConfig: {},
       confirmMultiDialogConfig: {},
       confirmMultiDialogConfig: {},
-    }
+    };
+  },
+  watch: {
+    $route(to, from) {
+      // console.log(from, "前from,后to", to);
+      console.log(this.$route);
+      if (this.$route.query) {
+        if (this.$route.query.dateRange == "24H") {
+          this.query.time = [
+            Dayjs(new Date()).subtract(1, "day").format("YYYY-MM-DD HH:mm:ss"),
+            Dayjs(new Date()).format("YYYY-MM-DD 23:59:59"),
+          ];
+        }
+        if (!!this.$route.query.date) {
+          console.log(
+            Dayjs(
+              this.$route.query.date
+                .replace("年", "-")
+                .replace("月", "-")
+                .replace("日", "")
+            )
+          );
+          this.query.time = [
+            Dayjs(
+              this.$route.query.date
+                .replace("年", "-")
+                .replace("月", "-")
+                .replace("日", "")
+            ).format("YYYY-MM-DD HH:mm:ss"),
+            Dayjs(
+              this.$route.query.date
+                .replace("年", "-")
+                .replace("月", "-")
+                .replace("日", "")
+            )
+              .add(1, "day")
+              .subtract(1, "second")
+              .format("YYYY-MM-DD HH:mm:ss"),
+          ];
+        }
+        if (!!this.$route.query.confirmStatus) {
+          this.query.confirmStatus = this.$route.query.confirmStatus;
+        }
+        if (!!this.$route.query.dealStatus) {
+          this.query.dealStatus = this.$route.query.dealStatus;
+        }
+        if (!!this.$route.query.level) {
+          this.query.level = this.$route.query.level;
+        }
+        if (!!this.$route.query.recoveryStatus) {
+          this.query.recoveryStatus = this.$route.query.recoveryStatus;
+        }
+        if (!!this.$route.query.category) {
+          this.query.category = this.$route.query.category;
+        } else {
+          this.query.category = "";
+        }
+        if (!!this.$route.query.departmentId) {
+          if (typeof this.$route.query.departmentId === "string") {
+            this.query.departmentId = new Array(this.$route.query.departmentId);
+          }
+        }
+      }
+      this.getAlarmCategory();
+      this.getAlarmDataList();
+      this.getDepartmentByPid();
+    },
   },
   },
   mounted() {
   mounted() {
-    console.log(this.$route)
-    if (this.$route.query.dateRange == '24H') {
+    console.log(this.$route);
+    if (this.$route.query.dateRange == "24H") {
       this.query.time = [
       this.query.time = [
-        Dayjs(new Date()).subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'),
-        Dayjs(new Date()).format('YYYY-MM-DD 23:59:59'),
-      ]
+        Dayjs(new Date()).subtract(1, "day").format("YYYY-MM-DD HH:mm:ss"),
+        Dayjs(new Date()).format("YYYY-MM-DD 23:59:59"),
+      ];
     }
     }
     if (!!this.$route.query.date) {
     if (!!this.$route.query.date) {
-      console.log(Dayjs(this.$route.query.date.replace('年', '-').replace('月', '-').replace('日', '')))
+      console.log(
+        Dayjs(
+          this.$route.query.date
+            .replace("年", "-")
+            .replace("月", "-")
+            .replace("日", "")
+        )
+      );
       this.query.time = [
       this.query.time = [
-        Dayjs(this.$route.query.date.replace('年', '-').replace('月', '-').replace('日', '')).format(
-          'YYYY-MM-DD HH:mm:ss'
-        ),
-        Dayjs(this.$route.query.date.replace('年', '-').replace('月', '-').replace('日', ''))
-          .add(1, 'day')
-          .subtract(1, 'second')
-          .format('YYYY-MM-DD HH:mm:ss'),
-      ]
+        Dayjs(
+          this.$route.query.date
+            .replace("年", "-")
+            .replace("月", "-")
+            .replace("日", "")
+        ).format("YYYY-MM-DD HH:mm:ss"),
+        Dayjs(
+          this.$route.query.date
+            .replace("年", "-")
+            .replace("月", "-")
+            .replace("日", "")
+        )
+          .add(1, "day")
+          .subtract(1, "second")
+          .format("YYYY-MM-DD HH:mm:ss"),
+      ];
     }
     }
     if (!!this.$route.query.confirmStatus) {
     if (!!this.$route.query.confirmStatus) {
-      this.query.confirmStatus = this.$route.query.confirmStatus
+      this.query.confirmStatus = this.$route.query.confirmStatus;
     }
     }
     if (!!this.$route.query.dealStatus) {
     if (!!this.$route.query.dealStatus) {
-      this.query.dealStatus = this.$route.query.dealStatus
+      this.query.dealStatus = this.$route.query.dealStatus;
     }
     }
     if (!!this.$route.query.level) {
     if (!!this.$route.query.level) {
-      this.query.level = this.$route.query.level
+      this.query.level = this.$route.query.level;
     }
     }
     if (!!this.$route.query.recoveryStatus) {
     if (!!this.$route.query.recoveryStatus) {
-      this.query.recoveryStatus = this.$route.query.recoveryStatus
+      this.query.recoveryStatus = this.$route.query.recoveryStatus;
     }
     }
     if (!!this.$route.query.category) {
     if (!!this.$route.query.category) {
-      this.query.category = this.$route.query.category
+      this.query.category = this.$route.query.category;
     }
     }
     if (!!this.$route.query.departmentId) {
     if (!!this.$route.query.departmentId) {
-      if (typeof this.$route.query.departmentId === 'string') {
-        this.query.departmentId = new Array(this.$route.query.departmentId)
+      if (typeof this.$route.query.departmentId === "string") {
+        this.query.departmentId = new Array(this.$route.query.departmentId);
       }
       }
     }
     }
     // if (!!this.$route.query.station) {
     // if (!!this.$route.query.station) {
     //   this.query.key = this.$route.query.station;
     //   this.query.key = this.$route.query.station;
     // }
     // }
-    this.getAlarmCategory()
-    this.getAlarmDataList()
-    this.getDepartmentByPid()
+    this.getAlarmCategory();
+    this.getAlarmDataList();
+    this.getDepartmentByPid();
   },
   },
   methods: {
   methods: {
     searchData() {
     searchData() {
-      this.pageConfig.pageNo = 1
-      this.getAlarmDataList()
+      this.pageConfig.pageNo = 1;
+      this.getAlarmDataList();
     },
     },
     exportData() {
     exportData() {
       const params = {
       const params = {
@@ -396,30 +565,32 @@ export default {
         key: this.query.key,
         key: this.query.key,
         tag: this.query.tag,
         tag: this.query.tag,
         departmentId:
         departmentId:
-          this.query.departmentId.length > 0 ? this.query.departmentId[this.query.departmentId.length - 1] : '',
-      }
+          this.query.departmentId.length > 0
+            ? this.query.departmentId[this.query.departmentId.length - 1]
+            : "",
+      };
       exportData(params)
       exportData(params)
-        .then(res => {
+        .then((res) => {
           if (res.code === 20000) {
           if (res.code === 20000) {
             download({ filePath: res.data, prefix: true })
             download({ filePath: res.data, prefix: true })
-              .then(result => {
-                downloadFile(result.data)
+              .then((result) => {
+                downloadFile(result.data);
                 //crud.exportLoading = false;
                 //crud.exportLoading = false;
               })
               })
-              .catch(error => {
-                console.error(error)
+              .catch((error) => {
+                console.error(error);
                 //crud.exportLoading = false;
                 //crud.exportLoading = false;
-              })
+              });
 
 
             //window.location.href = 'file/downloadFile?filePath=' + res.data + '&delete=1'
             //window.location.href = 'file/downloadFile?filePath=' + res.data + '&delete=1'
           } else {
           } else {
-            this.$message.error(res.msg)
+            this.$message.error(res.msg);
           }
           }
         })
         })
-        .catch(error => {
-          console.error(error)
+        .catch((error) => {
+          console.error(error);
           //crud.exportLoading = false;
           //crud.exportLoading = false;
-        })
+        });
     },
     },
     async getAlarmDataList() {
     async getAlarmDataList() {
       try {
       try {
@@ -437,10 +608,13 @@ export default {
           key: this.query.key,
           key: this.query.key,
           tag: this.query.tag,
           tag: this.query.tag,
           departmentId:
           departmentId:
-            this.query.departmentId.length > 0 ? this.query.departmentId[this.query.departmentId.length - 1] : '',
-        }
-        const res = await getAlarmDataList(params)
-        let alarmData = res.data.content
+            this.query.departmentId.length > 0
+              ? this.query.departmentId[this.query.departmentId.length - 1]
+              : "",
+        };
+        // console.log("报警记录查询参数", params);
+        const res = await getAlarmDataList(params);
+        let alarmData = res.data.content;
         // alarmData.push({
         // alarmData.push({
         //   eventTime: "2022-12-22 10:12:13",
         //   eventTime: "2022-12-22 10:12:13",
         //   category: "1",
         //   category: "1",
@@ -448,60 +622,60 @@ export default {
         //   dealStatus: "1",
         //   dealStatus: "1",
         //   imageUrl: "",
         //   imageUrl: "",
         // });
         // });
-        this.tableConfig.tableData = alarmData
-        this.pageConfig.pageTotal = res.data.total || alarmData.length
+        this.tableConfig.tableData = alarmData;
+        this.pageConfig.pageTotal = res.data.total || alarmData.length;
         // console.log(alarmData);
         // console.log(alarmData);
       } catch (err) {}
       } catch (err) {}
     },
     },
     async getAlarmCount() {
     async getAlarmCount() {
       try {
       try {
-        const res = await getAlarmCount()
-        const { content } = res.data
-        this.categoryOptions = content
+        const res = await getAlarmCount();
+        const { content } = res.data;
+        this.categoryOptions = content;
       } catch (err) {
       } catch (err) {
-        console.log(err)
+        console.log(err);
       }
       }
     },
     },
     async getAlarmCategory() {
     async getAlarmCategory() {
       try {
       try {
-        const param = { dictType: '100' }
-        const res = await getDictDetailByType(param)
-        const { content } = res.data
-        this.categoryOptions = content
+        const param = { dictType: "100" };
+        const res = await getDictDetailByType(param);
+        const { content } = res.data;
+        this.categoryOptions = content;
       } catch (err) {
       } catch (err) {
-        console.log(err)
+        console.log(err);
       }
       }
     },
     },
     async getAlarmType(category) {
     async getAlarmType(category) {
-      this.query.type = ''
-      this.alarmTypeOptions = []
-      if (!category) return
+      this.query.type = "";
+      this.alarmTypeOptions = [];
+      if (!category) return;
       try {
       try {
-        const res = await getAlarmType({ category })
-        const { content } = res.data
-        this.alarmTypeOptions = content
+        const res = await getAlarmType({ category });
+        const { content } = res.data;
+        this.alarmTypeOptions = content;
       } catch (err) {
       } catch (err) {
-        console.log(err)
+        console.log(err);
       }
       }
     },
     },
     async getDepartmentByPid() {
     async getDepartmentByPid() {
       try {
       try {
-        const p = { id: '0' }
-        const res = await getDepartmentByPid(p)
-        let { content } = res.data
-        content.forEach(element => {
-          element.value = element.id
-          element.label = element.departmentName
+        const p = { id: "0" };
+        const res = await getDepartmentByPid(p);
+        let { content } = res.data;
+        content.forEach((element) => {
+          element.value = element.id;
+          element.label = element.departmentName;
           if (element.children) {
           if (element.children) {
-            element.children.forEach(element2 => {
-              element2.value = element2.id
-              element2.label = element2.departmentName
-            })
+            element.children.forEach((element2) => {
+              element2.value = element2.id;
+              element2.label = element2.departmentName;
+            });
           }
           }
-        })
-        this.departmentOptions = content
+        });
+        this.departmentOptions = content;
       } catch (err) {
       } catch (err) {
-        console.log(err)
+        console.log(err);
       }
       }
     },
     },
     async dealAlarm() {
     async dealAlarm() {
@@ -509,71 +683,71 @@ export default {
         id: this.curAlarmDetail.id,
         id: this.curAlarmDetail.id,
         dealContent: this.curAlarmDetail.dealContent,
         dealContent: this.curAlarmDetail.dealContent,
         dataType: this.curAlarmDetail.dataType,
         dataType: this.curAlarmDetail.dataType,
-      }
+      };
       try {
       try {
-        const res = await dealAlarm(params)
+        const res = await dealAlarm(params);
         if (res.code == 20000) {
         if (res.code == 20000) {
-          this.hideDetail()
-          this.getAlarmDataList()
+          this.hideDetail();
+          this.getAlarmDataList();
           this.$message({
           this.$message({
-            message: '处理完成',
-            type: 'success',
-          })
+            message: "处理完成",
+            type: "success",
+          });
         }
         }
       } catch (err) {
       } catch (err) {
-        console.log(err)
+        console.log(err);
       }
       }
     },
     },
     async confirmAlarm() {
     async confirmAlarm() {
       const params = {
       const params = {
         id: this.curAlarmDetail.id,
         id: this.curAlarmDetail.id,
         dealContent: this.curAlarmDetail.dealContent,
         dealContent: this.curAlarmDetail.dealContent,
-      }
+      };
       try {
       try {
-        const res = await confirmAlarm(params)
+        const res = await confirmAlarm(params);
         if (res.code == 20000) {
         if (res.code == 20000) {
-          this.hideDetail()
-          this.getAlarmDataList()
+          this.hideDetail();
+          this.getAlarmDataList();
           this.$message({
           this.$message({
-            message: '确认完成',
-            type: 'success',
-          })
+            message: "确认完成",
+            type: "success",
+          });
         }
         }
       } catch (err) {
       } catch (err) {
-        console.log(err)
+        console.log(err);
       }
       }
     },
     },
     handleReset() {
     handleReset() {
       this.query = {
       this.query = {
         time: [
         time: [
-          Dayjs(new Date()).subtract(1, 'month').format('YYYY-MM-DD HH:mm:ss'),
-          Dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'),
+          Dayjs(new Date()).subtract(1, "month").format("YYYY-MM-DD HH:mm:ss"),
+          Dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
         ],
         ],
-        category: '',
-        dealStatus: '',
-        type: '',
-      }
-      this.searchData()
+        category: "",
+        dealStatus: "",
+        type: "",
+      };
+      this.searchData();
     },
     },
     showDetail(row) {
     showDetail(row) {
-      console.log(row)
-      this.detailShow = true
-      this.curAlarmDetail = row
+      console.log(row);
+      this.detailShow = true;
+      this.curAlarmDetail = row;
     },
     },
     hideDetail() {
     hideDetail() {
-      this.detailShow = false
-      this.curAlarmDetail = {}
+      this.detailShow = false;
+      this.curAlarmDetail = {};
     },
     },
     handleDeal() {
     handleDeal() {
-      console.log(this.curAlarmDetail)
-      this.dealAlarm()
+      console.log(this.curAlarmDetail);
+      this.dealAlarm();
     },
     },
     handleConfirm() {
     handleConfirm() {
-      console.log(this.curAlarmDetail)
-      this.confirmAlarm()
+      console.log(this.curAlarmDetail);
+      this.confirmAlarm();
     },
     },
     handleClose() {
     handleClose() {
-      this.hideDetail()
+      this.hideDetail();
     },
     },
     handleDealMulti() {
     handleDealMulti() {
       // this.$confirm("确认退出该系统?", "提示", {
       // this.$confirm("确认退出该系统?", "提示", {
@@ -587,19 +761,19 @@ export default {
       //   window.location.reload();
       //   window.location.reload();
       // });
       // });
       let ids = this.tableConfig.tableData.map((obj, index) => {
       let ids = this.tableConfig.tableData.map((obj, index) => {
-        return obj.id
-      })
+        return obj.id;
+      });
       let dialogConfig = {
       let dialogConfig = {
-        dialogId: 'dealMultiDialog',
+        dialogId: "dealMultiDialog",
         show: true, //是否显示
         show: true, //是否显示
-        title: '批量处理',
+        title: "批量处理",
         width: 500, //px宽度
         width: 500, //px宽度
         height: 320, //px高度
         height: 320, //px高度
         center: true, //是否居中定位
         center: true, //是否居中定位
         zIndex: 10,
         zIndex: 10,
         data: { ids },
         data: { ids },
-      }
-      this.dealMultiDialogConfig = dialogConfig
+      };
+      this.dealMultiDialogConfig = dialogConfig;
     },
     },
     handleConfirmMulti() {
     handleConfirmMulti() {
       // this.$confirm("确认退出该系统?", "提示", {
       // this.$confirm("确认退出该系统?", "提示", {
@@ -613,22 +787,22 @@ export default {
       //   window.location.reload();
       //   window.location.reload();
       // });
       // });
       let ids = this.tableConfig.tableData.map((obj, index) => {
       let ids = this.tableConfig.tableData.map((obj, index) => {
-        return obj.id
-      })
+        return obj.id;
+      });
       let dialogConfig = {
       let dialogConfig = {
-        dialogId: 'confirmMultiDialog',
+        dialogId: "confirmMultiDialog",
         show: true, //是否显示
         show: true, //是否显示
-        title: '批量确认',
+        title: "批量确认",
         width: 500, //px宽度
         width: 500, //px宽度
         height: 320, //px高度
         height: 320, //px高度
         center: true, //是否居中定位
         center: true, //是否居中定位
         zIndex: 10,
         zIndex: 10,
         data: { ids },
         data: { ids },
-      }
-      this.confirmMultiDialogConfig = dialogConfig
+      };
+      this.confirmMultiDialogConfig = dialogConfig;
     },
     },
   },
   },
-}
+};
 </script>
 </script>
 <style lang="less" scoped>
 <style lang="less" scoped>
 .alarmList-container {
 .alarmList-container {

+ 2 - 2
src/views/basePage/components/layerControl/index.vue

@@ -221,7 +221,7 @@ export default {
     },
     },
     switchConfig: {
     switchConfig: {
       handler(newVal) {
       handler(newVal) {
-        console.log("Infomation", newVal);
+        // console.log("Infomation", newVal);
       },
       },
     },
     },
     switchConfigShow: {
     switchConfigShow: {
@@ -452,7 +452,7 @@ export default {
           buildId: this.buildInfo?.positioningBuildId,
           buildId: this.buildInfo?.positioningBuildId,
           riskLevelArray: ["306001", "306002", "306003", "306004"],
           riskLevelArray: ["306001", "306002", "306003", "306004"],
         });
         });
-        console.log("FXQYInfomation", res);
+        // console.log("FXQYInfomation", res);
         let tempdata = res.data.content;
         let tempdata = res.data.content;
         let fxqyList = new Array();
         let fxqyList = new Array();
         if (show) {
         if (show) {

+ 16 - 0
src/views/basePage/index.vue

@@ -126,6 +126,13 @@
         <risk-hint />
         <risk-hint />
       </div>
       </div>
     </transition>
     </transition>
+    <!-- 中右侧面板 -->
+    <transition
+      enter-active-class="animated fadeInRight"
+      leave-active-class="animated fadeOutRight"
+    >
+      <fold :positionFold="position" @position="getPosition" />
+    </transition>
     <!-- 右侧面板 -->
     <!-- 右侧面板 -->
     <transition
     <transition
       enter-active-class="animated fadeInRight"
       enter-active-class="animated fadeInRight"
@@ -185,6 +192,7 @@ import {
   ModelViewToolbarDialog,
   ModelViewToolbarDialog,
   AlarmMapDialog,
   AlarmMapDialog,
 } from "./components/dialog/index";
 } from "./components/dialog/index";
+import Fold from "./panels/Fold";
 import Overview from "./panels/Overview";
 import Overview from "./panels/Overview";
 import RiskStatistics from "./panels/RiskStatistics";
 import RiskStatistics from "./panels/RiskStatistics";
 import RiskHint from "./panels/RiskHint";
 import RiskHint from "./panels/RiskHint";
@@ -212,6 +220,10 @@ export default {
       },
       },
       alarmLiveData: [],
       alarmLiveData: [],
       fullScreen: false,
       fullScreen: false,
+      position: {
+        isopen: true,
+        issprh: false,
+      },
     };
     };
   },
   },
   components: {
   components: {
@@ -234,6 +246,7 @@ export default {
     ModelViewToolbarDialog,
     ModelViewToolbarDialog,
     AlarmMapDialog,
     AlarmMapDialog,
     // ...comObj,
     // ...comObj,
+    Fold,
     Overview,
     Overview,
     RiskStatistics,
     RiskStatistics,
     RiskHint,
     RiskHint,
@@ -341,6 +354,9 @@ export default {
     this.$store.dispatch("globalConfig/clearSwitchConfig");
     this.$store.dispatch("globalConfig/clearSwitchConfig");
   },
   },
   methods: {
   methods: {
+    getPosition(data) {
+      this.position = data;
+    },
     openDialog,
     openDialog,
     setMapMode(newValue) {
     setMapMode(newValue) {
       console.log(newValue.value);
       console.log(newValue.value);

+ 3 - 3
src/views/basePage/mixins/LoadBuilding/LoadBuilding.js

@@ -19,7 +19,7 @@ import {
   PropertyBag,
   PropertyBag,
 } from 'cesium'
 } from 'cesium'
 import { getViewer } from '@/store/map/mapService'
 import { getViewer } from '@/store/map/mapService'
-import { addNewDatasource, openLayer } from '@/utils/mapUtil'
+import { addNewDatasource, openLayer, flyToPerspective } from '@/utils/mapUtil'
 import { getBuildModelList } from '@/API/model'
 import { getBuildModelList } from '@/API/model'
 import PolylineTrailLinkMaterialProperty from '@/assets/materials/PolylineTrailLinkMaterialProperty'
 import PolylineTrailLinkMaterialProperty from '@/assets/materials/PolylineTrailLinkMaterialProperty'
 // 贵阳市政府坐标  106.62597399249091 26.650868710810908  106.62662793866369 26.650351612695246
 // 贵阳市政府坐标  106.62597399249091 26.650868710810908  106.62662793866369 26.650351612695246
@@ -120,7 +120,7 @@ export default {
           this.addBuild(val)
           this.addBuild(val)
           // this.addBaseImage()
           // this.addBaseImage()
           this.zoomToModel()
           this.zoomToModel()
-        }, 1000)
+        }, 500)
       },
       },
       immediate: true,
       immediate: true,
     },
     },
@@ -426,7 +426,7 @@ export default {
       } = this.buildInfo
       } = this.buildInfo
       if (!!perspective) {
       if (!!perspective) {
         console.log('加载初始相机视角')
         console.log('加载初始相机视角')
-        this.flyToPerspective(perspective)
+        flyToPerspective(perspective)
       } else {
       } else {
         console.log('未设置初始相机视角')
         console.log('未设置初始相机视角')
         //按照sysbuild中两点进行飞行
         //按照sysbuild中两点进行飞行

+ 1 - 1
src/views/basePage/mixins/LoadBuilding/LoadLayer.js

@@ -46,7 +46,7 @@ export default {
         for (let item of this.layerData) {
         for (let item of this.layerData) {
           const res = await getElementList({ id: item.id });
           const res = await getElementList({ id: item.id });
           const content = res.data.content;
           const content = res.data.content;
-          console.log("Element", content)
+          // console.log("Element", content)
           content.forEach((d) => {
           content.forEach((d) => {
             d.GPSPoints = this.transPosition(d.pointList);
             d.GPSPoints = this.transPosition(d.pointList);
           });
           });

+ 19 - 15
src/views/basePage/mixins/LoadLayer/JGYT.js

@@ -136,7 +136,7 @@ export default {
       }
       }
     },
     },
     async getJGYTTagsData() {
     async getJGYTTagsData() {
-      console.log("建筑信息", this.buildInfo)
+      // console.log("建筑信息", this.buildInfo)
       try {
       try {
         let p = { buildId: this.buildInfo.positioningBuildId }
         let p = { buildId: this.buildInfo.positioningBuildId }
 
 
@@ -196,17 +196,21 @@ export default {
       }
       }
     },
     },
     async pushJGYTStatus(data) {
     async pushJGYTStatus(data) {
-      if (!data) return
-      if (data?.buildId === this.buildInfo.positioningBuildId) {
-        this.animationJGYT(data)
+      if (data.alarmType > 0) {
+        if (!data) return
+        if (data?.buildId === this.buildInfo.positioningBuildId) {
+          this.animationJGYT(data)
+        } else {
+          const curStation = GY_STATIONS.find(e => e.positioningBuildId === data.buildId)
+          if (!curStation) return
+          this.$store.dispatch('globalConfig/setMapMode', {
+            value: '3d',
+          })
+          await this.$store.dispatch('model/setBuildInfoByBuildId', curStation.buildId)
+          this.animationJGYT(data)
+        }
       } else {
       } else {
-        const curStation = GY_STATIONS.find(e => e.positioningBuildId === data.buildId)
-        if (!curStation) return
-        this.$store.dispatch('globalConfig/setMapMode', {
-          value: '3d',
-        })
-        await this.$store.dispatch('model/setBuildInfoByBuildId', curStation.buildId)
-        this.animationJGYT(data)
+        // this.animationJGYT(data)
       }
       }
     },
     },
     animationJGYT(data) {
     animationJGYT(data) {
@@ -236,7 +240,7 @@ export default {
               return tag
               return tag
             }),
             }),
           })
           })
-        }, 2000)
+        }, 1000)
       } else {
       } else {
         entity1.show = false
         entity1.show = false
         entity2.show = false
         entity2.show = false
@@ -253,9 +257,9 @@ export default {
         if (cameraId) {
         if (cameraId) {
           this.$store.dispatch('dialog/closeVideoDialog', cameraId)
           this.$store.dispatch('dialog/closeVideoDialog', cameraId)
         }
         }
-        setTimeout(() => {
-          flyToPerspective(this.buildInfo?.perspective)
-        }, 1000)
+        // setTimeout(() => {
+        flyToPerspective(this.buildInfo?.perspective)
+        // }, 1000)
       }
       }
     },
     },
     addJGYTTags() {
     addJGYTTags() {

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

@@ -199,7 +199,7 @@ export default {
           }, 2000)
           }, 2000)
         }
         }
       } else {
       } else {
-        this.animationPerimeter(data)
+        // this.animationPerimeter(data)
       }
       }
     },
     },
     animationPerimeter(data) {
     animationPerimeter(data) {

+ 1 - 1
src/views/basePage/mixins/MapEvent.js

@@ -121,7 +121,7 @@ export default {
               //打开站点模型
               //打开站点模型
               console.log(data)
               console.log(data)
               this.$store.dispatch('model/setBuildInfoByBuildId', data.buildId)
               this.$store.dispatch('model/setBuildInfoByBuildId', data.buildId)
-              this.$store.dispatch('globalConfig/setMapMode', { value: '3d' })
+              // this.$store.dispatch('globalConfig/setMapMode', { value: '3d' })
             }
             }
             //点击了建筑名称,打开建筑内人员情况
             //点击了建筑名称,打开建筑内人员情况
             else if (type === 'buildingPerson') {
             else if (type === 'buildingPerson') {

+ 119 - 0
src/views/basePage/panels/Fold.vue

@@ -0,0 +1,119 @@
+<template>
+  <div class="fold transition">
+    <div
+      class="openFold"
+      :class="[mapMode.value === 'home' ? 'isno' : 'isyes']"
+      @click="clickOpen"
+    >
+      <span>
+        {{ mapMode.value === "home" ? "收起面板" : "展开面板" }}
+      </span>
+    </div>
+  </div>
+</template>
+<script>
+import { mapGetters } from "vuex";
+export default {
+  props: { positionFold: Object },
+  data() {
+    return {
+      position: {
+        left: 490,
+        right: 490,
+        isopen: true,
+        issprh: false,
+      },
+    };
+  },
+  computed: {
+    ...mapGetters(["mapMode"]),
+  },
+  watch: {
+    mapMode: {
+      handler(val, oldVal) {
+        // console.log("mapMode", val.value, oldVal.value);
+        this.updateStyle();
+      },
+      deep: true,
+    },
+  },
+  methods: {
+    updateStyle() {
+      this.position.isopen = !this.position.isopen;
+      if (this.mapMode.value === "home") {
+        let main = document.querySelector(".fold");
+        main.style.transform = `translateX(0px)`;
+        main.style.transition = "transform 1s ease";
+      } else {
+        let main = document.querySelector(".fold");
+        main.style.transform = `translateX(470px)`;
+        main.style.transition = "transform 1s ease";
+      }
+      var param = {
+        isopen: this.position.isopen,
+        issprh: this.position.issprh,
+      };
+      this.$emit("position", param);
+    },
+    clickOpen() {
+      if (this.mapMode) {
+        if (this.mapMode.value === "home") {
+          this.$store.dispatch("globalConfig/setMapMode", { value: "3d" });
+        } else if (this.mapMode.value === "3d") {
+          this.$store.dispatch("globalConfig/setMapMode", { value: "home" });
+        }
+      }
+    },
+  },
+  mounted() {
+    this.position = this.positionFold;
+    if (this.mapMode.value === "home") {
+      let main = document.querySelector(".fold");
+      main.style.transform = `translateX(0px)`;
+      main.style.transition = "transform 1s ease";
+    } else {
+      let main = document.querySelector(".fold");
+      main.style.transform = `translateX(470px)`;
+      main.style.transition = "transform 1s ease";
+    }
+  },
+  updated() {
+    this.position = this.positionFold;
+  },
+};
+</script>
+<style lang="less" scoped>
+.fold {
+  position: absolute;
+  z-index: 99;
+  width: 140px;
+  // height: 200px;
+  top: 106px;
+  right: 450px;
+  //   background: #000;
+  .openFold {
+    pointer-events: auto;
+    cursor: pointer;
+    width: 140px;
+    height: 45px;
+    background-repeat: no-repeat;
+    background-size: cover;
+    text-align: center;
+    line-height: 45px;
+    span {
+      font-size: 14px;
+      font-weight: 700;
+      background-image: linear-gradient(180deg, #ffffff, #419aff);
+      -webkit-background-clip: text;
+      background-clip: text;
+      color: transparent;
+    }
+  }
+}
+.isno {
+  background-image: url(~@/assets/imgs/fold/button_收起面板_sel.png);
+}
+.isyes {
+  background-image: url(~@/assets/imgs/fold/button_收起面板_pre.png);
+}
+</style>

+ 113 - 76
src/views/basePage/panels/IntelligentVideo/index.vue

@@ -16,178 +16,215 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import BaseTitle from '../BaseTitle.vue'
-import VideoWindow from './videoWindow.vue'
+import { divide } from "lodash-es";
+import BaseTitle from "../BaseTitle.vue";
+import VideoWindow from "./videoWindow.vue";
+import { mapGetters } from "vuex";
 export default {
 export default {
-  name: 'IntelligentVideo',
+  name: "IntelligentVideo",
   components: { BaseTitle, VideoWindow },
   components: { BaseTitle, VideoWindow },
   data() {
   data() {
     return {
     return {
       videoData: {
       videoData: {
-        id: '593102253968072704',
-        name: '吴圩站',
-        type: 'wxz',
+        id: "593102253968072704",
+        name: "吴圩站",
+        type: "wxz",
         ptzEnable: true,
         ptzEnable: true,
-        tags: { ndTag: 'ND', gqTag: 'GQ' },
+        tags: { ndTag: "ND", gqTag: "GQ" },
       },
       },
       curStation: {},
       curStation: {},
       stationList: [
       stationList: [
         //初始化泄漏报警骨架
         //初始化泄漏报警骨架
         {
         {
-          id: '1',
-          name: '贵阳作业区',
+          id: "1",
+          name: "贵阳作业区",
           children: [
           children: [
             {
             {
-              id: '101',
-              name: '贵阳站',
+              id: "101",
+              name: "贵阳站",
               children: [
               children: [
                 {
                 {
-                  id: '1',
-                  name: '云台1',
-                  ndTag: 'ND',
+                  id: "1",
+                  name: "云台1",
+                  ndTag: "ND",
                 },
                 },
                 {
                 {
-                  id: '2',
-                  name: '云台2',
-                  ndTag: 'ND',
+                  id: "2",
+                  name: "云台2",
+                  ndTag: "ND",
                 },
                 },
                 {
                 {
-                  id: '3',
-                  name: '云台3',
-                  ndTag: 'ND',
+                  id: "3",
+                  name: "云台3",
+                  ndTag: "ND",
                 },
                 },
               ],
               ],
             },
             },
             {
             {
-              id: '102',
-              name: '白云站',
+              id: "102",
+              name: "白云站",
               children: [
               children: [
                 {
                 {
-                  id: '4',
-                  name: '云台1',
-                  ndTag: 'ND',
+                  id: "4",
+                  name: "云台1",
+                  ndTag: "ND",
                 },
                 },
               ],
               ],
             },
             },
           ],
           ],
         },
         },
         {
         {
-          id: '2',
-          name: '都匀作业区',
+          id: "2",
+          name: "都匀作业区",
           children: [
           children: [
             {
             {
-              id: '201',
-              name: '都匀站',
+              id: "201",
+              name: "都匀站",
               children: [
               children: [
                 {
                 {
-                  id: '20101',
-                  name: '云台1',
+                  id: "20101",
+                  name: "云台1",
                 },
                 },
               ],
               ],
             },
             },
             {
             {
-              id: '202',
-              name: '独山首站',
+              id: "202",
+              name: "独山首站",
               children: [
               children: [
                 {
                 {
-                  id: '20201',
-                  name: '云台1',
+                  id: "20201",
+                  name: "云台1",
                 },
                 },
                 {
                 {
-                  id: '20202',
-                  name: '云台2',
+                  id: "20202",
+                  name: "云台2",
                 },
                 },
               ],
               ],
             },
             },
             {
             {
-              id: '203',
-              name: '凯口站',
+              id: "203",
+              name: "凯口站",
               children: [
               children: [
                 {
                 {
-                  id: '20301',
-                  name: '云台1',
+                  id: "20301",
+                  name: "云台1",
                 },
                 },
               ],
               ],
             },
             },
             {
             {
-              id: '204',
-              name: '云雾首站',
+              id: "204",
+              name: "云雾首站",
               children: [
               children: [
                 {
                 {
-                  id: '20401',
-                  name: '云台1',
+                  id: "20401",
+                  name: "云台1",
                 },
                 },
               ],
               ],
             },
             },
           ],
           ],
         },
         },
       ],
       ],
-    }
+      list: [],
+      dId: "",
+    };
   },
   },
   computed: {
   computed: {
+    ...mapGetters(["departmentId"]),
     topData() {
     topData() {
-      let arr = []
-      let leng = this.curStation?.children?.length || 0
+      let arr = [];
+      let leng = this.curStation?.children?.length || 0;
       if (leng === 0) {
       if (leng === 0) {
-        arr = []
+        arr = [];
       }
       }
       // 一个的时候只显示上半部分,下半隐藏
       // 一个的时候只显示上半部分,下半隐藏
       // 两个的时候,上下都显示
       // 两个的时候,上下都显示
       else if (leng <= 2) {
       else if (leng <= 2) {
-        arr = [this.curStation.children[0]]
+        arr = [this.curStation.children[0]];
       }
       }
       // 大于2个的时候,上面左右结构,下面显示其余
       // 大于2个的时候,上面左右结构,下面显示其余
       else {
       else {
-        arr = [this.curStation.children[0], this.curStation.children[1]]
+        arr = [this.curStation.children[0], this.curStation.children[1]];
       }
       }
-      return arr
+      return arr;
     },
     },
     bottomData() {
     bottomData() {
-      let arr = []
-      let leng = this.curStation?.children?.length || 0
+      let arr = [];
+      let leng = this.curStation?.children?.length || 0;
       if (leng <= 1) {
       if (leng <= 1) {
         // 一个的时候只显示上半部分,下半隐藏
         // 一个的时候只显示上半部分,下半隐藏
-        arr = []
+        arr = [];
       }
       }
       // 两个的时候,上下各显示一个
       // 两个的时候,上下各显示一个
       else if (leng == 2) {
       else if (leng == 2) {
-        arr = [this.curStation.children[1]]
+        arr = [this.curStation.children[1]];
       }
       }
       // 大于两个,上面显示两个,下面显示其余
       // 大于两个,上面显示两个,下面显示其余
       else {
       else {
-        arr = this.curStation.children.slice(2)
+        arr = this.curStation.children.slice(2);
       }
       }
-      return arr
+      return arr;
     },
     },
   },
   },
   created() {
   created() {
-    this.stationList = GY_JGYT_CONFIG
-    this.curStation = this.getCurStation('1')
-    console.log('curStation', this.curStation)
+    this.init();
+  },
+  watch: {
+    departmentId(newVal) {
+      console.log("部门id信息", newVal, this.list);
+      this.dId = newVal;
+      if (this.dId === "") {
+        this.init();
+      } else {
+        setTimeout(() => {
+          for (let i = 0; i < this.list[0].children.length; i++) {
+            const e = this.list[0].children[i];
+            if (e.departmentId === this.dId) {
+              this.stationList[0].children = [this.list[0].children[i]];
+            }
+          }
+          this.curStation = this.getCurStation("1");
+        }, 200);
+      }
+      console.log("场站云台列表", this.stationList);
+    },
   },
   },
   methods: {
   methods: {
+    init() {
+      this.list = GY_JGYT_CONFIG;
+      if (this.list.length > 0) {
+        this.stationList = [
+          {
+            id: this.list[0].id,
+            name: this.list[0].name,
+            children: [this.list[0].children[0]],
+          },
+        ];
+      }
+      this.curStation = this.getCurStation("1");
+      console.log("curStation", this.curStation);
+    },
     getCurStation(id) {
     getCurStation(id) {
-      let obj = {}
-      const find = arr => {
-        arr.forEach(item => {
+      let obj = {};
+      const find = (arr) => {
+        arr.forEach((item) => {
           if (item.id === id) {
           if (item.id === id) {
-            obj.id = item.id
-            obj.name = item.name
-            obj.type = item.type
-            obj.ptzEnable = item.ptzEnable
-            obj.tags = item.tags
-            obj.children = item.children
+            obj.id = item.id;
+            obj.name = item.name;
+            obj.type = item.type;
+            obj.ptzEnable = item.ptzEnable;
+            obj.tags = item.tags;
+            obj.children = item.children;
           } else if (item.children && item.children.length) {
           } else if (item.children && item.children.length) {
-            find(item.children)
+            find(item.children);
           }
           }
-        })
-      }
+        });
+      };
 
 
-      find(this.stationList)
-      return obj
+      find(this.stationList);
+      return obj;
     },
     },
   },
   },
-}
+};
 </script>
 </script>
 
 
 <style lang="less" scoped>
 <style lang="less" scoped>

+ 52 - 0
src/views/basePage/panels/Overview.vue

@@ -33,6 +33,9 @@
 
 
 <script>
 <script>
 import BaseTitle from "./BaseTitle.vue";
 import BaseTitle from "./BaseTitle.vue";
+import Dayjs from "dayjs";
+import { getAlarmDataList } from "@/API/alarm";
+import { mapGetters } from "vuex";
 export default {
 export default {
   name: "Overview",
   name: "Overview",
   components: { BaseTitle },
   components: { BaseTitle },
@@ -115,11 +118,25 @@ export default {
         //   level: "024000",
         //   level: "024000",
         // },
         // },
       },
       },
+      dId: "",
     };
     };
   },
   },
+  computed: {
+    ...mapGetters(["departmentId"]),
+  },
   mounted() {
   mounted() {
+    this.getAlarmDataList();
     // this.startMqtt();
     // this.startMqtt();
   },
   },
+  watch: {
+    departmentId(newVal) {
+      console.log("部门id信息", newVal);
+      this.dId = newVal;
+      setTimeout(() => {
+        this.getAlarmDataList();
+      }, 200);
+    },
+  },
   methods: {
   methods: {
     startMqtt() {
     startMqtt() {
       const topics = [
       const topics = [
@@ -190,6 +207,7 @@ export default {
         dateRange: "24H",
         dateRange: "24H",
         dealStatus,
         dealStatus,
         confirmStatus,
         confirmStatus,
+        departmentId: this.dId,
       };
       };
       const query = JSON.stringify(p)
       const query = JSON.stringify(p)
         .replace("{", "")
         .replace("{", "")
@@ -203,6 +221,40 @@ export default {
 
 
       this.$router.push("/alarmlist?" + query);
       this.$router.push("/alarmlist?" + query);
     },
     },
+
+    async getAlarmDataList() {
+      try {
+        const params = {
+          pageSize: 1000,
+          pageIndex: 1,
+          dealStatus: "", //0
+          confirmStatus: "",
+          recoveryStatus: "",
+          category: "",
+          level: "",
+          type: "",
+          startTime: Dayjs(
+            Dayjs(new Date()).subtract(1, "day").format("YYYY-MM-DD HH:mm:ss")
+          ).format(),
+          endTime: Dayjs(
+            Dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")
+          ).format(),
+          key: "",
+          tag: "",
+          departmentId: this.dId ? this.dId : "",
+        };
+        const res = await getAlarmDataList(params);
+        let alarmData = res.data.content;
+        this.todayTotalData[0].total = alarmData.filter(
+          (e) => e.dealStatus === 0
+        ).length; //未处理
+        this.todayTotalData[1].total = alarmData ? alarmData.length : 0; //总数
+        this.todayTotalData[2].total = alarmData.filter(
+          (e) => e.confirmStatus === 0
+        ).length; //未确认
+        // console.log("统计报警数据", alarmData);
+      } catch (err) {}
+    },
   },
   },
 };
 };
 </script>
 </script>

+ 56 - 2
src/views/basePage/panels/RiskHint.vue

@@ -44,6 +44,8 @@
 import BaseTitle from "./BaseTitle.vue";
 import BaseTitle from "./BaseTitle.vue";
 import VueSeamless from "vue-seamless-scroll";
 import VueSeamless from "vue-seamless-scroll";
 import Dayjs from "dayjs";
 import Dayjs from "dayjs";
+import { getAlarmDataList } from "@/API/alarm";
+import { mapGetters } from "vuex";
 export default {
 export default {
   name: "",
   name: "",
   components: { BaseTitle, VueSeamless },
   components: { BaseTitle, VueSeamless },
@@ -60,12 +62,15 @@ export default {
         singleHeight: 78,
         singleHeight: 78,
         waitTime: 2000,
         waitTime: 2000,
       },
       },
-
+      dId: "",
       riskColors: {
       riskColors: {
         ["306001"]: { name: "重大级别", color: "#FF3636" },
         ["306001"]: { name: "重大级别", color: "#FF3636" },
         ["306002"]: { name: "较大级别", color: "#FF9F00" },
         ["306002"]: { name: "较大级别", color: "#FF9F00" },
         ["306003"]: { name: "一般级别", color: "#F8E71C" },
         ["306003"]: { name: "一般级别", color: "#F8E71C" },
         ["306004"]: { name: "低级别", color: "#53A3FF" },
         ["306004"]: { name: "低级别", color: "#53A3FF" },
+        ["024001"]: { name: "较大级别", color: "#FF9F00" },
+        ["024002"]: { name: "一般级别", color: "#F8E71C" },
+        ["024003"]: { name: "低级别", color: "#53A3FF" },
       },
       },
       hintData1: [
       hintData1: [
         {
         {
@@ -95,12 +100,61 @@ export default {
       ],
       ],
     };
     };
   },
   },
-  computed: {},
+  computed: {
+    ...mapGetters(["departmentId"]),
+  },
   mounted() {
   mounted() {
+    this.getAlarmDataList();
     this.startMqtt();
     this.startMqtt();
   },
   },
+  watch: {
+    departmentId(newVal) {
+      console.log("部门id信息", newVal);
+      this.dId = newVal;
+      setTimeout(() => {
+        this.getAlarmDataList();
+      }, 200);
+    },
+  },
   methods: {
   methods: {
     Dayjs,
     Dayjs,
+    async getAlarmDataList() {
+      try {
+        const params = {
+          pageSize: 10,
+          pageIndex: 1,
+          dealStatus: "", //0
+          confirmStatus: "",
+          recoveryStatus: "",
+          category: "",
+          level: "",
+          type: "",
+          startTime: Dayjs(
+            Dayjs(new Date()).subtract(1, "month").format("YYYY-MM-DD HH:mm:ss")
+          ).format(),
+          endTime: Dayjs(
+            Dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss")
+          ).format(),
+          key: "",
+          tag: "",
+          departmentId: this.dId,
+        };
+        const res = await getAlarmDataList(params);
+        let alarmData = res.data.content;
+        this.hintData1 = alarmData.map((e) => {
+          return {
+            id: e.id,
+            level: e.level ? e.level : "024003",
+            riskTime: e.eventTime,
+            content:
+              (e.departmentName ? e.departmentName : "") +
+              (e.categoryStr ? e.categoryStr : "") +
+              e.content,
+          };
+        });
+        // console.log("风险报警数据", alarmData, this.hintData1);
+      } catch (err) {}
+    },
     openRiskDialog(data) {
     openRiskDialog(data) {
       console.log(data);
       console.log(data);
       let dialogConfig = {
       let dialogConfig = {

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

@@ -26,20 +26,20 @@ export default {
   data() {
   data() {
     return {
     return {
       searchType: "1",
       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: {
       // levelTrendData: {
-      //   name: [],
+      //   name: ["11.30", "12.1", "12.2", "12.3", "12.4", "12.5", "12.6"],
       //   legend: ["一级", "二级", "三级"],
       //   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: [],
+      },
     };
     };
   },
   },
 
 
@@ -65,7 +65,7 @@ export default {
           const content = message.toString();
           const content = message.toString();
           const data = JSON.parse(content);
           const data = JSON.parse(content);
           if (topic === "Visualization/Number/RecentlyLevelByDate") {
           if (topic === "Visualization/Number/RecentlyLevelByDate") {
-            console.log(data);
+            // console.log(data);
             this.levelTrendData.length = 0;
             this.levelTrendData.length = 0;
             this.levelTrendData.name = data.name;
             this.levelTrendData.name = data.name;
             this.levelTrendData.legend.forEach((item, index) => {
             this.levelTrendData.legend.forEach((item, index) => {
@@ -75,7 +75,7 @@ export default {
                 })
                 })
               );
               );
             });
             });
-            console.log("风险统计数据", this.levelTrendData.data);
+            // console.log("风险统计数据", this.levelTrendData.data);
           }
           }
         },
         },
       });
       });

+ 83 - 26
src/views/components/baseFooter/FooterNavigation.vue

@@ -22,7 +22,7 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import { getFooterNavigationList } from '@/API/visual';
+import { getFooterNavigationList } from "@/API/visual";
 import {
 import {
   flyToPerspective,
   flyToPerspective,
   setModelShow,
   setModelShow,
@@ -31,10 +31,12 @@ import {
   openDialog,
   openDialog,
   setUnderPipeline,
   setUnderPipeline,
   setUndergroundMode,
   setUndergroundMode,
-} from '@/utils/mapUtil.js';
+  setBuildId,
+  setBuildInfoByBuildId,
+} from "@/utils/mapUtil.js";
 
 
 export default {
 export default {
-  name: 'FooterNavigation',
+  name: "FooterNavigation",
   data() {
   data() {
     return {
     return {
       btnSel: -1,
       btnSel: -1,
@@ -42,63 +44,63 @@ export default {
       btnList1: [
       btnList1: [
         {
         {
           id: 1,
           id: 1,
-          icon: '/imgs/footerNavigation/icon_RY_nor@2x.png',
-          iconNor: '/imgs/footerNavigation/icon_RY_nor@2x.png',
-          iconSel: '/imgs/footerNavigation/icon_RY_sel@2x.png',
-          text: '按钮',
-          script: 'alert(111)',
-          left: 'calc(50% - 74px)',
+          icon: "/imgs/footerNavigation/icon_RY_nor@2x.png",
+          iconNor: "/imgs/footerNavigation/icon_RY_nor@2x.png",
+          iconSel: "/imgs/footerNavigation/icon_RY_sel@2x.png",
+          text: "按钮",
+          script: "alert(111)",
+          left: "calc(50% - 74px)",
           level: 0,
           level: 0,
         },
         },
       ],
       ],
 
 
       btnPositionList: [
       btnPositionList: [
         {
         {
-          left: 'calc(50% - 74px)',
+          left: "calc(50% - 74px)",
           level: 0,
           level: 0,
         },
         },
         {
         {
-          left: 'calc(50% + 13px)',
+          left: "calc(50% + 13px)",
           level: 0,
           level: 0,
         },
         },
         {
         {
-          left: 'calc(50% - 161px)',
+          left: "calc(50% - 161px)",
           level: 1,
           level: 1,
         },
         },
         {
         {
-          left: 'calc(50% + 100px)',
+          left: "calc(50% + 100px)",
           level: 1,
           level: 1,
         },
         },
         {
         {
-          left: 'calc(50% - 248px)',
+          left: "calc(50% - 248px)",
           level: 2,
           level: 2,
         },
         },
         {
         {
-          left: 'calc(50% + 187px)',
+          left: "calc(50% + 187px)",
           level: 2,
           level: 2,
         },
         },
         {
         {
-          left: 'calc(50% - 335px)',
+          left: "calc(50% - 335px)",
           level: 3,
           level: 3,
         },
         },
         {
         {
-          left: 'calc(50% + 274px)',
+          left: "calc(50% + 274px)",
           level: 3,
           level: 3,
         },
         },
         {
         {
-          left: 'calc(50% - 422px)',
+          left: "calc(50% - 422px)",
           level: 4,
           level: 4,
         },
         },
         {
         {
-          left: 'calc(50% + 361px)',
+          left: "calc(50% + 361px)",
           level: 4,
           level: 4,
         },
         },
         {
         {
-          left: 'calc(50% - 509px)',
+          left: "calc(50% - 509px)",
           level: 5,
           level: 5,
         },
         },
         {
         {
-          left: 'calc(50% + 448px)',
+          left: "calc(50% + 448px)",
           level: 5,
           level: 5,
         },
         },
       ],
       ],
@@ -115,11 +117,31 @@ export default {
     openDialog,
     openDialog,
     setUnderPipeline,
     setUnderPipeline,
     setUndergroundMode,
     setUndergroundMode,
+    setBuildId,
+    setBuildInfoByBuildId,
+    initMap() {
+      this.setBuildId("");
+      this.jumpRoute("/basePage", { buildId: "654044537953460225" });
+      setTimeout(() => {
+        this.setBuildInfoByBuildId("654044537953460225");
+      }, 500);
+    },
+    jumpRoute(path, param) {
+      if (!path) return;
+      let route = { path: path };
+      if (param) {
+        // if (path === "/page2" && !!param.path) param.path = decodeURIComponent(param.path);
+        if (!!param.path) param.path = decodeURIComponent(param.path);
+
+        route["query"] = { ...param };
+      }
+      this.$router.push(route);
+    },
     async getNavigationList() {
     async getNavigationList() {
       try {
       try {
         const p = {};
         const p = {};
         const res = await getFooterNavigationList(p);
         const res = await getFooterNavigationList(p);
-        console.log("底部菜单",res.data);
+        // console.log("底部菜单", res.data);
         res.data.content.forEach((item, index) => {
         res.data.content.forEach((item, index) => {
           const btn = {
           const btn = {
             id: item.id,
             id: item.id,
@@ -135,7 +157,8 @@ export default {
           item.level = this.btnPositionList[index].level;
           item.level = this.btnPositionList[index].level;
           this.btnList.push(btn);
           this.btnList.push(btn);
         });
         });
-        console.log(this.btnList);
+        // this.initMap(); //都匀加载驾驶舱模型//托克托不需要
+        // console.log(this.btnList, "按钮列表");
       } catch (err) {
       } catch (err) {
         console.log(err);
         console.log(err);
       }
       }
@@ -165,10 +188,44 @@ export default {
       }
       }
     },
     },
     toDefaultView() {
     toDefaultView() {
-      this.$store.dispatch('globalConfig/setMapMode', {
-        value: '3d',
+      this.$store.dispatch("globalConfig/setMapMode", {
+        value: "3d",
       });
       });
     },
     },
+    openFooterDialog(type) {
+      if (type) {
+        switch (type) {
+          case "防爆扩音":
+            console.log("防爆扩音");
+            this.$store.dispatch("globalConfig/setSoundDialog", {
+              show: true,
+              dialogMsg: {},
+              type: "All",
+            });
+            break;
+          case "出入控制":
+            console.log("出入控制");
+            this.$store.dispatch("globalConfig/setAccessControlDialog", {
+              show: true,
+              dialogMsg: {},
+              type: "All",
+            });
+            break;
+          case "激光云台":
+            console.log("激光云台");
+            this.$store.dispatch("globalConfig/setJGYTControlDialog", {
+              show: true,
+              dialogMsg: {},
+              type: "All",
+            });
+            break;
+
+          default:
+            break;
+        }
+      }
+      // this.getTestList();
+    },
   },
   },
 };
 };
 </script>
 </script>
@@ -200,7 +257,7 @@ export default {
     position: absolute;
     position: absolute;
     background-size: 100% 100%;
     background-size: 100% 100%;
     background-repeat: no-repeat;
     background-repeat: no-repeat;
-    background-image: url('/imgs/footerNavigation/buttn_GKPT.png');
+    // background-image: url("/imgs/footerNavigation/buttn_GKPT.png");
     display: inline-block;
     display: inline-block;
     border: 0px solid rgb(0, 255, 136);
     border: 0px solid rgb(0, 255, 136);
     box-sizing: border-box;
     box-sizing: border-box;

+ 38 - 6
src/views/components/baseHeader/left.vue

@@ -45,6 +45,7 @@
     </div>
     </div>
     <div class="right-box">
     <div class="right-box">
       <div class="right_icon_box">
       <div class="right_icon_box">
+        <div class="name_box">{{ buildInfo.name }}</div>
         <div class="datetime_box">
         <div class="datetime_box">
           <div class="date" v-show="false">
           <div class="date" v-show="false">
             <div class="line_1">{{ datetimeData.date }}</div>
             <div class="line_1">{{ datetimeData.date }}</div>
@@ -76,12 +77,12 @@
             <el-dropdown-item @click.native="test3">
             <el-dropdown-item @click.native="test3">
               <span style="display: block">防爆扩音</span>
               <span style="display: block">防爆扩音</span>
             </el-dropdown-item>
             </el-dropdown-item>
-            <!-- <el-dropdown-item @click.native="test">
+            <el-dropdown-item @click.native="test">
               <span style="display: block">报警声音弹窗</span>
               <span style="display: block">报警声音弹窗</span>
             </el-dropdown-item>
             </el-dropdown-item>
             <el-dropdown-item @click.native="test1">
             <el-dropdown-item @click.native="test1">
               <span style="display: block">入场动画开关</span>
               <span style="display: block">入场动画开关</span>
-            </el-dropdown-item> -->
+            </el-dropdown-item>
             <el-dropdown-item @click.native="goToLogout">
             <el-dropdown-item @click.native="goToLogout">
               <span style="display: block">退出登录</span>
               <span style="display: block">退出登录</span>
             </el-dropdown-item>
             </el-dropdown-item>
@@ -93,6 +94,8 @@
 </template>
 </template>
 
 
 <script>
 <script>
+import md5 from "md5";
+import { getTestList } from "@/API/ddxt";
 import { mapGetters } from "vuex";
 import { mapGetters } from "vuex";
 import Dayjs from "dayjs";
 import Dayjs from "dayjs";
 import { getMenuList } from "@/API/visual";
 import { getMenuList } from "@/API/visual";
@@ -209,7 +212,13 @@ export default {
     };
     };
   },
   },
   computed: {
   computed: {
-    ...mapGetters(["alarmDataCount", "serverTime", "mapMode", "buildId"]), //"accessInfo", "pageSizeMode", "username", "userInfo",
+    ...mapGetters([
+      "alarmDataCount",
+      "serverTime",
+      "mapMode",
+      "buildId",
+      "buildInfo",
+    ]), //"accessInfo", "pageSizeMode", "username", "userInfo",
     safetyDays() {
     safetyDays() {
       const startTime = Dayjs("2024-03-28");
       const startTime = Dayjs("2024-03-28");
       const startDay = 6690;
       const startDay = 6690;
@@ -265,12 +274,21 @@ export default {
     setShouldAnimation,
     setShouldAnimation,
     test3() {
     test3() {
       console.log("防爆扩音");
       console.log("防爆扩音");
+      // this.getTestList();
       this.$store.dispatch("globalConfig/setSoundDialog", {
       this.$store.dispatch("globalConfig/setSoundDialog", {
         show: true,
         show: true,
         dialogMsg: {},
         dialogMsg: {},
         type: "All",
         type: "All",
       });
       });
     },
     },
+    async getTestList() {
+      try {
+        let p = {};
+        let res = await getTestList(p);
+      } catch (err) {
+        console.log(err);
+      }
+    },
     test2() {
     test2() {
       console.log("一键报警");
       console.log("一键报警");
       this.$store.dispatch("globalConfig/setOneKey110", {
       this.$store.dispatch("globalConfig/setOneKey110", {
@@ -321,11 +339,12 @@ export default {
       // }, 40000);
       // }, 40000);
     },
     },
     init() {
     init() {
+      this.setBuildId("");
       this.jumpRoute("/basePage", { buildId: "654044537953460225" });
       this.jumpRoute("/basePage", { buildId: "654044537953460225" });
       this.switchMode("home");
       this.switchMode("home");
       setTimeout(() => {
       setTimeout(() => {
         this.setBuildInfoByBuildId("654044537953460225");
         this.setBuildInfoByBuildId("654044537953460225");
-      }, 2000);
+      }, 1000);
     },
     },
     // async getSystemMenu() {
     // async getSystemMenu() {
     //   try {
     //   try {
@@ -427,7 +446,8 @@ export default {
         // this.navConfig.left = lMenu;
         // this.navConfig.left = lMenu;
         // this.navConfig.right = rMenu;
         // this.navConfig.right = rMenu;
         this.navConfig = lMenu.concat(rMenu);
         this.navConfig = lMenu.concat(rMenu);
-        // console.log("菜单信息", this.navConfig);
+        console.log("顶部菜单信息", this.navConfig);
+        this.init();
       } catch (err) {
       } catch (err) {
         console.log(err);
         console.log(err);
       }
       }
@@ -813,9 +833,21 @@ export default {
           margin-bottom: 6px;
           margin-bottom: 6px;
         }
         }
       }
       }
+      .name_box {
+        // background-image: url(~@/assets/imgs/header/nav_bg@2x.png);
+        width: 100px;
+        height: 40px;
+        padding-top: 14px;
+        font-family: MicrosoftYaHei;
+        font-size: 18px;
+        color: #dcedff;
+        letter-spacing: 0;
+        text-align: center;
+        font-weight: 260;
+      }
       .back_box {
       .back_box {
         img {
         img {
-          width: 35px;
+          width: 70px;
           height: 35px;
           height: 35px;
           cursor: pointer;
           cursor: pointer;
           pointer-events: auto;
           pointer-events: auto;

+ 523 - 0
src/views/components/dialog/AccessControlDialog.vue

@@ -0,0 +1,523 @@
+<template>
+  <base-drag-bg-dialog
+    :dialogConfig="baseDialogConfig"
+    @handleClose="closeDialog"
+  >
+    <!-- 弹窗内容 -->
+    <div class="dialog_box">
+      <!-- 内容 -->
+      <div>
+        <el-row class="access_video">
+          <el-col :span="8">
+            <div class="select">
+              <div class="select_title">
+                车辆识别1
+                <el-select
+                  value-key="id"
+                  v-model="cameraCarInfo1"
+                  style="width: 160px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择摄像头"
+                  @change="exchangeVideo(1, $event)"
+                >
+                  <el-option
+                    v-for="item in cameraCarList"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+            </div>
+            <div class="select_video">
+              <div class="select_video_main">
+                <video-image-window
+                  :cameraData="cameraCarInfo1"
+                  :cameraId="cameraCarInfo1.id"
+                />
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="8">
+            <div class="select">
+              <div class="select_title">
+                车辆识别2
+                <el-select
+                  value-key="id"
+                  v-model="cameraCarInfo2"
+                  style="width: 160px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择摄像头"
+                  @change="exchangeVideo(2, $event)"
+                >
+                  <el-option
+                    v-for="item in cameraCarList"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+            </div>
+            <div class="select_video">
+              <div class="select_video_main">
+                <video-image-window
+                  :cameraData="cameraCarInfo2"
+                  :cameraId="cameraCarInfo2.id"
+                />
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="8">
+            <div class="select">
+              <div class="select_title">
+                人脸识别
+                <el-select
+                  value-key="id"
+                  v-model="cameraFaceInfo"
+                  style="width: 160px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择摄像头"
+                  @change="exchangeVideo(3, $event)"
+                >
+                  <el-option
+                    v-for="item in cameraFaceList"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+            </div>
+            <div class="select_video">
+              <div class="select_video_main">
+                <video-image-window
+                  :cameraData="cameraFaceInfo"
+                  :cameraId="cameraFaceInfo.id"
+                />
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="8">
+            <div class="search-box">
+              <div class="search-item">
+                <span class="search-label">场站:</span>
+                <el-select
+                  value-key="id"
+                  v-model="department"
+                  style="width: 110px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择场站"
+                  @change="searchData($event)"
+                >
+                  <el-option
+                    v-for="item in departmentOptions"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+              <!-- <el-cascader
+                  v-model="query.departmentId"
+                  :options="departmentOptions"
+                  clearable
+                  size="mini"
+                  placeholder="请选择场站"
+                  style="width: 160px"
+                  @change="searchData()"
+                /> -->
+              <!-- <div class="search-btn2" @click="openAll">
+                <el-button size="mini" type="success">人员授权</el-button>
+              </div>
+              <div class="search-btn2" @click="closeAll">
+                <el-button size="mini" type="warning">车辆授权</el-button>
+              </div> -->
+              <!-- <div class="search-btn2" @click="openBroadcast">
+                <el-button size="mini" type="success">开门</el-button>
+              </div>
+              <div class="search-btn2" @click="closeBroadcast">
+                <el-button size="mini" type="danger">关门</el-button>
+              </div> -->
+            </div>
+            <div class="info_list">
+              <base-table-list
+                :tableConfig="tableConfig"
+                @handleClick="handleTableClick"
+              />
+            </div>
+          </el-col>
+          <el-col :span="16">
+            <div class="record_list">
+              <div class="record_title">出入门记录</div>
+              <div class="record_info">
+                <base-table-list :tableConfig="recordTableConfig" />
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+  </base-drag-bg-dialog>
+</template>
+<script>
+import BaseTableList from "@/views/components/base/BaseTableList";
+import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
+import VideoImageWindow from "@/views/components/dialog/VideoImageWindow.vue";
+import { dealAlarm } from "@/API/common";
+import { getDepartmentByPid } from "@/API/alarm";
+import { getAccessInfoList, getAccessLogList } from "@/API/accessControl";
+import { mapGetters } from "vuex";
+export default {
+  name: "accessControlDialog",
+  components: { BaseDragBgDialog, BaseTableList, VideoImageWindow },
+  watch: {
+    "accessControlDialog.show": {
+      handler(newVal) {
+        this.baseDialogConfig.show = newVal;
+      },
+      // deep: true,
+      immediate: true,
+    },
+    dataList: {
+      handler(newValue, oldValue) {
+        this.filterKey = "";
+        this.tableConfig.tableData = newValue;
+      },
+      deep: true,
+    },
+    recordList: {
+      handler(newValue, oldValue) {
+        this.filterKey = "";
+        this.recrodTableConfig.tableData = newValue;
+      },
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      BASE_URL,
+      dataList: [
+        {
+          id: "",
+          name: "",
+          buildName: "",
+        },
+      ],
+      recordList: [
+        {
+          id: "",
+          name: "",
+          eventTime: "",
+          content: "",
+        },
+      ],
+      baseDialogConfig: {
+        dialogId: "accessControlDialog",
+        show: false,
+        title: "出入门控制",
+        width: 1440,
+        height: 680,
+        center: true,
+        zIndex: 10,
+      },
+      tableConfig: {
+        needIndex: true,
+        height: 130,
+        header: [
+          { title: "名称", prop: "name", width: "" },
+          { title: "所在场站", prop: "buildName", width: "" },
+        ],
+        tableData: [],
+      },
+      recordTableConfig: {
+        needIndex: false,
+        height: 130,
+        header: [
+          { title: "设备名称", prop: "name", width: "80px" },
+          { title: "人员名称", prop: "personName", width: "100px" },
+          { title: "时间", prop: "eventTime", width: "" },
+          { title: "详细描述", prop: "content", width: "" },
+        ],
+        tableData: [],
+      },
+      cameraFaceList: [{ id: "1", name: "摄像头1" }],
+      cameraCarList: [{ id: "2", name: "摄像头2" }],
+      cameraFaceInfo: { id: "1", name: "摄像头1" },
+      cameraCarInfo1: { id: "2", name: "摄像头2" },
+      cameraCarInfo2: { id: "3", name: "摄像头3" },
+      departmentOptions: [],
+      department: {
+        id: "",
+        positioningBuildId: "",
+      },
+      query: {
+        departmentId: "",
+        buildId: "",
+      },
+    };
+  },
+  created() {},
+  computed: {
+    ...mapGetters(["accessControlDialog"]),
+  },
+  mounted() {
+    this.initAccessControlList("");
+    this.initAccessLogList();
+    // this.getDepartmentByPid();
+    this.departmentOptions = GY_STATIONS.filter((e) => e.id !== "");
+  },
+  methods: {
+    async initAccessControlList(buildId) {
+      try {
+        const params = {
+          pageSize: 100,
+          pageIndex: 1,
+          buildId: buildId,
+        };
+        const res = await getAccessInfoList(params);
+        this.dataList = res.data.content;
+        console.log("门禁列表", this.dataList);
+        //人脸识别列表
+        this.cameraFaceList = this.dataList.filter((e) => e.faceRecognition);
+        //车辆识别列表
+        this.cameraCarList = this.dataList.filter((e) => !e.faceRecognition);
+        console.log("门禁摄像头列表", this.cameraFaceList, this.cameraCarList);
+        if (this.cameraFaceList && this.cameraCarList.length > 0) {
+          this.cameraFaceInfo = this.cameraFaceList[0];
+        }
+        if (this.cameraCarList && this.cameraCarList.length > 1) {
+          this.cameraCarInfo1 = this.cameraCarList[0];
+          this.cameraCarInfo2 = this.cameraCarList[1];
+        }
+        console.log(
+          "门禁摄像头",
+          this.cameraFaceInfo,
+          this.cameraCarInfo1,
+          this.cameraCarInfo2
+        );
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    async initAccessLogList() {
+      try {
+        const params = {
+          pageSize: 100,
+          pageIndex: 1,
+        };
+        const res = await getAccessLogList(params);
+        this.recordList = res.data.content;
+        // console.log("门禁事件列表", this.recordList);
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    closeDialog() {
+      this.$store.dispatch("globalConfig/setAccessControlDialog", {
+        show: false,
+        dialogMsg: {},
+        type: "All",
+      });
+    },
+    async handleDeal() {
+      try {
+        await dealAlarm({
+          id: this.accessControlDialog.dialogMsg.id,
+          dealContent: this.accessControlDialog.dialogMsg.dealContent,
+        });
+        this.closeDialog();
+        // 刷新报警列表页
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    handleTableClick(data, btnType) {
+      if (btnType === "open") {
+        console.log("打开", data);
+      }
+      if (btnType === "close") {
+        console.log("关闭", data);
+      }
+    },
+    async getDepartmentByPid() {
+      try {
+        const p = { id: "0" };
+        const res = await getDepartmentByPid(p);
+        let { content } = res.data;
+        content.forEach((element) => {
+          element.value = element.id;
+          element.label = element.departmentName;
+          if (element.children) {
+            element.children.forEach((element2) => {
+              element2.value = element2.id;
+              element2.label = element2.departmentName;
+            });
+          }
+        });
+        this.departmentOptions = content;
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    searchData(e) {
+      console.log("事件信息", e);
+      this.filterInfo();
+    },
+    filterInfo() {
+      if (this.department.positioningBuildId) {
+        this.initAccessControlList(this.department.positioningBuildId);
+      } else {
+        this.initAccessControlList("");
+      }
+    },
+    exchangeVideo(type, e) {
+      switch (type) {
+        case 1:
+          // this.cameraCarInfo1 = this.cameraCarList.filter((c) => c.id === e);
+          break;
+        case 2:
+          // this.cameraCarInfo2 = this.cameraCarList.filter((c) => c.id === e);
+          break;
+        case 3:
+          // this.cameraFaceInfo = this.cameraFaceList.filter((c) => c.id === e);
+          break;
+
+        default:
+          break;
+      }
+    },
+    openAll() {},
+    closeAll() {},
+    openBroadcast() {},
+    closeBroadcast() {},
+    handleClose(item) {
+      let index = -1;
+      for (let i = 0; i < this.openningList.length; i++) {
+        const e = this.openningList[i];
+        if (e.label === item.label) {
+          index = i;
+          this.openningList.splice(index, 1);
+        }
+      }
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.dialog_box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  .access_video {
+    padding-left: 10px;
+    .select {
+      text-align: left;
+      font-size: 0.083333rem /* 16/192 */;
+      line-height: 30px /* 50/192 */;
+      color: #fff;
+      .select_title {
+        padding: 6px;
+      }
+    }
+    .select_list {
+      height: 66px;
+      overflow: auto;
+      max-height: 66px;
+      .select-tag {
+        margin: 2px;
+      }
+    }
+    .select_video {
+      width: 100%;
+      height: 380px;
+      padding: 2px;
+      position: relative;
+      .select_video_main {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+  .search-box {
+    width: 100%;
+    display: flex;
+    margin: 6px /* 10/192 */ 0;
+    color: #fff;
+    .search-item {
+      display: flex;
+      .search-label {
+        display: inline-block;
+        width: 60px;
+        font-size: 0.083333rem /* 16/192 */;
+        line-height: 30px;
+        text-align: center;
+        word-break: keep-all;
+      }
+      .search-date.el-input__inner {
+        width: 1.666667rem /* 320/192 */;
+        height: 28px;
+        border-radius: 0;
+        margin-right: 0;
+      }
+      .el-input {
+        ::v-deep .el-input__inner {
+          height: 28px;
+          border-radius: 0;
+          color: #fff;
+        }
+      }
+      .el-select {
+        margin-right: 0.052083rem /* 10/192 */;
+        ::v-deep .el-input__inner {
+          width: 0.572917rem /* 110/192 */;
+          height: 28px;
+          border-radius: 0;
+          color: #fff;
+          // padding-right: 0.182292rem /* 35/192 */;
+        }
+        ::v-deep .el-input__icon {
+          line-height: 28px;
+        }
+      }
+    }
+    .search-btn2 {
+      box-sizing: content-box;
+      text-align: center;
+      justify-content: right;
+      color: #fff;
+      font-size: 0.072917rem /* 14/192 */;
+      cursor: pointer;
+      border-radius: 0;
+      margin-left: 10px;
+      &:hover {
+        border-color: #ccc;
+      }
+      img {
+        width: 0.083333rem /* 16/192 */;
+        height: 0.083333rem /* 16/192 */;
+      }
+    }
+  }
+  .info_list {
+  }
+  .record_list {
+    margin-left: 4px;
+    text-align: left;
+    font-size: 0.083333rem /* 16/192 */;
+    line-height: 30px /* 50/192 */;
+    color: #fff;
+    .record_title {
+      padding: 6px;
+    }
+    .record_info {
+    }
+  }
+}
+</style>

+ 289 - 0
src/views/components/dialog/JGYTControlDialog/VideoControl.vue

@@ -0,0 +1,289 @@
+<template>
+  <div class="videoControl-container">
+    <div class="comm-open">
+      {{ commOpenning ? "允许操作" : "禁止操作" }}
+      <el-switch
+        style="display: block; margin: 4px"
+        v-model="commOpenning"
+        active-color="#13ce66"
+        inactive-color="#ff4949"
+      >
+      </el-switch>
+    </div>
+    <div class="comm-panel">
+      <div
+        class="btn-box"
+        v-for="item of commandConfig.direction"
+        :key="item.type"
+      >
+        <el-button
+          type="primary"
+          :icon="`el-icon-${item.type}`"
+          size="mini"
+          @mousedown.native="changePtzCommParam(item.command, false)"
+          @mouseup.native="changePtzCommParam(item.command, true)"
+        ></el-button>
+      </div>
+    </div>
+    <div class="zoom-panel">
+      <div class="btn-box" v-for="item of commandConfig.zoom" :key="item.type">
+        <el-button
+          type="primary"
+          :icon="`el-icon-${item.type}`"
+          size="mini"
+          @mousedown.native="changePtzCommParam(item.command, false)"
+          @mouseup.native="changePtzCommParam(item.command, true)"
+        ></el-button>
+      </div>
+    </div>
+    <div class="form_box">
+      <el-form label-width="70px" size="small">
+        <el-form-item label="速度" prop="speed" class="form_info">
+          <el-select
+            class="myInput"
+            size="mini"
+            v-model="speed"
+            placeholder="请选择速度"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in Array.from(
+                { length: 10 },
+                (item, index) => index + 1
+              )"
+              :key="item"
+              :label="item"
+              :value="item"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="预置点" prop="presetIndex" class="form_info">
+          <el-select
+            class="myInput"
+            size="mini"
+            v-model="presetIndex"
+            placeholder="请选择预置点"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in Array.from(
+                { length: 255 },
+                (item, index) => index + 1
+              )"
+              :key="item"
+              :label="item"
+              :value="item"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <div class="btn_box">
+          <el-button type="primary" size="mini" @click="changePtzPresetParam(8)"
+            >设置</el-button
+          >
+          <el-button
+            type="primary"
+            size="mini"
+            @click="changePtzPresetParam(39)"
+            >转到</el-button
+          >
+        </div>
+        <!-- <el-form-item label="时间" prop="startTime">
+          <el-date-picker class="myInput" size="mini" v-model="startTime" type="datetime" placeholder="选择日期时间" style="width: 100%"></el-date-picker>
+        </el-form-item>
+        <div class="btn_box">
+          <el-button type="primary" size="mini" @click="changePlayTypeParam(true)" :disabled="!startTime">回放</el-button>
+          <el-button type="primary" size="mini" @click="changePlayTypeParam(false)" :disabled="!startTime">实时</el-button>
+        </div> -->
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Dayjs from "dayjs";
+export default {
+  name: "VideoControl",
+  props: {
+    curVideoData: {
+      type: Object,
+      require: true,
+      default: () => ({}),
+    },
+  },
+  data() {
+    return {
+      // 视频控制相关 start
+      commandConfig: {
+        //视频控制开关配置
+        direction: [
+          //方向
+          { type: "top-left", name: "左上", command: 25 },
+          { type: "top", name: "上", command: 21 },
+          { type: "top-right", name: "右上", command: 26 },
+          { type: "back", name: "左", command: 23 },
+          { type: "rank", name: "中", command: 0 },
+          { type: "right", name: "右", command: 24 },
+          { type: "bottom-left", name: "左下", command: 27 },
+          { type: "bottom", name: "下", command: 22 },
+          { type: "bottom-right", name: "右下", command: 28 },
+        ],
+        zoom: [
+          //放大缩小
+          { type: "zoom-in", name: "放大", command: 11 },
+          { type: "zoom-out", name: "缩小", command: 12 },
+        ],
+      },
+      startTime: null,
+      speed: 5,
+      presetIndex: 1,
+      // 视频控制 end
+      commOpenning: false,
+    };
+  },
+  mounted() {},
+  methods: {
+    changePtzCommParam(comm, stop) {
+      if (!this.commOpenning) {
+        stop && this.$message.warning("请先开启操作许可!");
+        return;
+      }
+      if (!comm) return;
+      if (!this.curVideoData.id) {
+        stop && this.$message.warning("请先选择视频窗口!");
+        return;
+      }
+      let param = {
+        id: this.curVideoData.id,
+        ptzCommand: comm,
+        ptzStop: stop,
+        ptzSpeed: this.speed,
+        canControl: this.curVideoData.ptzEnable,
+      };
+      this.$EventBus.$emit("updateSendParam", param);
+    },
+    changePtzPresetParam(comm) {
+      if (!this.commOpenning) {
+        stop && this.$message.warning("请先开启操作许可!");
+        return;
+      }
+      if (!comm) return;
+      if (!this.curVideoData.id) {
+        this.$message.warning("请先选择视频窗口!");
+        return;
+      }
+      let param = {
+        id: this.curVideoData.id,
+        ptzPreset: comm,
+        ptzPresetIndex: this.presetIndex,
+        canControl: this.curVideoData.ptzEnable,
+      };
+      this.$EventBus.$emit("updateSendParam", param);
+    },
+    /**
+     * state  true代表回放模式
+     */
+    changePlayTypeParam(state) {
+      if (!this.commOpenning) {
+        stop && this.$message.warning("请先开启操作许可!");
+        return;
+      }
+      let param = { id: this.curVideoData.id };
+      if (!this.curVideoData.id) {
+        this.$message.warning("请先选择视频窗口!");
+        return;
+      }
+      if (state) {
+        if (!this.startTime) {
+          this.$message.warning("请选择回放开始时间!");
+          return;
+        }
+        param["startTime"] = Dayjs(this.startTime).format(
+          "YYYY-MM-DD HH:mm:ss"
+        );
+      }
+      this.$EventBus.$emit("updateSendParam", param, true);
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.videoControl-container {
+  width: 100%;
+  .comm-open {
+    padding: 6px 6px 6px 16px;
+    text-align: left;
+    font-size: 0.083333rem /* 16/192 */;
+    line-height: 30px /* 50/192 */;
+    color: #fff;
+    display: flex;
+    height: 43px;
+  }
+  .comm-panel {
+    width: 184px;
+    margin: 0 auto;
+    display: flex;
+    flex-wrap: wrap;
+    .el-button {
+      background: #007ccc;
+      border-color: #007ccc;
+    }
+  }
+  .zoom-panel {
+    width: 122px;
+    margin: 0 auto;
+    display: flex;
+    .el-button {
+      background: #007ccc;
+      border-color: #007ccc;
+    }
+  }
+  .btn-box {
+    flex-shrink: 0;
+    width: 60px;
+    height: 40px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+  .form_box {
+    width: 100%;
+    padding: 10px 0;
+    ::v-deep .form_info .el-form-item__label {
+      color: rgb(255, 255, 255);
+    }
+    ::v-deep .el-form {
+      width: 100%;
+      .myInput {
+        .el-input__inner {
+          // width: 110px;
+          height: 30px;
+          border-radius: 0;
+          background: rgba(0, 20, 23, 0.2);
+          border: 0.5px solid #5bd6ff;
+          color: #5bd6ff;
+          // padding-right: 35px;
+        }
+        .el-input__inner:focus {
+          border: 0.5px solid #5bd6ff !important;
+        }
+        .el-input.is-focus .el-input__inner {
+          border: 0.5px solid #5bd6ff !important;
+        }
+        .el-input__suffix {
+          right: 5px;
+        }
+        .el-input__icon {
+          line-height: 30px;
+        }
+      }
+      .btn_box {
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-bottom: 12px;
+      }
+    }
+  }
+}
+</style>

+ 453 - 0
src/views/components/dialog/JGYTControlDialog/index.vue

@@ -0,0 +1,453 @@
+<template>
+  <base-drag-bg-dialog
+    :dialogConfig="baseDialogConfig"
+    @handleClose="closeDialog"
+  >
+    <!-- 弹窗内容 -->
+    <div class="dialog_box">
+      <!-- 内容 -->
+      <div class="detail-table-box">
+        <el-row>
+          <el-col :span="8">
+            <div class="search-box">
+              <div class="search-item">
+                <span class="search-label">场站:</span>
+                <el-select
+                  value-key="id"
+                  v-model="department"
+                  style="width: 110px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择场站"
+                  @change="searchData($event)"
+                >
+                  <el-option
+                    v-for="item in departmentOptions"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+              <!-- <div class="search-btn2" @click="openAll">
+                <el-button size="mini" type="success">人员授权</el-button>
+              </div>
+              <div class="search-btn2" @click="closeAll">
+                <el-button size="mini" type="warning">车辆授权</el-button>
+              </div> -->
+              <!-- <div class="search-btn2" @click="openBroadcast">
+                  <el-button size="mini" type="success">开门</el-button>
+                </div>
+                <div class="search-btn2" @click="closeBroadcast">
+                  <el-button size="mini" type="danger">关门</el-button>
+                </div> -->
+            </div>
+            <div class="info_list">
+              <base-table-list
+                :tableConfig="tableConfig"
+                @handleClick="handleTableClick"
+              />
+            </div>
+          </el-col>
+          <el-col class="jgyt_video" :span="12">
+            <div class="select">
+              <div class="select_title">
+                泄漏检测
+                <el-select
+                  value-key="id"
+                  v-model="cameraInfo"
+                  style="width: 220px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择摄像头"
+                  @change="exchangeVideo()"
+                >
+                  <el-option
+                    v-for="item in cameraList"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+            </div>
+            <div class="select_video">
+              <div class="select_video_main">
+                <video-image-window
+                  :cameraData="cameraInfo"
+                  :cameraId="cameraInfo.id"
+                />
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="4">
+            <video-control :curVideoData="cameraInfo" />
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24">
+            <div class="record_list">
+              <div class="record_title">告警记录</div>
+              <div class="record_info">
+                <base-table-list :tableConfig="recordTableConfig" />
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+  </base-drag-bg-dialog>
+</template>
+  <script>
+import BaseTableList from "@/views/components/base/BaseTableList";
+import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
+import VideoImageWindow from "@/views/components/dialog/VideoImageWindow.vue";
+import { dealAlarm } from "@/API/common";
+import { getDepartmentByPid } from "@/API/alarm";
+import { getJGYTList, getJGYTAlarmList } from "@/API/JGYT";
+import { mapGetters } from "vuex";
+import VideoControl from "./VideoControl";
+export default {
+  name: "jgytControlDialog",
+  components: {
+    BaseDragBgDialog,
+    BaseTableList,
+    VideoImageWindow,
+    VideoControl,
+  },
+  watch: {
+    "jgytControlDialog.show": {
+      handler(newVal) {
+        this.baseDialogConfig.show = newVal;
+      },
+      // deep: true,
+      immediate: true,
+    },
+    dataList: {
+      handler(newValue, oldValue) {
+        this.filterKey = "";
+        this.tableConfig.tableData = newValue;
+      },
+      deep: true,
+    },
+    recordList: {
+      handler(newValue, oldValue) {
+        this.filterKey = "";
+        this.recrodTableConfig.tableData = newValue;
+      },
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      BASE_URL,
+      dataList: [
+        {
+          id: "",
+          name: "",
+          departmentName: "",
+        },
+      ],
+      recordList: [
+        {
+          id: "",
+          name: "",
+          eventTime: "",
+          content: "",
+        },
+      ],
+      baseDialogConfig: {
+        dialogId: "jgytControlDialog",
+        show: false,
+        title: "泄漏检测",
+        width: 1250,
+        height: 680,
+        center: true,
+        zIndex: 10,
+      },
+      tableConfig: {
+        needIndex: true,
+        height: 300,
+        header: [
+          { title: "名称", prop: "name", width: "" },
+          { title: "所在场站", prop: "departmentName", width: "" },
+        ],
+        tableData: [],
+      },
+      recordTableConfig: {
+        needIndex: true,
+        height: 118,
+        header: [
+          { title: "名称", prop: "laserPtzName", width: "80px" },
+          { title: "浓度", prop: "concentration", width: "80px" },
+          { title: "记录描述", prop: "content", width: "" },
+          { title: "时间", prop: "startTime", width: "80px" },
+        ],
+        tableData: [],
+      },
+      cameraList: [{ id: "1", name: "摄像头1" }],
+      cameraInfo: {
+        id: "1",
+      },
+      departmentOptions: [],
+      department: {
+        id: "",
+        positioningBuildId: "",
+      },
+      query: {
+        departmentId: "",
+      },
+    };
+  },
+  created() {},
+  computed: {
+    ...mapGetters(["jgytControlDialog"]),
+  },
+  mounted() {
+    this.initJGYTList("");
+    this.initJGYTAlarmList("");
+    // this.getDepartmentByPid();
+    this.departmentOptions = GY_STATIONS.filter((e) => e.id !== "");
+  },
+  methods: {
+    async initJGYTList(buildId) {
+      try {
+        const params = {
+          pageSize: 100,
+          pageIndex: 1,
+          buildId: buildId,
+        };
+        const res = await getJGYTList(params);
+        this.dataList = res.data.content;
+        console.log("激光云台列表", this.dataList);
+        this.cameraList = this.dataList.map((e) => e.camera);
+        if (this.cameraList && this.cameraList.length > 0) {
+          this.cameraInfo = this.cameraList[0];
+        }
+        console.log("激光云台摄像头列表", this.cameraList, this.cameraInfo);
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    async initJGYTAlarmList(buildId) {
+      try {
+        const params = {
+          pageSize: 100,
+          pageIndex: 1,
+          buildId: buildId,
+        };
+        const res = await getJGYTAlarmList(params);
+        this.recordList = res.data.content;
+        this.recordTableConfig.tableData = this.recordList;
+        console.log("激光云台报警列表", this.recordList);
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    closeDialog() {
+      this.$store.dispatch("globalConfig/setJGYTControlDialog", {
+        show: false,
+        dialogMsg: {},
+        type: "All",
+      });
+    },
+    async handleDeal() {
+      try {
+        await dealAlarm({
+          id: this.jgytControlDialog.dialogMsg.id,
+          dealContent: this.jgytControlDialog.dialogMsg.dealContent,
+        });
+        this.closeDialog();
+        // 刷新报警列表页
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    handleTableClick(data, btnType) {
+      if (btnType === "open") {
+        console.log("打开", data);
+      }
+      if (btnType === "close") {
+        console.log("关闭", data);
+      }
+    },
+    async getDepartmentByPid() {
+      try {
+        const p = { id: "0" };
+        const res = await getDepartmentByPid(p);
+        let { content } = res.data;
+        content.forEach((element) => {
+          element.value = element.id;
+          element.label = element.departmentName;
+          if (element.children) {
+            element.children.forEach((element2) => {
+              element2.value = element2.id;
+              element2.label = element2.departmentName;
+            });
+          }
+        });
+        this.departmentOptions = content;
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    searchData(e) {
+      console.log("事件信息", e);
+      this.filterInfo();
+    },
+    filterInfo() {
+      if (this.department.positioningBuildId) {
+        this.initJGYTList(this.department.positioningBuildId);
+      } else {
+        this.initJGYTList("");
+      }
+    },
+    exchangeVideo() {},
+    openAll() {},
+    closeAll() {},
+    openBroadcast() {},
+    closeBroadcast() {},
+    handleClose(item) {
+      let index = -1;
+      for (let i = 0; i < this.openningList.length; i++) {
+        const e = this.openningList[i];
+        if (e.label === item.label) {
+          index = i;
+          this.openningList.splice(index, 1);
+        }
+      }
+    },
+  },
+};
+</script>
+  <style lang="less" scoped>
+.dialog_box {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  .search-box {
+    width: 100%;
+    display: flex;
+    margin: 6px /* 10/192 */ 0;
+    color: #fff;
+    .search-item {
+      display: flex;
+      .search-label {
+        display: inline-block;
+        width: 60px;
+        font-size: 0.083333rem /* 16/192 */;
+        line-height: 30px;
+        text-align: center;
+        word-break: keep-all;
+      }
+      .search-date.el-input__inner {
+        width: 1.666667rem /* 320/192 */;
+        height: 28px;
+        border-radius: 0;
+        margin-right: 0;
+      }
+      .el-input {
+        ::v-deep .el-input__inner {
+          height: 28px;
+          border-radius: 0;
+          color: #fff;
+        }
+      }
+      .el-select {
+        margin-right: 0.052083rem /* 10/192 */;
+        ::v-deep .el-input__inner {
+          width: 0.572917rem /* 110/192 */;
+          height: 28px;
+          border-radius: 0;
+          color: #fff;
+          // padding-right: 0.182292rem /* 35/192 */;
+        }
+        ::v-deep .el-input__icon {
+          line-height: 28px;
+        }
+      }
+    }
+    .search-btn2 {
+      box-sizing: content-box;
+      text-align: center;
+      justify-content: right;
+      color: #fff;
+      font-size: 0.072917rem /* 14/192 */;
+      cursor: pointer;
+      border-radius: 0;
+      margin-left: 10px;
+      &:hover {
+        border-color: #ccc;
+      }
+      img {
+        width: 0.083333rem /* 16/192 */;
+        height: 0.083333rem /* 16/192 */;
+      }
+    }
+  }
+  .select {
+    text-align: left;
+    font-size: 0.083333rem /* 16/192 */;
+    line-height: 30px /* 50/192 */;
+    color: #fff;
+    .select_title {
+      padding: 6px 6px 6px 16px;
+    }
+  }
+  .jgyt_video {
+    padding-left: 10px;
+    .select {
+      text-align: left;
+      font-size: 0.083333rem /* 16/192 */;
+      line-height: 30px /* 50/192 */;
+      color: #fff;
+      .select_title {
+        padding: 6px;
+      }
+    }
+    .select_list {
+      height: 66px;
+      overflow: auto;
+      max-height: 66px;
+      .select-tag {
+        margin: 2px;
+      }
+    }
+    .select_video {
+      width: 100%;
+      height: 400px;
+      position: relative;
+      .select_video_main {
+        width: 100%;
+        height: 100%;
+      }
+    }
+    .tag_info {
+      text-align: left;
+      font-size: 0.083333rem /* 16/192 */;
+      line-height: 30px /* 50/192 */;
+      color: #fff;
+      position: relative;
+      .tag {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+  .info_list {
+  }
+  .record_list {
+    margin-left: 4px;
+    text-align: left;
+    font-size: 0.083333rem /* 16/192 */;
+    line-height: 30px /* 50/192 */;
+    color: #fff;
+    .record_title {
+      padding: 6px;
+    }
+    .record_info {
+    }
+  }
+}
+</style>
+  

+ 241 - 68
src/views/components/dialog/SoundDialog.vue

@@ -2,16 +2,98 @@
   <base-drag-bg-dialog
   <base-drag-bg-dialog
     :dialogConfig="baseDialogConfig"
     :dialogConfig="baseDialogConfig"
     @handleClose="closeDialog"
     @handleClose="closeDialog"
-    @onActivated="onActivated"
   >
   >
     <!-- 弹窗内容 -->
     <!-- 弹窗内容 -->
     <div class="dialog_box">
     <div class="dialog_box">
       <!-- 内容 -->
       <!-- 内容 -->
       <div class="detail-table-box">
       <div class="detail-table-box">
-        <base-table-list
-          :tableConfig="tableConfig"
-          @handleClick="handleTableClick"
-        />
+        <el-row>
+          <el-col :span="13">
+            <div class="search-box">
+              <div class="search-item">
+                <span class="search-label">场站:</span>
+                <el-cascader
+                  v-model="query.departmentId"
+                  :options="departmentOptions"
+                  :props="{ checkStrictly: true }"
+                  clearable
+                  size="mini"
+                  placeholder="请选择场站"
+                  style="width: 160px"
+                  @change="searchData()"
+                />
+              </div>
+              <div class="search-btn2" @click="openAll">
+                <el-button size="mini" type="success">全部打开</el-button>
+              </div>
+              <div class="search-btn2" @click="closeAll">
+                <el-button size="mini" type="warning">全部关闭</el-button>
+              </div>
+              <div class="search-btn2" @click="openBroadcast">
+                <el-button size="mini" type="success">广播</el-button>
+              </div>
+              <div class="search-btn2" @click="closeBroadcast">
+                <el-button size="mini" type="danger">停止广播</el-button>
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="11">
+            <div class="select">
+              <div class="select_title">已打开防爆扩音</div>
+            </div>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="13">
+            <base-table-list
+              :tableConfig="tableConfig"
+              @handleClick="handleTableClick"
+            />
+          </el-col>
+          <el-col class="fbky" :span="11">
+            <div class="select_list">
+              <el-tag
+                class="select-tag"
+                v-for="item in openningList"
+                size="medium"
+                :key="item.label"
+                :type="item.type"
+                closable
+                @close="handleClose(item)"
+              >
+                {{ item.label }}
+              </el-tag>
+            </div>
+            <div class="select">
+              <div class="select_title">
+                防爆扩音现场监视
+                <el-select
+                  v-model="cameraInfo"
+                  style="width: 160px"
+                  size="mini"
+                  clearable
+                  placeholder="请选择摄像头"
+                  @change="exchangeVideo()"
+                >
+                  <el-option
+                    v-for="item in cameraList"
+                    :key="item.id"
+                    :value="item"
+                    :label="item.name"
+                  ></el-option>
+                </el-select>
+              </div>
+            </div>
+            <div class="select_video">
+              <div class="select_video_main">
+                <video-image-window
+                  :cameraData="cameraInfo"
+                  :cameraId="cameraInfo.id"
+                />
+              </div>
+            </div>
+          </el-col>
+        </el-row>
       </div>
       </div>
     </div>
     </div>
   </base-drag-bg-dialog>
   </base-drag-bg-dialog>
@@ -19,12 +101,14 @@
 <script>
 <script>
 import BaseTableList from "@/views/components/base/BaseTableList";
 import BaseTableList from "@/views/components/base/BaseTableList";
 import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
 import BaseDragBgDialog from "@/views/components/base/BaseDragBgDialog.vue";
+import VideoImageWindow from "@/views/components/dialog/VideoImageWindow.vue";
 import { dealAlarm } from "@/API/common";
 import { dealAlarm } from "@/API/common";
+import { getDepartmentByPid } from "@/API/alarm";
 import { getElementList } from "@/API/visual";
 import { getElementList } from "@/API/visual";
 import { mapGetters } from "vuex";
 import { mapGetters } from "vuex";
 export default {
 export default {
   name: "soundDialog",
   name: "soundDialog",
-  components: { BaseDragBgDialog, BaseTableList },
+  components: { BaseDragBgDialog, BaseTableList, VideoImageWindow },
   watch: {
   watch: {
     "soundDialog.show": {
     "soundDialog.show": {
       handler(newVal) {
       handler(newVal) {
@@ -54,8 +138,8 @@ export default {
         dialogId: "soundDialog",
         dialogId: "soundDialog",
         show: false,
         show: false,
         title: "防爆扩音",
         title: "防爆扩音",
-        width: 640,
-        height: 540,
+        width: 1250,
+        height: 640,
         center: true,
         center: true,
         zIndex: 10,
         zIndex: 10,
       },
       },
@@ -78,10 +162,31 @@ export default {
         tableData: [],
         tableData: [],
         rowClick: this.location,
         rowClick: this.location,
       },
       },
+      openningList: [
+        { type: "", label: "设备一" },
+        { type: "", label: "设备二" },
+        { type: "", label: "设备三" },
+        { type: "", label: "设备四" },
+        { type: "", label: "设备五" },
+        { type: "", label: "设备六" },
+        { type: "", label: "设备七" },
+        { type: "", label: "设备八" },
+        { type: "", label: "设备九" },
+        { type: "", label: "设备十" },
+      ],
+      cameraList: [{ id: "1", name: "摄像头1" }],
+      cameraInfo: {
+        id: "1",
+      },
+      departmentOptions: [],
+      query: {
+        departmentId: "",
+      },
     };
     };
   },
   },
   created() {
   created() {
     this.initSoundList();
     this.initSoundList();
+    this.getDepartmentByPid();
   },
   },
   computed: {
   computed: {
     ...mapGetters(["soundDialog"]),
     ...mapGetters(["soundDialog"]),
@@ -141,11 +246,45 @@ export default {
       //   },
       //   },
       // });
       // });
     },
     },
-    onActivated() {
-      // console.log("aaa");
-      this.$nextTick(() => {
-        this.$refs.dealContent.focus();
-      });
+    async getDepartmentByPid() {
+      try {
+        const p = { id: "0" };
+        const res = await getDepartmentByPid(p);
+        let { content } = res.data;
+        content.forEach((element) => {
+          element.value = element.id;
+          element.label = element.departmentName;
+          if (element.children) {
+            element.children.forEach((element2) => {
+              element2.value = element2.id;
+              element2.label = element2.departmentName;
+            });
+          }
+        });
+        this.departmentOptions = content;
+      } catch (err) {
+        console.log(err);
+      }
+    },
+    searchData() {
+      this.pageConfig.pageNo = 1;
+      this.filterInfo();
+    },
+    filterInfo() {},
+    exchangeVideo() {},
+    openAll() {},
+    closeAll() {},
+    openBroadcast() {},
+    closeBroadcast() {},
+    handleClose(item) {
+      let index = -1;
+      for (let i = 0; i < this.openningList.length; i++) {
+        const e = this.openningList[i];
+        if (e.label === item.label) {
+          index = i;
+          this.openningList.splice(index, 1);
+        }
+      }
     },
     },
   },
   },
 };
 };
@@ -155,69 +294,103 @@ export default {
   width: 100%;
   width: 100%;
   height: 100%;
   height: 100%;
   box-sizing: border-box;
   box-sizing: border-box;
-  .dialog_content_box {
-    height: 2.083333rem /* 400/192 */;
-    padding: 0.104167rem /* 20/192 */ 0;
-    box-sizing: border-box;
+  .search-box {
+    width: 100%;
+    display: flex;
+    margin: 6px /* 10/192 */ 0;
     color: #fff;
     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 */;
+    .search-item {
+      display: flex;
+      .search-label {
+        display: inline-block;
+        width: 60px;
+        font-size: 14px;
+        line-height: 28px;
         text-align: center;
         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;
+        word-break: keep-all;
+      }
+      .search-date.el-input__inner {
+        width: 1.666667rem /* 320/192 */;
+        height: 28px;
+        border-radius: 0;
+        margin-right: 0;
+      }
+      .el-input {
+        ::v-deep .el-input__inner {
+          height: 28px;
           border-radius: 0;
           border-radius: 0;
-          &:hover {
-            border-color: #ccc;
-          }
+          color: #fff;
         }
         }
-        .btn-handle.el-button {
-          // background: url('../../../../assets/out/imgs/popup/button_bg.png') center no-repeat;
-          background: rgba(4, 42, 47, 0.6);
+      }
+      .el-select {
+        margin-right: 0.052083rem /* 10/192 */;
+        ::v-deep .el-input__inner {
+          width: 0.572917rem /* 110/192 */;
+          height: 28px;
+          border-radius: 0;
+          color: #fff;
+          // padding-right: 0.182292rem /* 35/192 */;
         }
         }
-        .btn-cancel.el-button {
-          background: rgba(13, 35, 64, 0.1);
+        ::v-deep .el-input__icon {
+          line-height: 28px;
         }
         }
       }
       }
     }
     }
+    .search-btn2 {
+      box-sizing: content-box;
+      text-align: center;
+      justify-content: right;
+      color: #fff;
+      font-size: 0.072917rem /* 14/192 */;
+      cursor: pointer;
+      border-radius: 0;
+      margin-left: 10px;
+      &:hover {
+        border-color: #ccc;
+      }
+      img {
+        width: 0.083333rem /* 16/192 */;
+        height: 0.083333rem /* 16/192 */;
+      }
+    }
+  }
+  .select {
+    text-align: left;
+    font-size: 0.083333rem /* 16/192 */;
+    line-height: 30px /* 50/192 */;
+    color: #fff;
+    .select_title {
+      padding: 6px 6px 6px 16px;
+    }
+  }
+  .fbky {
+    padding-left: 10px;
+    .select {
+      text-align: left;
+      font-size: 0.083333rem /* 16/192 */;
+      line-height: 30px /* 50/192 */;
+      color: #fff;
+      .select_title {
+        padding: 6px;
+      }
+    }
+    .select_list {
+      height: 66px;
+      overflow: auto;
+      max-height: 66px;
+      .select-tag {
+        margin: 2px;
+      }
+    }
+    .select_video {
+      width: 100%;
+      height: 440px;
+      position: relative;
+      .select_video_main {
+        width: 100%;
+        height: 100%;
+      }
+    }
   }
   }
 }
 }
 </style>
 </style>

+ 1 - 1
src/views/components/dialog/VideoImageWindow.vue

@@ -134,7 +134,7 @@ export default {
       this.ws = new WebSocket('ws://' + window.location.host + BASE_URL + '/VideoOverWebSocket')
       this.ws = new WebSocket('ws://' + window.location.host + BASE_URL + '/VideoOverWebSocket')
       this.ws.onmessage = evt => {
       this.ws.onmessage = evt => {
         if (typeof evt.data === 'string') {
         if (typeof evt.data === 'string') {
-          console.log(JSON.parse(evt.data).Msg)
+          // console.log(JSON.parse(evt.data).Msg)
         } else {
         } else {
           let _this = this
           let _this = this
           // const updateUrl = _.debounce(function () {
           // const updateUrl = _.debounce(function () {

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

@@ -58,5 +58,7 @@ export default {
   // background: #001012;
   // background: #001012;
   // background: ;
   // background: ;
   pointer-events: auto;
   pointer-events: auto;
+  // position: absolute;
+  // z-index: 3000; // loading层是2000 设置高一些,下拉菜单会盖住loading层
 }
 }
 </style>
 </style>

+ 1 - 1
src/views/stationMapTKT/components/BaseImgMap/StationPoint.vue

@@ -144,7 +144,7 @@ export default {
     switchMode,
     switchMode,
     setBuildInfoByBuildId,
     setBuildInfoByBuildId,
     openStation(c) {
     openStation(c) {
-      console.log("ConfigInfomation", c);
+      // console.log("ConfigInfomation", c);
       if (c.type == "station") {
       if (c.type == "station") {
         this.jumpRoute("/basePage", { buildId: c.buildId });
         this.jumpRoute("/basePage", { buildId: c.buildId });
         this.switchMode("home");
         this.switchMode("home");

+ 242 - 0
src/views/videoMonitorType/components/StationSelect.vue

@@ -0,0 +1,242 @@
+<template>
+  <div class="stationSelect-container">
+    <div class="search-box">
+      <el-input v-model="stationName" placeholder="请输入查询内容" />
+      <div class="search-btn">
+        <img
+          :src="require('@/assets/imgs/video/icon_sousuo_sel@2x.png')"
+          alt=""
+        />
+      </div>
+    </div>
+    <div class="viewType_box">
+      <span class="label"></span>
+      <el-radio-group v-model="type" size="mini" @change="changeViewType">
+        <el-radio-button label="1">场站</el-radio-button>
+        <el-radio-button label="2">分类</el-radio-button>
+      </el-radio-group>
+    </div>
+    <div class="stationTree-box">
+      <el-tree
+        :data="videoTreeData"
+        :props="defaultProps"
+        node-key="id"
+        default-expand-all
+        @node-click="handleNodeClick"
+        :filter-node-method="filterNode"
+        ref="tree"
+      ></el-tree>
+    </div>
+  </div>
+</template>
+
+<script>
+import { uniqBy } from "lodash-es";
+export default {
+  name: "StationSelect",
+  props: {
+    videoList: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  data() {
+    return {
+      stationName: "",
+      defaultProps: {
+        children: "children",
+        label: "label",
+        id: "id",
+      },
+      type: "1",
+    };
+  },
+  computed: {
+    videoTreeData() {
+      if (!this.videoList?.length) return [];
+      if (this.type === "1") {
+        const stations = this.videoList.map((item) => ({
+          id: item.departmentId,
+          label: item.departmentName,
+        }));
+        const level_1 = uniqBy(stations, "id"); // 去重
+        return level_1.map((item) => {
+          return {
+            ...item,
+            children: this.videoList
+              .filter((t1) => t1.departmentId === item.id)
+              .map((t2) => {
+                return {
+                  id: t2.id,
+                  label: t2.name,
+                  departmentId: t2.departmentId,
+                };
+              }),
+          };
+        });
+      } else if (this.type === "2") {
+        const types = this.videoList.map((item) => ({
+          id: item.useType,
+          label: item.useTypeStr,
+        }));
+        const type_1 = uniqBy(types, "id").sort((a, b) => +a.id - +b.id); // 去重
+        return type_1.map((item) => {
+          return {
+            ...item,
+            children: this.videoList
+              .filter((t1) => t1.useType === item.id)
+              .map((t2) => {
+                return {
+                  id: t2.id,
+                  label: t2.name,
+                  departmentId: t2.departmentId,
+                };
+              }),
+          };
+        });
+      }
+      return [];
+    },
+  },
+  watch: {
+    stationName(val) {
+      this.$nextTick(() => {
+        this.$refs.tree.filter(val);
+      });
+    },
+  },
+  methods: {
+    handleNodeClick(data, node) {
+      console.log(data);
+      if (node.level === 1) return;
+      this.$emit("selectNode", data);
+    },
+    filterNode(value, data) {
+      if (!value) return true;
+      return data.label.indexOf(value) !== -1;
+    },
+    setTreeValue(id) {
+      this.$nextTick(() => {
+        this.$refs.tree.setCurrentKey(id);
+      });
+    },
+    changeViewType() {
+      this.$parent.sortVideoList(this.type);
+    },
+  },
+};
+</script>
+<style lang="less" scoped>
+.stationSelect-container {
+  width: 306px;
+  // height: 862px;
+  min-height: 862px;
+  height: calc(100vh - 218px);
+  background: #001f54;
+  border: 1px solid #5bd6ff;
+  .search-box {
+    width: 100%;
+    padding: 10px;
+    display: flex;
+    // justify-content: space-between;
+    ::v-deep .el-input__inner {
+      // width: 110px;
+      height: 30px;
+      border-radius: 0;
+      background: rgba(0, 20, 23, 0.2);
+      border: 0.5px solid #5bd6ff;
+      color: #fff;
+      // padding-right: 35px;
+    }
+    ::v-deep .el-input__inner:focus {
+      border: 0.5px solid #5bd6ff !important;
+    }
+    ::v-deep .el-input.is-focus .el-input__inner {
+      border: 0.5px solid #5bd6ff !important;
+    }
+    ::v-deep .el-input__suffix {
+      right: 5px;
+    }
+    ::v-deep .el-input__icon {
+      line-height: 30px;
+    }
+    .search-btn {
+      width: 30px;
+      height: 30px;
+      margin-left: 10px;
+      cursor: pointer;
+      flex-shrink: 0;
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+  .viewType_box {
+    width: 100%;
+    padding: 0 10px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    .label {
+      margin-right: 10px;
+      color: #fff;
+    }
+  }
+  .stationTree-box {
+    padding: 0 10px;
+    height: calc(100% - 80px);
+    overflow-y: auto;
+    .el-tree {
+      background-color: transparent;
+      color: #fff;
+      /deep/ .el-tree-node__expand-icon.expanded {
+        -webkit-transform: rotate(0deg);
+        transform: rotate(0deg);
+      }
+      //有子节点 且未展开
+      /deep/ .el-icon-caret-right:before {
+        background: url("~@/assets/imgs/video/unfold.png") no-repeat 0 0;
+        content: "";
+        display: block;
+        width: 16px;
+        height: 16px;
+        font-size: 16px;
+        background-size: 16px;
+      }
+      //有子节点 且已展开
+      /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
+        background: url("~@/assets/imgs/video/fold.png") no-repeat 0 0;
+        content: "";
+        display: block;
+        width: 16px;
+        height: 16px;
+        font-size: 16px;
+        background-size: 16px;
+      }
+      //没有子节点
+      /deep/.el-tree-node__expand-icon.is-leaf::before {
+        background: url("~@/assets/imgs/video/camera.png") no-repeat 0 0;
+        content: "";
+        display: block;
+        width: 16px;
+        height: 16px;
+        font-size: 16px;
+        background-size: 16px;
+      }
+      /deep/ .el-tree-node.is-current > .el-tree-node__content {
+        background-color: transparent;
+        color: #73ffd2;
+      }
+      /deep/ .el-tree-node:focus > .el-tree-node__content {
+        background-color: transparent;
+        color: #73ffd2;
+      }
+      /deep/ .el-tree-node__content:hover {
+        background-color: transparent;
+        color: #73ffd2;
+      }
+    }
+  }
+}
+</style>

+ 238 - 0
src/views/videoMonitorType/components/VideoConfig.vue

@@ -0,0 +1,238 @@
+<template>
+  <div class="videoConfig-container">
+    <div class="video_control_box">
+      <el-form :model="configOptions" :label-width="$px2rem(70) + 'rem'" size="small" :rules="rules">
+        <el-form-item label="码流类型" prop="codeStreamType">
+          <el-select class="myInput" v-model="configOptions.codeStreamType" style="width: 100%">
+            <el-option value="1" label="主码流"></el-option>
+            <el-option value="2" label="子码流"></el-option>
+            <el-option value="3" label="辅码流"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="分屏方式" prop="splitScreenType">
+          <el-select class="myInput" v-model="configOptions.splitScreenType" style="width: 100%">
+            <el-option v-for="item of screenConfig" :key="item.type" :value="item.type" :label="item.name"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="速率" prop="loopFreq">
+          <el-input-number class="myInput" v-model="configOptions.loopFreq" :step="10" controls-position="right" size="mini" @change="updatePollFreq">
+          </el-input-number>
+          <span class="unit">秒</span>
+        </el-form-item>
+        <el-form-item label="开启轮询" prop="isLoop">
+          <el-switch
+            v-model="configOptions.isLoop"
+            active-color="#13ce66"
+            inactive-color="#C0C4CC"
+            :active-value="true"
+            :inactive-value="false"
+            @change="handleChangeLoop">
+          </el-switch>
+        </el-form-item>
+        <el-form-item label="全屏显示" prop="isFullScreen">
+          <el-switch
+            v-model="configOptions.isFullScreen"
+            active-color="#13ce66"
+            inactive-color="#C0C4CC"
+            :active-value="true"
+            :inactive-value="false"
+            @change="setFullScreen">
+          </el-switch>
+        </el-form-item>
+        <el-form-item label="视频操作" prop="isFullScreen">
+          <el-tag v-if="configOptions.selectedVideoData.name" size="small" closable @close="updateVideoData">
+            <span>{{ configOptions.selectedVideoData.name }}</span>
+          </el-tag>
+          <span v-else>无</span>
+        </el-form-item>
+      </el-form>
+      <video-control :curVideoData="configOptions.selectedVideoData" />
+    </div>
+  </div>
+</template>
+
+<script>
+import VideoControl from './VideoControl'
+import { debounce } from 'lodash-es'
+export default {
+  name: 'VideoConfig',
+  components: { VideoControl },
+  props: {
+    configOptions: {
+      type: Object,
+      default: () => ({}),
+    },
+    screenMode: {
+      type: String,
+      default: 'large',
+    },
+  },
+  data() {
+    return {
+      screenConfig: [
+        { type: '1', name: '一分屏', row: 1, col: 1, imgConfig: { maxWidth: 960, maxHeight: 540, quality: 70 } },
+        { type: '2', name: '二分屏', row: 1, col: 2, imgConfig: { maxWidth: 960, maxHeight: 540, quality: 70 } },
+        { type: '4', name: '四分屏', row: 2, col: 2, imgConfig: { maxWidth: 960, maxHeight: 540, quality: 50 } },
+        { type: '9', name: '九分屏', row: 3, col: 3, imgConfig: { maxWidth: 960, maxHeight: 540, quality: 30 } },
+        {
+          type: '6',
+          name: '9分主次屏',
+          row: 3,
+          col: 3,
+          unequal: true,
+          imgConfig: { maxWidth: 960, maxHeight: 540, quality: 30 },
+        },
+        { type: '16', name: '16分屏', row: 4, col: 4, imgConfig: { maxWidth: 720, maxHeight: 405, quality: 20 } },
+        {
+          type: '13',
+          name: '16分主次屏',
+          row: 4,
+          col: 4,
+          unequal: true,
+          imgConfig: { maxWidth: 960, maxHeight: 540, quality: 10 },
+        },
+      ],
+      selectedCodeStreamType: '1',
+      selectedSplitScreenType: '9',
+      isAllScreen: false,
+      rules: {
+        loopFreq: [
+          { required: true, message: '请输入轮询频率', trigger: 'blur' },
+          // 必须是正整数
+          { pattern: /^[1-9]\d*$/, message: '请输入正整数', trigger: 'blur' },
+        ],
+      },
+    }
+  },
+  computed: {},
+  watch: {
+    'configOptions.splitScreenType': {
+      handler(val) {
+        console.log(val)
+        this.$nextTick(() => {
+          setTimeout(() => {
+            const data = this.screenConfig.find(item => item.type === val)
+            this.$EventBus.$emit('updateSplitScreenType', data)
+            this.updatePollFreq()
+          }, 300)
+        })
+      },
+      immediate: true,
+    },
+  },
+  mounted() {},
+  methods: {
+    // 更新选择视频数据
+    updateVideoData() {
+      this.$parent.updateSelectedVideoData({})
+    },
+    // 更新分屏模式
+
+    // 开启关闭轮询
+    handleChangeLoop(val) {
+      if (val) {
+        this.$parent.updateLoop()
+      } else {
+        this.$parent.stopLoop()
+      }
+    },
+    // 更新轮询频率
+    updatePollFreq: debounce(function () {
+      this.$parent.updateLoop()
+    }, 300),
+    setFullScreen(value) {
+      if (value) {
+        this.$emit('update:screenMode', 'full')
+      }
+    },
+  },
+}
+</script>
+<style lang="less" scoped>
+.videoConfig-container {
+  width: 258px;
+  // height: 862px;
+  min-height: 862px;
+  height: calc(100vh - 218px);
+  background: #001f54;
+  border: 1px solid #5bd6ff;
+  padding: 15px 10px;
+
+  ::v-deep .el-form-item {
+    .el-form-item__label {
+      color: #5bd6ff;
+    }
+    .el-switch__core {
+      width: 36px !important;
+      &::after {
+        top: 1px !important;
+      }
+    }
+    .myInput.el-cascader,
+    .myInput.el-select,
+    .myInput.el-input-number {
+      .el-input__inner {
+        // width: 110px;
+        height: 30px;
+        border-radius: 0;
+        background: rgba(0, 20, 23, 0.2);
+        border: 0.5px solid #5bd6ff;
+        color: #5bd6ff;
+        // padding-right: 35px;
+      }
+      .el-input__inner:focus {
+        border: 0.5px solid #5bd6ff !important;
+      }
+      .el-input.is-focus .el-input__inner {
+        border: 0.5px solid #5bd6ff !important;
+      }
+      .el-input__suffix {
+        right: 5px;
+      }
+      .el-input__icon {
+        line-height: 30px;
+      }
+      .el-input-number__decrease,
+      .el-input-number__increase {
+        border-radius: 0;
+        background: rgba(0, 60, 57, 0.3);
+        border-color: #5bd6ff;
+        color: #fff;
+      }
+    }
+    .el-tag {
+      position: absolute;
+      top: 50%;
+      transform: translateY(-50%);
+      border-radius: 0;
+      background: rgba(0, 20, 23, 0.2);
+      border: 0.5px solid #5bd6ff;
+      color: #5bd6ff;
+      span {
+        display: inline-block;
+        max-width: 120px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        // line-height: 20px;
+      }
+      .el-tag__close {
+        top: -6px;
+        right: -3px;
+        color: #5bd6ff;
+        &:hover {
+          color: #fff;
+          background-color: #5bd6ff;
+        }
+      }
+    }
+    span {
+      color: #5bd6ff;
+    }
+    .unit {
+      display: inline-block;
+      margin-left: 10px;
+    }
+  }
+}
+</style>

+ 201 - 0
src/views/videoMonitorType/components/VideoControl.vue

@@ -0,0 +1,201 @@
+<template>
+  <div class="videoControl-container">
+    <div class="comm-panel">
+      <div class="btn-box" v-for="item of commandConfig.direction" :key="item.type">
+        <el-button type="primary" :icon="`el-icon-${item.type}`" size="mini" @mousedown.native="changePtzCommParam(item.command, false)" @mouseup.native="changePtzCommParam(item.command, true)"></el-button>
+      </div>
+    </div>
+    <div class="zoom-panel">
+      <div class="btn-box" v-for="item of commandConfig.zoom" :key="item.type">
+        <el-button type="primary" :icon="`el-icon-${item.type}`" size="mini" @mousedown.native="changePtzCommParam(item.command, false)" @mouseup.native="changePtzCommParam(item.command, true)"></el-button>
+      </div>
+    </div>
+    <div class="form_box">
+      <el-form label-width="70px" size="small">
+        <el-form-item label="速度" prop="speed">
+          <el-select class="myInput" size="mini" v-model="speed" placeholder="请选择速度" style="width: 100%">
+            <el-option v-for="item in Array.from({ length: 10 }, (item, index) => index + 1)" :key="item" :label="item" :value="item"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="预置点" prop="presetIndex">
+          <el-select class="myInput" size="mini" v-model="presetIndex" placeholder="请选择预置点" style="width: 100%">
+            <el-option v-for="item in Array.from({ length: 255 }, (item, index) => index + 1)" :key="item" :label="item" :value="item"></el-option>
+          </el-select>
+        </el-form-item>
+        <div class="btn_box">
+          <el-button type="primary" size="mini" @click="changePtzPresetParam(8)">设置</el-button>
+          <el-button type="primary" size="mini" @click="changePtzPresetParam(39)">转到</el-button>
+        </div>
+        <el-form-item label="时间" prop="startTime">
+          <el-date-picker class="myInput" size="mini" v-model="startTime" type="datetime" placeholder="选择日期时间" style="width: 100%"></el-date-picker>
+        </el-form-item>
+        <div class="btn_box">
+          <el-button type="primary" size="mini" @click="changePlayTypeParam(true)" :disabled="!startTime">回放</el-button>
+          <el-button type="primary" size="mini" @click="changePlayTypeParam(false)" :disabled="!startTime">实时</el-button>
+        </div>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import Dayjs from 'dayjs'
+export default {
+  name: 'VideoControl',
+  props: {
+    curVideoData: {
+      type: Object,
+      require: true,
+      default: () => ({}),
+    },
+  },
+  data() {
+    return {
+      // 视频控制相关 start
+      commandConfig: {
+        //视频控制开关配置
+        direction: [
+          //方向
+          { type: 'top-left', name: '左上', command: 25 },
+          { type: 'top', name: '上', command: 21 },
+          { type: 'top-right', name: '右上', command: 26 },
+          { type: 'back', name: '左', command: 23 },
+          { type: 'rank', name: '中', command: 0 },
+          { type: 'right', name: '右', command: 24 },
+          { type: 'bottom-left', name: '左下', command: 27 },
+          { type: 'bottom', name: '下', command: 22 },
+          { type: 'bottom-right', name: '右下', command: 28 },
+        ],
+        zoom: [
+          //放大缩小
+          { type: 'zoom-in', name: '放大', command: 11 },
+          { type: 'zoom-out', name: '缩小', command: 12 },
+        ],
+      },
+      startTime: null,
+      speed: 5,
+      presetIndex: 1,
+      // 视频控制 end
+    }
+  },
+  mounted() {},
+  methods: {
+    changePtzCommParam(comm, stop) {
+      if (!comm) return
+      if (!this.curVideoData.id) {
+        stop && this.$message.warning('请先选择视频窗口!')
+        return
+      }
+      let param = {
+        id: this.curVideoData.id,
+        ptzCommand: comm,
+        ptzStop: stop,
+        ptzSpeed: this.speed,
+        canControl: this.curVideoData.ptzEnable,
+      }
+      this.$EventBus.$emit('updateSendParam', param)
+    },
+    changePtzPresetParam(comm) {
+      if (!comm) return
+      if (!this.curVideoData.id) {
+        this.$message.warning('请先选择视频窗口!')
+        return
+      }
+      let param = {
+        id: this.curVideoData.id,
+        ptzPreset: comm,
+        ptzPresetIndex: this.presetIndex,
+        canControl: this.curVideoData.ptzEnable,
+      }
+      this.$EventBus.$emit('updateSendParam', param)
+    },
+    /**
+     * state  true代表回放模式
+     */
+    changePlayTypeParam(state) {
+      let param = { id: this.curVideoData.id }
+      if (!this.curVideoData.id) {
+        this.$message.warning('请先选择视频窗口!')
+        return
+      }
+      if (state) {
+        if (!this.startTime) {
+          this.$message.warning('请选择回放开始时间!')
+          return
+        }
+        param['startTime'] = Dayjs(this.startTime).format('YYYY-MM-DD HH:mm:ss')
+      }
+      this.$EventBus.$emit('updateSendParam', param, true)
+    },
+  },
+}
+</script>
+<style lang="less" scoped>
+.videoControl-container {
+  width: 100%;
+  .comm-panel {
+    width: 184px;
+    margin: 0 auto;
+    display: flex;
+    flex-wrap: wrap;
+    .el-button {
+      background: #007ccc;
+      border-color: #007ccc;
+    }
+  }
+  .zoom-panel {
+    width: 122px;
+    margin: 0 auto;
+    display: flex;
+    .el-button {
+      background: #007ccc;
+      border-color: #007ccc;
+    }
+  }
+  .btn-box {
+    flex-shrink: 0;
+    width: 60px;
+    height: 40px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+  .form_box {
+    width: 100%;
+    padding: 10px 0;
+    ::v-deep .el-form {
+      width: 100%;
+      .myInput {
+        .el-input__inner {
+          // width: 110px;
+          height: 30px;
+          border-radius: 0;
+          background: rgba(0, 20, 23, 0.2);
+          border: 0.5px solid #5bd6ff;
+          color: #5bd6ff;
+          // padding-right: 35px;
+        }
+        .el-input__inner:focus {
+          border: 0.5px solid #5bd6ff !important;
+        }
+        .el-input.is-focus .el-input__inner {
+          border: 0.5px solid #5bd6ff !important;
+        }
+        .el-input__suffix {
+          right: 5px;
+        }
+        .el-input__icon {
+          line-height: 30px;
+        }
+      }
+      .btn_box {
+        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        margin-bottom: 12px;
+      }
+    }
+  }
+}
+</style>

+ 284 - 0
src/views/videoMonitorType/components/VideoForensics.vue

@@ -0,0 +1,284 @@
+<template>
+  <div class="videoWindow-container" @scroll="handleScroll">
+    <div v-for="item of displayList" :key="item.id" class="videoWindow-item">
+      <!-- <f-image class="f_image" :src="item.src" :preview-src-list="previewList" fit="fill" @changeIndex="changeIndex">
+        <div class="img_detail_box" v-drag>
+          <div class="detail_title">报警详情</div>
+          <div class="detail_content">
+            <div class="detail_row">
+              <div class="detail_label">报警场站:</div>
+              <div class="detail_value">{{ previewDetail.departmentName }}</div>
+            </div>
+            <div class="detail_row">
+              <div class="detail_label">报警时间:</div>
+              <div class="detail_value">{{ previewDetail.eventTime }}</div>
+            </div>
+            <div class="detail_row">
+              <div class="detail_label">报警类型:</div>
+              <div class="detail_value">{{ previewDetail.typeStr }}</div>
+            </div>
+            <div class="detail_row">
+              <div class="detail_label">是否处理:</div>
+              <div class="detail_value">{{ previewDetail.dealStatusStr }}</div>
+            </div>
+            <div class="detail_row">
+              <div class="detail_label">报警内容:</div>
+              <div class="detail_value">{{ previewDetail.content }}</div>
+            </div>
+          </div>
+        </div>
+      </f-image> -->
+      <div class="desc_box">
+        <div class="desc_row">
+          <span class="label">报警时间:</span>
+          <span class="value">{{ item.eventTime }}</span>
+        </div>
+        <div class="desc_row">
+          <span class="label">报警类型:</span>
+          <span class="value">{{ item.typeStr }}</span>
+        </div>
+        <div class="desc_row">
+          <span class="label">报警内容:</span>
+          <span class="value" :title="item.content">{{ item.content }}</span>
+        </div>
+      </div>
+    </div>
+    <div v-if="loading" class="loading">加载中...</div>
+  </div>
+</template>
+<script>
+// import FImage from '@/components/FImage'
+import { getAlarmDataList } from '@/API/alarm'
+import Dayjs from 'dayjs'
+
+export default {
+  name: 'VideoForensics',
+  components: {  },
+  props: {},
+  data() {
+    return {
+      previewDetail: {},
+      previewList: [],
+      displayList: [],
+      pageSize: 12,
+      currentPage: 1,
+      loading: false,
+      hasMore: true,
+      departmentId: localStorage.getItem('departmentId'),
+    }
+  },
+  computed: {
+    dialogVisible() {
+      return Object.keys(this.previewDetail).length > 0
+    },
+  },
+  mounted() {
+    this.getAlarmDataList()
+  },
+  methods: {
+    changeIndex(i) {
+      this.$set(this, 'previewDetail', this.previewList[i])
+      // console.log(this.previewDetail)
+    },
+    handleScroll(e) {
+      const { scrollHeight, scrollTop, clientHeight } = e.target
+      if (scrollHeight - scrollTop - clientHeight < 100 && !this.loading && this.hasMore) {
+        this.loadMore()
+      }
+    },
+    async loadMore() {
+      if (this.loading) return
+      this.loading = true
+
+      try {
+        const params = {
+          startTime: Dayjs(new Date()).subtract(1, 'week').format('YYYY-MM-DD HH:mm:ss'),
+          endTime: Dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'),
+          category: '100005',
+          pageSize: this.pageSize,
+          pageIndex: this.currentPage,
+          departmentId: this.departmentId,
+        }
+
+        const res = await getAlarmDataList(params)
+        const content = res.data.content || []
+
+        const newItems = content.map(item => ({
+          ...item,
+          src: BASE_URL + item.imageUrl,
+        }))
+
+        this.displayList.push(...newItems)
+        this.previewList.push(...newItems)
+
+        this.hasMore = content.length === this.pageSize
+        this.currentPage++
+      } catch (error) {
+        console.error('加载数据失败:', error)
+      } finally {
+        this.loading = false
+      }
+    },
+    async getAlarmDataList() {
+      this.currentPage = 1
+      this.displayList = []
+      this.previewList = []
+      this.hasMore = true
+      await this.loadMore()
+    },
+  },
+}
+</script>
+<style lang="less" scoped>
+.videoWindow-container {
+  width: 1414px;
+  // height: 862px;
+  min-height: 862px;
+  height: calc(100vh - 218px);
+  background: #001f54;
+  border: 1px solid #5bd6ff;
+  padding: 10px;
+  display: flex;
+  flex-wrap: wrap;
+  overflow-y: auto;
+  // 加入末尾占位符
+  &::after {
+    content: '';
+    display: block;
+    width: 100%;
+    height: 0;
+  }
+
+  .videoWindow-item {
+    width: calc(25% - 8px);
+    height: calc(100% / 3 - 6px);
+    margin-right: 10px;
+    margin-bottom: 10px;
+    padding: 10px;
+    &:nth-child(4n) {
+      margin-right: 0;
+    }
+    // &:nth-child() {
+    //   margin-bottom: 0;
+    // }
+    background: rgba(0, 20, 23, 0.2);
+    border: 1px solid #5bd6ff;
+    color: #fff;
+    font-size: 20px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: flex-start;
+    cursor: pointer;
+    overflow: hidden;
+    .f_image {
+      width: 100%;
+      height: 75%;
+    }
+    .desc_box {
+      height: 25%;
+      width: 100%;
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: flex-start;
+      border: 1px solid #5bd6ff44;
+      border-top-color: transparent;
+      .desc_row {
+        width: 100%;
+        display: flex;
+        justify-content: flex-start;
+        align-items: center;
+        font-size: 12px;
+        .label {
+          width: 70px;
+          text-align: right;
+          opacity: 0.67;
+        }
+        .value {
+          flex: 1;
+          width: calc(100% - 70px);
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+      }
+    }
+  }
+}
+.loading {
+  width: 100%;
+  height: 40px;
+  line-height: 40px;
+  text-align: center;
+  color: #fff;
+}
+</style>
+
+<style lang="less">
+// 缩略图图层位于body之下,不能加scoped
+.img_detail_box {
+  position: absolute;
+  width: 300px;
+  height: 500px;
+  top: 150px;
+  right: 450px;
+  border: 1px solid #5bd6ff;
+  background-color: rgba(0, 37, 118, 0.6);
+  .detail_title {
+    width: 100%;
+    height: 50px;
+    padding-left: 16px;
+    display: flex;
+    align-items: center;
+    color: #7cffff;
+    font-size: 18px;
+    font-weight: 600;
+    position: relative;
+    &::before {
+      content: '';
+      display: block;
+      width: 6px;
+      height: 6px;
+      background-color: #00f9ff;
+      margin-right: 10px;
+      box-shadow: 0 0 6px 0 #00f9ff;
+      border-radius: 1px;
+    }
+    &::after {
+      content: '';
+      display: block;
+      width: 100%;
+      height: 1px;
+      opacity: 0.67;
+      background-image: linear-gradient(90deg, #ffffff 1%, rgba(255, 255, 255, 0) 100%);
+      position: absolute;
+      bottom: 0;
+      left: 0;
+    }
+  }
+  .detail_content {
+    width: 100%;
+    height: 70%;
+    display: flex;
+    flex-direction: column;
+    padding: 10px 20px;
+    .detail_row {
+      width: 100%;
+      min-height: 30px;
+      display: flex;
+      align-items: flex-start;
+      color: #fff;
+      font-size: 16px;
+      font-weight: 400;
+      .detail_label {
+        width: 80px;
+      }
+      .detail_value {
+        width: calc(100% - 80px);
+        flex: 1;
+      }
+    }
+  }
+}
+</style>

+ 151 - 0
src/views/videoMonitorType/components/VideoWindow.vue

@@ -0,0 +1,151 @@
+<template>
+  <div
+    class="videoWindow-container"
+    :style="gridStyle"
+    :class="{
+      small: screenMode === 'small',
+      large: screenMode === 'large',
+      full: screenMode === 'full',
+    }"
+    @dblclick="zoomWindow">
+    <template v-if="gridStyle">
+      <div
+        v-for="item of showVideoList"
+        :key="item.id"
+        class="videoWindow-item"
+        :class="{
+          unequal: unequal,
+          selected: selectedVideoData.id === item.id,
+        }"
+        @click="chooseWindow(item)">
+        <!-- :src="require(`@/assets/imgs/video/${item.url}`)" -->
+        <canvas-video :cameraData="item" :imgConfig="imgConfig" />
+      </div>
+    </template>
+  </div>
+</template>
+
+<script>
+import VideoContent from './videoContent.vue'
+import CanvasVideo from '@/components/ImageVideo/CanvasVideo.vue'
+export default {
+  name: 'VideoWindow',
+  components: { VideoContent, CanvasVideo },
+  props: {
+    showVideoList: {
+      type: Array,
+      default: () => [],
+    },
+    screenMode: {
+      type: String,
+      default: 'large',
+    },
+    selectedVideoData: {
+      type: Object,
+      default: () => ({}),
+    },
+  },
+  data() {
+    return {
+      clickTime: null,
+      splitOption: {}, // 当前分屏模式的配置,从videoConfig组件中传过来
+      gridStyle: '', // 当前分屏模式的样式
+      unequal: false, // 是否主次屏
+      imgConfig: {
+        maxWidth: 960, // 图片最大宽度
+        maxHeight: 540, // 图片最大高度
+        quality: 70, // 图片质量,可选值:high/low
+      },
+    }
+  },
+  computed: {},
+  mounted() {
+    this.$EventBus.$off('updateSplitScreenType')
+    this.$EventBus.$on('updateSplitScreenType', data => {
+      this.setWindowStyle(data)
+      this.setVideoImgQuality(data)
+    })
+  },
+  beforeDestroy() {
+    this.$EventBus.$off('updateSplitScreenType')
+  },
+  methods: {
+    chooseWindow(item) {
+      clearTimeout(this.clickTime)
+      this.clickTime = setTimeout(() => {
+        const data = this.selectedVideoData.id === item.id ? {} : item
+        this.$parent.updateSelectedVideoData(data)
+      }, 300)
+    },
+    zoomWindow() {
+      // console.log("111");
+      clearTimeout(this.clickTime)
+      this.$parent.updateScreenMode()
+    },
+    setWindowStyle(data) {
+      const { row, col, unequal } = data
+      this.splitConfig = data
+      // this.gridStyle = ''
+      setTimeout(() => {
+        this.gridStyle = `grid-template-columns: repeat(${row}, 1fr);grid-template-rows: repeat(${col}, 1fr);`
+        this.unequal = unequal
+      }, 300)
+
+      // this.$forceUpdate()
+    },
+    setVideoImgQuality(data) {
+      // const { imgConfig } = data
+      const { maxWidth, maxHeight, quality } = data.imgConfig
+      this.imgConfig.maxWidth = maxWidth
+      this.imgConfig.maxHeight = maxHeight
+      this.imgConfig.quality = quality
+    },
+  },
+}
+</script>
+<style lang="less" scoped>
+.videoWindow-container {
+  background: #001f54;
+  border: 1px solid #5bd6ff;
+  padding: 10px;
+  display: grid;
+  // grid-template-columns: repeat(3, 1fr);
+  // grid-template-rows: repeat(3, 1fr);
+  gap: 10px;
+  &.small {
+    width: 1138px;
+    // height: 862px;
+    min-height: 862px;
+    height: calc(100vh - 218px);
+  }
+  &.large {
+    width: 100%;
+    min-height: 902px;
+    height: calc(100vh - 178px);
+  }
+  &.full {
+    width: 100vw;
+    height: 100vh;
+    padding: 3px;
+    gap: 3px;
+  }
+  .videoWindow-item {
+    background: rgba(0, 20, 23, 0.2);
+    border: 1px solid #5bd6ff;
+    color: #fff;
+    font-size: 20px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+    overflow: hidden;
+    &.unequal:first-child {
+      grid-column-start: span 2;
+      grid-row-start: span 2;
+    }
+    &.selected {
+      border-color: orangered;
+    }
+  }
+}
+</style>

+ 166 - 0
src/views/videoMonitorType/components/videoContent.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="img-container">
+    <!-- <img :src="url" v-if="url" /> -->
+    <canvas class="canvas_box" ref="canvas" v-if="url" width="960" height="540" />
+    <div class="image-slot" v-else>
+      <i class="el-icon-video-camera"></i>
+      <span>无信号</span>
+      <span>{{ cameraData.name }}</span>
+    </div>
+  </div>
+</template>
+<script>
+import { debounce, throttle } from 'lodash-es'
+export default {
+  props: {
+    cameraData: {
+      type: Object,
+      default: () => ({}),
+    },
+  },
+  data() {
+    return {
+      url: '',
+      ws: null,
+      startTime: null,
+      speed: 4,
+      presetIndex: 1,
+    }
+  },
+  watch: {
+    cameraData: {
+      handler(val) {
+        if (val.id) {
+          this.updateEvent({ id: val.id }, true)
+        }
+      },
+      deep: true,
+      immediate: true,
+    },
+  },
+  mounted() {
+    this.$EventBus.$off('updateSendParam')
+    this.$EventBus.$on('updateSendParam', (data, state) => {
+      if (data.id === this.cameraData.id) {
+        this.updateEvent(data, state)
+      }
+    })
+  },
+  beforeDestroy() {
+    this.closeHandler()
+  },
+  methods: {
+    init(str) {
+      // this.socketList[`ws_${this.cameraData.id}`];
+      const host = VUE_APP_BASE_WS() + '/VideoOverWebSocket'
+      this.ws = new WebSocket(host)
+      this.ws.onmessage = evt => {
+        if (typeof evt.data === 'string') {
+          console.log(JSON.parse(evt.data).Msg)
+        } else {
+          this.url = URL.createObjectURL(evt.data)
+          this.$nextTick(() => {
+            this.updateUrl()
+          })
+        }
+      }
+      this.handleSend(str)
+      // console.log(window);
+    },
+    updateUrl() {
+      const canvas = this.$refs.canvas
+      const ctx = canvas.getContext('2d')
+      const img = new Image()
+      // console.log('canvas', canvas.width, canvas.height)
+
+      img.src = this.url
+      img.onload = () => {
+        // console.log('img', img.width, img.height)
+        const canvasRatio = canvas.width / canvas.height
+        const imgRatio = img.width / img.height
+        if (imgRatio > canvasRatio) {
+          // 图片宽高比大于画布宽高比,以宽度为基准进行缩放
+          const newWidth = canvas.width
+          const newHeight = newWidth / canvasRatio
+          ctx.clearRect(0, 0, newWidth, newHeight)
+          ctx.drawImage(img, 0, (canvas.height - newHeight) / 2, newWidth, newHeight)
+        } else {
+          // 图片宽高比小于等于画布宽高比,以高度为基准进行缩放
+          const newHeight = canvas.height
+          const newWidth = newHeight * canvasRatio
+          ctx.clearRect(0, 0, newWidth, newHeight)
+          ctx.drawImage(img, (canvas.width - newWidth) / 2, 0, newWidth, newHeight)
+        }
+      }
+    },
+    // 100),
+    handleSend(str) {
+      if (this.ws.readyState === WebSocket.OPEN) {
+        this.ws.send(str)
+      } else if (this.ws.readyState == WebSocket.CONNECTING) {
+        // Wait for the open event, maybe do something with promises
+        // depending on your use case. I believe in you developer!
+        this.ws.addEventListener('open', () => this.handleSend(str))
+      } else {
+        // etc.
+      }
+    },
+    updateEvent(data, state) {
+      const param = JSON.stringify(data)
+      if (this.ws && this.ws.readyState == 1) {
+        this.handleSend(param)
+      } else {
+        this.init(param)
+      }
+      if (state) {
+        setTimeout(() => {
+          this.url = ''
+        }, 500)
+      }
+    },
+    closeHandler() {
+      this.ws && this.ws.close()
+      setTimeout(() => {
+        if (this.url) URL.revokeObjectURL(this.url)
+        this.url = ''
+        this.ws.onclose = evt => {
+          this.ws = null
+          console.log('websocket已关闭')
+        }
+      }, 500)
+    },
+  },
+}
+</script>
+
+<style lang="less" scoped>
+.img-container {
+  width: 100%;
+  height: 100%;
+  img {
+    width: 100%;
+    height: 100%;
+    object-fit: fill;
+    // display: block;
+  }
+  .canvas_box {
+    width: 100%;
+    height: 100%;
+  }
+  .image-slot {
+    width: 100%;
+    height: 100%;
+    // background-color: #f5f7fa;
+    color: #5bd6ff;
+    font-size: 24px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    font-weight: 500;
+    span {
+      font-size: 16px;
+    }
+  }
+}
+</style>

+ 346 - 0
src/views/videoMonitorType/index.vue

@@ -0,0 +1,346 @@
+<template>
+  <div class="videoMonitor-container" :class="{ full: screenMode === 'full' }">
+    <div class="btns-container" v-show="screenMode === 'small'">
+      <div
+        class="btn-box"
+        v-for="btn of btnConfig"
+        :key="btn.type"
+        @click="changeVideoType(btn)"
+      >
+        <img
+          :src="getImageSrc(btn.type)"
+          alt=""
+          :class="{ disable: btn.disable }"
+        />
+      </div>
+    </div>
+    <div class="videoMonitor-main">
+      <station-select
+        ref="stationSelect"
+        :videoList="videoList"
+        v-show="screenMode === 'small'"
+        @selectNode="selectNode"
+      />
+      <video-forensics
+        ref="videoForensics"
+        v-if="curVideoType === 'playback'"
+      />
+      <template v-else>
+        <video-window
+          ref="videoWindow"
+          :showVideoList="showVideoList"
+          :screenMode.sync="screenMode"
+          v-bind="{ ...configOptions }"
+        />
+        <video-config
+          v-show="screenMode === 'small'"
+          :screenMode.sync="screenMode"
+          :configOptions="configOptions"
+        />
+      </template>
+    </div>
+  </div>
+</template>
+
+<script>
+import StationSelect from "./components/StationSelect.vue";
+import VideoConfig from "./components/VideoConfig.vue";
+import VideoWindow from "./components/VideoWindow.vue";
+import VideoForensics from "./components/VideoForensics.vue";
+import { getCameraList } from "@/API/custom.js";
+import { cloneDeep, orderBy } from "lodash-es";
+export default {
+  name: "videoMonitor",
+  components: {
+    VideoWindow,
+    VideoForensics,
+    VideoConfig,
+    StationSelect,
+  },
+  data() {
+    return {
+      btnConfig: [
+        { name: "实时视频", type: "realtime" },
+        { name: "智能AI", type: "playback" },
+        //  { name: '视频轮询', type: 'rotationpatrol' },
+      ],
+      curVideoType: "realtime", //当前视频模式
+      videoList: [], //所有摄像头
+      showVideoList: [], //当前展示的摄像头
+      timer: null,
+      curIndex: 0,
+      screenMode: "large", // 窗口展示大小模式  full/large/small
+      // videoConfig组件中的所有数据项
+      configOptions: {
+        splitScreenType: "9", // 分屏模式
+        codeStreamType: "1", // 码流格式
+        isLoop: true, // 是否循环播放
+        loopFreq: 30, // 循环播放频率
+        isFullScreen: false, // 是否全屏-隐藏头部
+        selectedVideoData: {}, // 选择的视频窗口数据
+      },
+      query: {
+        departmentId: "",
+        useType: "",
+      },
+    };
+  },
+  watch: {
+    screenMode(val) {
+      this.configOptions.isFullScreen = val === "full";
+      // this.$parent.fullScreen = val === 'full'
+      // this.$parent.setHeaderVisible()
+      const pageSizeMode = val === "full" ? "full" : "normal";
+      // this.$store.dispatch('home/setPageSizeMode', pageSizeMode)
+    },
+    $route(to, from) {
+      //你在create里的方法
+      //你在mounted里的方法
+      this.stopLoop();
+      console.log("视频路由参数", this.$route);
+      if (!!this.$route.query && this.$route.query !== "{}") {
+        if (!!this.$route.query.did) {
+          this.query.departmentId = this.$route.query.did;
+        } else {
+          this.query.departmentId = "";
+        }
+        if (!!this.$route.query.type) {
+          this.query.useType = this.$route.query.type;
+        } else {
+          this.query.useType = "";
+        }
+        this.getCameraList();
+      } else {
+        console.log("视频路由无参数", this.$route);
+
+        this.query = {
+          departmentId: "",
+          useType: "",
+        };
+        this.getCameraList();
+      }
+      setTimeout(() => {
+        this.startLoop();
+      }, 1000);
+    },
+  },
+  mounted() {
+    if (!!this.$route.query.did) {
+      this.query.departmentId = this.$route.query.did;
+    } else {
+      this.query.departmentId = "";
+    }
+    if (!!this.$route.query.type) {
+      this.query.useType = this.$route.query.type;
+    } else {
+      this.query.useType = "";
+    }
+    this.getCameraList();
+  },
+  beforeDestroy() {
+    this.stopLoop();
+  },
+  methods: {
+    getImageSrc(type) {
+      return require(`@/assets/imgs/video/btn_${type}_${
+        type === this.curVideoType ? "sel" : "nor"
+      }@2x.png`);
+    },
+    async getCameraList() {
+      try {
+        // console.log("ddd", this.$route.query.did);
+        const res = await getCameraList({
+          pageIndex: 1,
+          pageSize: 100,
+          listOrder: ["ip,asc"],
+          departmentId: this.query.departmentId, //按照部门筛选
+          useType: this.query.useType, //按照用途类型筛选
+        });
+        const content = res.data?.content || [];
+        // 暂时屏蔽掉没信号的摄像头,否则会导致服务崩溃
+        // const tData = content.filter(c => {
+        //   // return true
+        //   return !NO_SINGLE_CAMERA.includes(c?.name)
+        // })
+        this.videoList = content;
+        // this.sortVideoList()
+      } catch (error) {
+        console.log("getCameraList error", error);
+      }
+    },
+    changeVideoType(data) {
+      const { type, disable } = data;
+      if (disable) return;
+      this.curVideoType = type;
+      if (type === "playback") {
+        this.stopLoop();
+        // this.$refs.stationSelect.setTreeValue(null)
+      } else {
+        this.updateLoop();
+      }
+    },
+    startLoop() {
+      this.buildShowVideoList();
+      this.timer = setInterval(() => {
+        // console.log('loop')
+        this.buildShowVideoList();
+      }, this.configOptions.loopFreq * 1000);
+    },
+
+    stopLoop() {
+      this.timer && clearInterval(this.timer);
+      this.timer = null;
+    },
+    // 更新循环状态
+    updateLoop() {
+      const { isLoop } = this.configOptions;
+      if (isLoop) {
+        this.stopLoop();
+        this.startLoop();
+      } else {
+        this.buildShowVideoList();
+      }
+    },
+    /**
+     * 循环展示视频窗口
+     * curIndex是当前的窗口索引
+     * range 是展示的窗口个数
+     * videoList是所有摄像头列表
+     * 1、如果摄像头总数小于窗口个数,直接展示所有摄像头
+     * 2、如果摄像头总数大于窗口个数,循环展示
+     * 3、每次循环展示一组range个摄像头
+     * 4、每次循环后,curIndex+range
+     * 5、如果curIndex+range大于总数,则尾头相连,用头部的补齐range个窗口
+     */
+    buildShowVideoList() {
+      const range = +this.configOptions.splitScreenType;
+      const listLength = this.videoList.length;
+      // 如果开启了轮询
+      if (this.configOptions.isLoop && this.timer) {
+        // 更新当前索引,进行下一轮循环
+        this.curIndex = (this.curIndex + range) % listLength;
+        // 清空选中摄像头
+        this.updateSelectedVideoData({});
+      }
+      // 如果摄像头总数小于窗口个数,直接展示所有摄像头
+      if (listLength <= range) {
+        this.showVideoList = this.videoList.slice();
+        if (this.configOptions.isLoop && this.timer) {
+          // 停止轮询
+          console.log("摄像头总数小于窗口个数,停止轮询");
+          // this.stopLoop()
+          this.configOptions.isLoop = false;
+        }
+      } else {
+        //
+        const endIndex = (this.curIndex + range) % listLength;
+        // 展示范围内的摄像头列表
+        if (this.curIndex < endIndex) {
+          this.showVideoList = this.videoList.slice(this.curIndex, endIndex);
+        } else {
+          // 当索引超出列表长度时,进行尾头相连展示
+          this.showVideoList = this.videoList
+            .slice(this.curIndex)
+            .concat(this.videoList.slice(0, endIndex));
+        }
+      }
+
+      this.$nextTick(() => {
+        // 获取展示列表中的第一个摄像头的id
+        const firstId = this.showVideoList?.[0]?.id;
+        // 设置树形选择器的值为第一个摄像头的id
+        this.$refs.stationSelect.setTreeValue(firstId);
+      });
+      // console.log(this.curIndex, this.showVideoList?.[0])
+    },
+    // 树形选择器回调
+    selectNode({ id, departmentId }) {
+      // 智能AI模式下,筛选场站下的报警,功能不完善,暂时不加
+      // if (this.curVideoType === 'playback') {
+      //   this.$refs.videoForensics.departmentId = departmentId
+      //   this.$refs.videoForensics.getAlarmDataList()
+      //   return
+      // }
+      this.curIndex = this.videoList.findIndex((v) => v.id === id);
+      if (this.configOptions.selectedVideoData?.id !== id) {
+        this.updateSelectedVideoData({});
+      }
+      this.updateLoop();
+    },
+    // 更新选中摄像头数据
+    updateSelectedVideoData(data) {
+      this.configOptions.selectedVideoData = cloneDeep(data);
+    },
+    /**
+     * 更新屏幕模式
+     *
+     * @param mode 屏幕模式,full/large/small
+     * @returns 无返回值
+     */
+    updateScreenMode() {
+      switch (this.screenMode) {
+        case "full":
+          this.screenMode = "small";
+          break;
+        case "small":
+          this.screenMode = "large";
+          break;
+        case "large":
+          this.screenMode = "small";
+          break;
+        default:
+          break;
+      }
+    },
+    // 摄像头列表排序
+    sortVideoList(type) {
+      const param = type === "1" ? ["buildId", "sort"] : ["useType", "sort"];
+      this.videoList = orderBy(this.videoList, param, ["asc", "asc"]);
+      this.curIndex = 0;
+      this.updateLoop();
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.videoMonitor-container {
+  width: 100%;
+  height: 100%;
+  padding: 110px 90px 0;
+  // background: #001012;
+  pointer-events: auto;
+  position: absolute;
+  z-index: 0;
+  &.full {
+    padding: 0;
+    .videoMonitor-main {
+      margin: 0;
+    }
+  }
+  .btns-container {
+    width: 100%;
+    height: 40px;
+    display: flex;
+    .btn-box {
+      width: 147px;
+      height: 40px;
+      margin-right: 10px;
+      cursor: pointer;
+      img {
+        width: 100%;
+        height: 100%;
+        &.disable {
+          filter: grayscale(100%);
+          cursor: not-allowed;
+        }
+      }
+    }
+  }
+  .videoMonitor-main {
+    margin-top: 20px;
+    display: flex;
+    justify-content: space-between;
+  }
+}
+</style>

+ 10 - 4
vue.config.js

@@ -19,11 +19,14 @@ module.exports = {
       '/yapi': {
       '/yapi': {
         // target: 'http://39.101.177.49:5013/', // 远程服务器-皞哥
         // target: 'http://39.101.177.49:5013/', // 远程服务器-皞哥
         // target: 'http://127.0.0.1:18201/prod-api/', // 贵州现场
         // target: 'http://127.0.0.1:18201/prod-api/', // 贵州现场
+        // target: 'http://11.100.46.218:8080/prod-api/', // 贵都匀现场
         // target: 'http://11.100.46.220:8080/prod-api/', // 贵州现场
         // target: 'http://11.100.46.220:8080/prod-api/', // 贵州现场
         // target: 'http://192.168.1.10:8080/prod-api/', // 贵州现场
         // target: 'http://192.168.1.10:8080/prod-api/', // 贵州现场
-        // target: 'http://192.168.195.133:8080/prod-api/', // 贵州现场
+        target: 'http://192.168.18.219:22102/prod-api/', // 都匀转发
+        // target: 'http://192.168.18.219:22100/prod-api/', // 托克托转发
+        // target: 'http://192.168.195.134:8080/prod-api/', // 贵州现场
         // target: 'http://172.168.0.62:8080/prod-api/', // 托克托现场
         // target: 'http://172.168.0.62:8080/prod-api/', // 托克托现场
-        target: 'http://192.168.195.136:8080/prod-api/', // 托克托本地
+        // target: 'http://192.168.195.136:8080/prod-api/', // 托克托本地
         // target: 'http://192.168.1.10:8080/prod-api/', // 贵州现场
         // target: 'http://192.168.1.10:8080/prod-api/', // 贵州现场
         // target: 'http://11.100.46.220:8080/prod-api/', // 贵州现场
         // target: 'http://11.100.46.220:8080/prod-api/', // 贵州现场
         // target: "http://localhost:5002", // 远程服务器-赵哥
         // target: "http://localhost:5002", // 远程服务器-赵哥
@@ -37,13 +40,16 @@ module.exports = {
         // target: 'http://39.101.177.49:5013/model/', //模型服务器
         // target: 'http://39.101.177.49:5013/model/', //模型服务器
         // target: 'http://127.0.0.1:18202/model/', //贵州现场
         // target: 'http://127.0.0.1:18202/model/', //贵州现场
         // target: 'http://11.100.46.220:8081/model/', //都匀现场
         // target: 'http://11.100.46.220:8081/model/', //都匀现场
+        // target: 'http://11.100.46.218:8081/model/', //都匀现场
         // target: "http://192.168.70.11:8081/model/", // 静海现场
         // target: "http://192.168.70.11:8081/model/", // 静海现场
         // target: "http://localhost:8000/model/", // 济北综合站现场服务器
         // target: "http://localhost:8000/model/", // 济北综合站现场服务器
         // target: 'http://11.100.46.220:8081/model/', //贵阳模型服务器
         // target: 'http://11.100.46.220:8081/model/', //贵阳模型服务器
         // target: 'http://192.168.1.10:8081/model/', //贵阳模型服务器
         // target: 'http://192.168.1.10:8081/model/', //贵阳模型服务器
-        // target: 'http://192.168.195.133:8081/model/', //贵阳模型服务器
+        target: 'http://192.168.18.219:22101/model/', //托克托模型服务器转发
+        // target: 'http://192.168.18.219:22103/model/', //都匀模型服务器转发
+        // target: 'http://192.168.195.134:8081/model/', //模型服务器
         // target: 'http://172.168.0.62:8081/model/', //托克托模型现场服务器
         // target: 'http://172.168.0.62:8081/model/', //托克托模型现场服务器
-        target: 'http://192.168.195.136:8081/model/', //托克托模型服务器
+        // target: 'http://192.168.195.136:8081/model/', //托克托模型服务器
         changeOrigin: true,
         changeOrigin: true,
         pathRewrite: {
         pathRewrite: {
           '^/model': '/',
           '^/model': '/',

Some files were not shown because too many files changed in this diff