Ver Fonte

视频监控与地图联动

Hwf há 4 meses atrás
pai
commit
daf7eae41a

+ 6 - 1
src/components/TimeAxis/index.vue

@@ -538,6 +538,11 @@ const clearObj = () => {
   }
 };
 
+const clearData = () => {
+  timeAxisState.data = [];
+  clearObj();
+};
+
 onMounted(() => {
   getInitTime();
 });
@@ -546,7 +551,7 @@ onUnmounted(() => {
   clearObj();
 });
 
-defineExpose({ initDataToPlay });
+defineExpose({ initDataToPlay, clearData });
 </script>
 
 <style lang="scss" scoped>

+ 46 - 27
src/store/modules/map.ts

@@ -46,6 +46,8 @@ export const useMapStore = defineStore('map', () => {
     dict_value: [],
     option: ''
   });
+  // 是否需要触发点击菜单
+  const updateMenu = ref({});
   // 设置地图加载完成状态
   const setMapLoaded = (loaded: boolean) => {
     mapLoaded.value = loaded;
@@ -73,46 +75,61 @@ export const useMapStore = defineStore('map', () => {
   };
   // 更多视频界面、设置视频打点标识
   const setPointParams = (dictValue: string) => {
-    if (dictValue !== '573204ca-e814-11ef-a825-fa163e4bf12e' && !pointParams.value.dict_value.includes(dictValue)) {
-      // 还没选中,则进入选中
-      const data = menuData.value;
-      let shouldBreak = false;
-      for (let i = 0; i < data.length; i++) {
-        if (data[i].children && data[i].children.length > 0) {
-          const data2 = data[i].children;
-          for (let k = 0; k < data2.length; k++) {
-            if (data2[k].name === '图像资源') {
-              if (data2[k].children && data2[k].children.length > 0) {
-                const data3 = data2[k].children;
-                for (let z = 0; z < data3.length; z++) {
-                  // if (dictValue === data3[z].name) {
-                  if (dictValue === '7' && data3[z].name === '台风视频') {
-                    data3[z].checked = true;
-                    shouldBreak = true;
-                    pointParams.value.dict_value.push(dictValue);
-                    break;
-                  }
-                }
-                if (shouldBreak) {
-                  break;
+    const data = menuData.value;
+    let shouldBreak = false;
+    for (let i = 0; i < data.length; i++) {
+      if (data[i].children && data[i].children.length > 0) {
+        const data2 = data[i].children;
+        for (let k = 0; k < data2.length; k++) {
+          if (data2[k].name === '图像资源') {
+            shouldBreak = true;
+            if (data2[k].children && data2[k].children.length > 0) {
+              const data3 = data2[k].children;
+              let selectItem = {};
+              for (let z = 0; z < data3.length; z++) {
+                if (dictValue === data3[z].component) {
+                  data3[z].checked = true;
+                  selectItem = data3[z];
+                } else {
+                  data3[z].checked = false;
                 }
               }
+              updateMenu.value = [selectItem];
+              menuState.value.menuData = [selectItem];
+              menuState.value.activeIndex = menuState.value.menuData.findIndex((item) => {
+                return item.name === selectItem.name;
+              });
+              menuState.value.showMenu = true;
+              pointParams.value.dict_value = [dictValue];
+              if (shouldBreak) {
+                break;
+              }
             }
           }
-          if (shouldBreak) {
-            break;
-          }
+        }
+        if (shouldBreak) {
+          break;
         }
       }
     }
   };
+  const setUpdateMenu = (obj: object) => {
+    updateMenu.value = obj;
+  };
   // 打点option变化
   const setPointOption = () => {
     const path = [];
-    pointType.value.forEach((item) => {
-      path.push(item.component);
+    const path2 = [];
+    pointType.value.forEach((item: any) => {
+      if (item.isVideo) {
+        path2.push(item.component);
+      } else {
+        path.push(item.component);
+      }
     });
     pointParams.value.option = path.toString();
+    //合并到视频类别里
+    pointParams.value.dict_value = path2;
   };
   // 初始化左侧菜单数据
   const initMenuData = () => {
@@ -180,6 +197,7 @@ export const useMapStore = defineStore('map', () => {
     mapLoaded,
     activeMap,
     isAMap,
+    updateMenu,
     showMask,
     AMapType,
     YMapType,
@@ -194,6 +212,7 @@ export const useMapStore = defineStore('map', () => {
     setTrackState,
     setIsMapSelect,
     initData,
+    setUpdateMenu,
     setPointParams,
     setPointOption,
     handleCancelAllChecked

+ 0 - 18
src/types/components.d.ts

@@ -24,20 +24,15 @@ declare module 'vue' {
     DistributionMap: typeof import('./../components/Map/YztMap/DistributionMap.vue')['default']
     DrawMap: typeof import('./../components/Map/YztMap/DrawMap.vue')['default']
     Editor: typeof import('./../components/Editor/index.vue')['default']
-    ElAnchor: typeof import('element-plus/es')['ElAnchor']
-    ElAnchorLink: typeof import('element-plus/es')['ElAnchorLink']
     ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
     ElBadge: typeof import('element-plus/es')['ElBadge']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
-    ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton']
     ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
-    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
-    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDivider: typeof import('element-plus/es')['ElDivider']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
@@ -50,36 +45,23 @@ declare module 'vue' {
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElInput: typeof import('element-plus/es')['ElInput']
-    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElMenu: typeof import('element-plus/es')['ElMenu']
     ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
     ElPopover: typeof import('element-plus/es')['ElPopover']
-    ElRadio: typeof import('element-plus/es')['ElRadio']
-    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
     ElRow: typeof import('element-plus/es')['ElRow']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
-    ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
-    ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
     ElSlider: typeof import('element-plus/es')['ElSlider']
-    ElStep: typeof import('element-plus/es')['ElStep']
-    ElSteps: typeof import('element-plus/es')['ElSteps']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
-    ElTable: typeof import('element-plus/es')['ElTable']
-    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
-    ElTabPane: typeof import('element-plus/es')['ElTabPane']
-    ElTabs: typeof import('element-plus/es')['ElTabs']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
     ElTimeline: typeof import('element-plus/es')['ElTimeline']
     ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
-    ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElTree: typeof import('element-plus/es')['ElTree']
-    ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     ExcelEditor: typeof import('./../components/ExcelEditor/index.vue')['default']
     FileUpload: typeof import('./../components/FileUpload/index.vue')['default']

+ 7 - 4
src/views/emergencyCommandMap/LeftSection/VideoMonitorEdit.vue

@@ -99,7 +99,6 @@
 
 <script lang="ts" setup>
 import { getUserVideoPoints, getVideoFromList, getVideoListNew, updateUserVideoPoints } from '@/api/videoMonitor';
-import { deepClone } from '@/utils';
 import useAppStore from '@/store/modules/app';
 import useMapStore from '@/store/modules/map';
 import HKVideo from '@/components/HKVideo/index2.vue';
@@ -163,9 +162,6 @@ const getList = (flag?: boolean) => {
   getVideoListNew(newParams).then((res) => {
     dialogListData.value = res.data;
     total.value = res.total;
-    getUserVideoPoints().then((res2) => {
-      editData.value = deepClone(res2.data.videoInfos);
-    });
   });
 };
 const getVideoInfoList = () => {
@@ -208,6 +204,7 @@ const resetQuery = () => {
 // 开启编辑视频
 const activeEdit = () => {
   editVideo.value = true;
+  getUserPoint();
 };
 // 关闭编辑
 const handleCancel = () => {
@@ -234,8 +231,14 @@ const handleUpdateTags = (item, data) => {
   item.tagLabels = labels.toString();
   emits('change');
 };
+const getUserPoint = () => {
+  getUserVideoPoints().then((res) => {
+    editData.value = res.data.videoInfos;
+  });
+};
 onMounted(() => {
   getList();
+  getUserPoint();
   getVideoInfoList();
   getVideoFromList().then((res) => {
     videoFromList.value = res.rows;

+ 5 - 1
src/views/globalMap/LeftMenu.vue

@@ -229,6 +229,10 @@ const handleClick = (item) => {
   emits('clickMenu', item, menuData.value);
 };
 
+const setMenuIndex = (index) => {
+  menuState.activeIndex = index;
+}
+
 const setMenuChange = (item, flag) => {
   for (let i = 0; i < menuData.value.length; i++) {
     if (item.meta.title === menuData.value[i].meta.title) {
@@ -272,7 +276,7 @@ const handleCancelAllChecked = () => {
   // 清空所有打点
   mapUtils.clearMarker('point');
 };
-defineExpose({ setMenuChange });
+defineExpose({ setMenuChange, setMenuIndex });
 </script>
 
 <style lang="scss" scoped>

+ 177 - 0
src/views/globalMap/RightMenu/CommonVideo.vue

@@ -0,0 +1,177 @@
+<template>
+  <div class="menu-content">
+    <div class="container">
+      <div class="gradient-text common-dialog-title2">{{ title }}</div>
+      <div class="box-left">
+        <el-input v-model="queryParams.keyword" class="custom-input" placeholder="搜索" @input="initData">
+          <template #prefix>
+            <el-icon class="el-input__icon"><search /></el-icon>
+          </template>
+        </el-input>
+        <div class="btn" @click="handleCancel">取消</div>
+      </div>
+      <div class="custom-table">
+        <div class="th">
+          <div class="td">
+            <div style="width: 240px">
+              <el-select
+                v-model="queryParams.area"
+                placeholder="所有区县"
+                size="large"
+                class="custom-select2"
+                popper-class="custom-select-popper2"
+                :teleported="false"
+                @change="initData"
+              >
+                <el-option label="所有区县" value="" />
+                <el-option v-for="item in district_type" :key="item.value" :label="item.label" :value="item.label" />
+              </el-select>
+            </div>
+          </div>
+          <div class="td">名称</div>
+        </div>
+        <div class="table-content">
+          <div v-for="(item, index) in listData" :key="index" class="tr" @click="handleShowDialog(item)">
+            <div class="td">{{ item.area }}</div>
+            <div class="td">{{ item.name }}</div>
+          </div>
+        </div>
+      </div>
+      <Dialog v-if="showDialog" v-model="showDialog" type="md" height="720px" :title="title" hide-footer>
+        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center">
+          <HKVideo :dot_data="videoMonitorData" />
+        </div>
+      </Dialog>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { Search } from '@element-plus/icons-vue';
+import { getRescue } from '@/api/globalMap/mitigation';
+import { deepClone } from '@/utils';
+
+const props = defineProps({
+  title: String
+});
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { district_type } = toRefs<any>(proxy?.useDict('district_type'));
+const queryParams = reactive({
+  current: 1,
+  size: 10,
+  keyword: '',
+  area: ''
+});
+const total = ref(0);
+
+const listData = ref([]);
+
+let showDialog = ref(false);
+let videoMonitorData = ref({});
+const handleShowDialog = (row) => {
+  showDialog.value = false;
+  nextTick(() => {
+    videoMonitorData.value = row;
+    showDialog.value = true;
+  });
+};
+const handleCancel = () => {
+  queryParams.keyword = '';
+  initData();
+};
+const initData = () => {
+  let newQueryParams = deepClone(queryParams);
+  newQueryParams.query = {
+    area: queryParams.area,
+    keyword: queryParams.keyword
+  };
+  delete newQueryParams.area;
+  delete newQueryParams.keyword;
+  getRescue(newQueryParams).then((res) => {
+    listData.value = res.rows;
+    total.value = res.total;
+  });
+};
+initData();
+</script>
+
+<style lang="scss" scoped>
+.menu-content {
+  width: 574px;
+  height: 581px;
+  background: url('@/assets/images/map/rightMenu/content.png') no-repeat;
+  background-size: 100% 100%;
+  padding: 60px 10px 10px 15px;
+  font-size: 14px;
+  position: relative;
+  color: #ffffff;
+  .box-left {
+    display: flex;
+    align-items: center;
+    margin-bottom: 10px;
+    .btn {
+      width: 59px;
+      height: 23px;
+      background: url('@/assets/images/map/rightMenu/potentialFloodHazard/btn.png') no-repeat;
+      background-size: 100% 100%;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      cursor: pointer;
+      margin-left: 20px;
+    }
+  }
+}
+.custom-table {
+  width: 550px;
+  .table-content {
+    height: 420px;
+    overflow-y: auto;
+    overflow-x: hidden;
+  }
+  .th {
+    background: url('@/assets/images/map/rightMenu/th.png') no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+    padding: 7px 12px;
+    height: 32px;
+  }
+  .tr {
+    background: url('@/assets/images/map/rightMenu/td.png') no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+    padding: 7px 12px;
+    &:hover {
+      background: url('@/assets/images/map/rightMenu/td_checked.png') no-repeat;
+      background-size: 100% 100%;
+    }
+  }
+  .td {
+    flex: 1;
+    color: #edfaff;
+    font-size: 14px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+  }
+  .td-text {
+    /* 设置字体透明 */
+    color: transparent;
+    /* 使用 -webkit-background-clip 属性将背景剪裁至文本形状 */
+    -webkit-background-clip: text;
+    /* 非Webkit内核浏览器需要使用标准前缀 */
+    background-clip: text;
+    font-family: 'YouSheBiaoTiHei';
+    /* 设置线性渐变,从红色渐变到蓝色 */
+    background-image: linear-gradient(to bottom, #ffffff 50%, #3075d3 100%);
+    font-size: 14px;
+  }
+  .text-green {
+    background-image: linear-gradient(to bottom, #ffffff 50%, #40c75f 100%);
+  }
+  .text-danger {
+    background-image: linear-gradient(to bottom, #ffffff 50%, #ff2f3c 100%);
+  }
+}
+</style>

+ 4 - 2
src/views/globalMap/RightMenu/index.vue

@@ -97,6 +97,8 @@
         <TyphoonVideo v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '台风视频'" @handle-menu="handleMenu" />
         <RescueTeam v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '救援队伍'" />
         <WindMonitor v-if="menuState.showMenu && menuState.menuData[menuState.activeIndex]?.name === '大风监测'" />
+        <!--图像资源下视频通用组件-->
+        <CommonVideo v-if="!!menuState.menuData[menuState.activeIndex]?.isVideo" :title="menuState.menuData[menuState.activeIndex]?.name" />
       </div>
     </div>
   </div>
@@ -113,7 +115,6 @@ import OnlinePlotting from './OnlinePlotting/index.vue';
 import FixedPointAnalysis from './FixedPointAnalysis.vue';
 import UAV from './UAV/index.vue';
 import WarningInfo from './WarningInfo.vue';
-import { PointType } from '@/api/globalMap/type';
 import RainMonitor from './RainMonitor/index.vue';
 import PreventDrowning from './PreventDrowning.vue';
 import Fireproofing from './Fireproofing.vue';
@@ -131,7 +132,8 @@ import Helicopter from './Helicopter.vue';
 import TyphoonVideo from './TyphoonVideo.vue';
 import RescueTeam from './RescueTeam.vue';
 import TrafficVideo from './TrafficVideo.vue';
-import WindMonitor from './WindMonitor/index.vue'
+import WindMonitor from './WindMonitor/index.vue';
+import CommonVideo from './CommonVideo.vue';
 import useMapStore from '@/store/modules/map';
 
 const emits = defineEmits(['update:drawing']);

+ 28 - 36
src/views/globalMap/index.vue

@@ -141,9 +141,7 @@ const addMarkersMethod = debounce(
       latitude_max: '',
       longitude_min: '',
       longitude_max: '',
-      // option: '22',
       option: mapStore.pointParams.option,
-      // dict_value: 'slfh'
       dict_value: mapStore.pointParams.dict_value.toString()
     };
     if (!queryParams.option && !queryParams.dict_value) {
@@ -209,47 +207,35 @@ const clickMenu = (item, dataList) => {
     }
     rightMenuRef.value.updateMenu(item.checked ? '1' : '2', item);
   } else if (item.path === '2') {
-    let checked = item.checked ? '1' : '2';
-    // 打点信息
-    addMarkers(item);
-    if (
-      [
-        '易涝隐患点',
-        '省政务无人机',
-        '铁塔运行监测',
-        // '物资与装备',
-        '通讯保障',
-        '路网视频',
-        '江湖河库',
-        '防溺水',
-        // '森林防火',
-        '森防视频',
-        '防灾救援',
-        '救援队伍',
-        '交通局视频',
-        '重点车辆'
-      ].includes(item.name)
-    ) {
-      rightMenuRef.value.updateMenu(checked, item);
+    if (item.name === '附近视频') {
+      // 附近视频
+      tempMenu.value = item;
+      //为地图注册click事件获取鼠标点击出的经纬度坐标
+      map.on('click', handleClickMap);
+      mapStore.setIsMapSelect(true);
     } else {
-      let index = findChecked(dataList, item.name);
-      if (item.checked && index > 0) {
-        // 已有图层分析直接切换到该index
-        rightMenuRef.value.showIndexMenu('图层分析');
-      } else if (item.checked || (!item.checked && index === 0)) {
-        rightMenuRef.value.updateMenu(checked, { name: '图层分析', meta: { icon: 'icon1' } });
+      let checked = item.checked ? '1' : '2';
+      // 打点信息
+      addMarkers(item);
+      if (['易涝隐患点', '省政务无人机', '铁塔运行监测', '通讯保障', '救援队伍', '重点车辆'].includes(item.name) || item.isVideo) {
+        rightMenuRef.value.updateMenu(checked, item);
+      } else {
+        let index = findChecked(dataList, item.name);
+        if (item.checked && index > 0) {
+          // 已有图层分析直接切换到该index
+          rightMenuRef.value.showIndexMenu('图层分析');
+        } else if (item.checked || (!item.checked && index === 0)) {
+          rightMenuRef.value.updateMenu(checked, { name: '图层分析', meta: { icon: 'icon1' } });
+        }
       }
     }
   } else if (item.path === '3') {
     // 通讯保障
     communicationSupport.show = !communicationSupport.show;
     communicationSupport.data = item;
-  } else if (item.path === '4') {
-    // 附近视频
-    tempMenu.value = item;
-    //为地图注册click事件获取鼠标点击出的经纬度坐标
-    map.on('click', handleClickMap);
-    mapStore.setIsMapSelect(true);
+  }
+  if (['重点车辆'].includes(item.name) && !item.checked) {
+    timeAxisRef.value.clearData();
   }
 };
 const handleHideCommunicationSupport = () => {
@@ -455,6 +441,12 @@ watch(
 watch(
   () => mapStore.pointParams,
   () => {
+    if (mapStore.updateMenu && !!mapStore.updateMenu.name) {
+      // 视频修改的值,需要显示左侧辅助分析、显示右侧菜单
+      leftMenuRef.value.setMenuIndex(2);
+      rightMenuRef.value.updateMenu('1', mapStore.updateMenu);
+      mapStore.setUpdateMenu({});
+    }
     addMarkersMethod();
   },
   {