Jelajahi Sumber

Merge remote-tracking branch 'origin/dev' into dev

yangyuxuan 1 bulan lalu
induk
melakukan
35d2d6ff4c

+ 10 - 10
public/transform/systemTransform-worker.js

@@ -1,16 +1,16 @@
 importScripts('libSystemTransform.js');
     const RECORDRTP = 0;  //录制一份未经过转封装的码流原始数据,用于定位问题
     let dataType = 1;
-    
+
     // 转封装库回调函数
     self.STCallBack = function (fileIndex,indexLen, data, dataLen)
     {
         //stFrameInfo的类型见DETAIL_FRAME_INFO
 		let stFrameInfo = Module._GetDetialFrameInfo();
         let nIsMp4Index = stFrameInfo.nIsMp4Index;
-		//console.log("FrameType is " , stFrameInfo);	
+		//console.log("FrameType is " , stFrameInfo);
 		//console.log("nIsMp4Index is " + nIsMp4Index);
-        //debugger
+
         var pData = null;
         pData = new Uint8Array(dataLen);
         pData.set(Module.HEAPU8.subarray(data, data + dataLen));
@@ -34,10 +34,10 @@ importScripts('libSystemTransform.js');
 		//let nFrameNum = stFrameInfo.nFrameNum;
 		//let nTimeStamp = stFrameInfo.nTimeStamp;
         //let nIsMp4Index = stFrameInfo.nIsMp4Index;
-		
-		//console.log("FrameType is " + stFrameType);	
-		//console.log("nIsMp4Index is " + nIsMp4Index);	
-        
+
+		//console.log("FrameType is " + stFrameType);
+		//console.log("nIsMp4Index is " + nIsMp4Index);
+
     }
 
     // self.Module = { memoryInitializerRequest: loadMemInitFile(), TOTAL_MEMORY: 128*1024*1024 };
@@ -55,14 +55,14 @@ importScripts('libSystemTransform.js');
             } else {
                 var iHeadLen = data.len;
                 var pHead = Module._malloc(iHeadLen);
-    
+
                 self.writeArrayToMemory(new Uint8Array(data.buf), pHead);
                 var iTransType = data.packType;//目标格式
                 var iRet = Module._CreatHandle(pHead, iTransType, 4096);
                 if (iRet != 0) {
                     console.log("_CreatHandle failed!" + iRet);
                 } else {
-                    iRet = Module._SysTransRegisterDataCallBack();			
+                    iRet = Module._SysTransRegisterDataCallBack();
                     if(iRet != 0)
                     {
                         console.log("_SysTransRegisterDataCallBack Failed:" + iRet);
@@ -117,4 +117,4 @@ importScripts('libSystemTransform.js');
             }
             close();
         }
-    };
+    };

+ 9 - 0
src/api/globalMap/index.ts

@@ -44,6 +44,15 @@ export const getPointInfoList = (data) => {
   });
 };
 
+// 全域地图-点位信息-详情列表(带视频点位)
+export const getPointInfoList2 = (data) => {
+  return request({
+    url: '/api/spatial_analysis/point/get_details',
+    method: 'post',
+    data: data
+  });
+};
+
 // 空间分析接口 多边形
 export const getEmergencyExpertNum = (params) => {
   return request({

+ 35 - 1
src/api/videoMonitor/index.ts

@@ -9,6 +9,14 @@ export function getEmergencyVideoCata(data) {
   });
 }
 
+// 获取视频监控列表 新
+export function getVideoListNew(params) {
+  return request({
+    url: '/api/videoResource/videoinfo/get_video_list_new',
+    method: 'get',
+    params: params
+  });
+}
 // 获取视频地址
 export function getVideoUrlById(id: string) {
   return request({
@@ -109,10 +117,36 @@ export function getVideoList(params) {
 }
 
 // 视频打点
-export function getLocationVideos(params: LocationVideosParams) {
+export function getLocationVideos(params: PointParams) {
   return request({
     url: '/api/videoResource/location/videos',
     method: 'get',
     params: params
   });
 }
+// 新 地图打点
+export function getPointInfo2(data: PointParams) {
+  return request({
+    url: '/api/spatial_analysis/point/get_info',
+    method: 'post',
+    data: data
+  });
+}
+
+// 地图菜单
+export function getTagList(params) {
+  return request({
+    url: '/api/videoResource/tag/notNull/list',
+    method: 'get',
+    params: params
+  });
+}
+
+// 视频标签打点
+export function setVideoTag(data: PointParams) {
+  return request({
+    url: '/api/videoResource/tag/labeling_video_tag',
+    method: 'post',
+    data: data
+  });
+}

+ 44 - 30
src/components/Dialog/index.vue

@@ -1,17 +1,19 @@
 <template>
   <div
     v-if="modelValue || customShow"
-    v-drag="{ draggable: draggable, position: 'fixed', scale: containerScale, handle: '.dialog-header' }"
+    v-drag="{ draggable: draggable, position: 'fixed', scale: containerScale, handle: headerType === 'header2' ? '.dialog-header2' : '.dialog-header' }"
     class="common-dialog"
     :style="{ width: computedWidth, height: computedHeight, zIndex: zIndex }"
   >
     <div :class="type === 'xs' || headerType === 'header2' ? 'dialog-header2' : 'dialog-header'">
-      <div v-if="!hideTitle" class="dialog-title" :title="title ? title : '弹窗'">
-        {{ title ? title : '弹窗' }}
-      </div>
-      <div v-if="!!getTagId" class="tags">
-        <div v-for="(item, index) in tags" :key="index" class="tag">{{ item.dict_label }}</div>
-        <i :class="tags && tags.length > 0 ? 'collectFill' : 'collect'" @click="handleShowAddTag" />
+      <div class="header-left">
+        <div v-if="!hideTitle" class="dialog-title" :title="title ? title : '弹窗'">
+          {{ title ? title : '弹窗' }}
+        </div>
+        <div v-if="!!getTagId" class="tags">
+          <div v-for="(item, index) in tags" :key="index" class="tag">{{ item.dict_label }}</div>
+          <i :class="tags && tags.length > 0 ? 'collectFill' : 'collect'" @click="handleShowAddTag" />
+        </div>
       </div>
       <i class="decoration" />
       <i class="dialog-close" @click="closeDialog" />
@@ -26,12 +28,12 @@
         <div :class="confirmClass ? confirmClass + ' common-btn-primary' : 'common-btn-primary'" @click="confirm">{{ confirmText }}</div>
       </div>
     </template>
-    <VideoTagEdit v-if="showAddTag" :id="getTagId" v-model="showAddTag" :tags="tags" @update-video-tag="getData(true)" />
     <i class="triangle1" />
     <i class="triangle2" />
     <i class="triangle3" />
     <i class="triangle4" />
   </div>
+  <VideoTagEdit v-if="showAddTag" :id="getTagId" v-model="showAddTag" :tags="tags" @update-video-tag="getData2" />
 </template>
 
 <script lang="ts" setup name="Dialog">
@@ -138,6 +140,10 @@ const getData = (needUpdate?: boolean) => {
     }
   });
 };
+const getData2 = () => {
+  getData(true);
+  showAddTag.value = false;
+};
 onMounted(() => {
   if (props.customShow) {
     zIndex.value = appStore.getZIndex();
@@ -168,7 +174,7 @@ onMounted(() => {
     position: relative;
     min-height: 175px;
     line-height: 135px;
-    padding: 0 40px;
+    padding: 0 40px 40px;
     .dialog-title {
       width: 965px;
       color: transparent;
@@ -232,12 +238,11 @@ onMounted(() => {
     display: flex;
     .dialog-title {
       width: auto;
-      max-width: 2350px;
+      max-width: 1900px;
     }
     .tags {
       display: flex;
       align-items: center;
-      margin-top: -45px;
       .tag {
         width: 345px;
         height: 71px;
@@ -265,26 +270,31 @@ onMounted(() => {
         margin-left: 20px;
       }
     }
-    &::before {
-      content: '';
-      position: absolute;
-      bottom: 19px;
-      left: 0;
-      width: 163px;
-      height: 69px;
-      background: url('@/assets/images/line.png') no-repeat;
-      background-size: 100%;
-    }
-    &::after {
-      content: '';
-      position: absolute;
-      bottom: 50px;
-      left: 178px;
-      width: calc(100% - 178px);
-      height: 6.9px;
-      background-image: linear-gradient(to right, rgba(10, 154, 196, 1) 0%, rgba(10, 154, 196, 0) 100%);
-      background-size: 100% 100%;
+    .header-left {
+      position: relative;
+      max-width: 2350px;
+      &::before {
+        content: '';
+        position: absolute;
+        bottom: -31px;
+        left: 0;
+        width: 163px;
+        height: 69px;
+        background: url('@/assets/images/line.png') no-repeat;
+        background-size: 100%;
+      }
+      &::after {
+        content: '';
+        position: absolute;
+        bottom: 0px;
+        left: 178px;
+        width: calc(100% - 178px);
+        height: 6.9px;
+        background-image: linear-gradient(to right, rgba(10, 154, 196, 1) 0%, rgba(10, 154, 196, 0) 100%);
+        background-size: 100% 100%;
+      }
     }
+
   }
   .el-form-item__label {
     font-size: 38px;
@@ -342,4 +352,8 @@ onMounted(() => {
 .common-btn-danger {
   margin-left: 20px;
 }
+.header-left {
+  display: flex;
+  flex-wrap: wrap;
+}
 </style>

+ 0 - 77
src/components/Dialog/index2.vue

@@ -1,77 +0,0 @@
-<template>
-  <div>
-    <div v-if="modelValue" class="dialog-wrap" :style="{ width: width ? width : '780px', height: height ? height : '590px' }">
-      <!--    <div class="overlay" @click="closeDialog"></div>-->
-      <div class="dialog" :style="{ width: width ? width : '780px', height: height ? height : '590px' }">
-        <div class="dialog-header">
-          <div class="dialog-title">{{ title }}</div>
-          <div class="icon-close" @click="closeDialog">
-            <el-icon size="40px"><Close /></el-icon>
-          </div>
-        </div>
-        <div class="dialog-content">
-          <slot />
-        </div>
-      </div>
-    </div>
-  </div>
-
-</template>
-
-<script lang="ts" setup>
-interface Props {
-  modelValue: boolean;
-  title?: string;
-  width?: string;
-  height?: string;
-}
-const props = withDefaults(defineProps<Props>(), {
-  modelValue: false
-});
-const emit = defineEmits(['update:modelValue', 'close']);
-
-// 关闭弹窗
-const closeDialog = () => {
-  emit('update:modelValue', false);
-  emit('close');
-};
-</script>
-
-<style lang="scss" scoped>
-.dialog-wrap {
-  position: fixed;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  z-index: 2000;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 16px;
-  .dialog {
-    height: 590px;
-    margin: 0 auto;
-    background-color: #fff;
-    border-radius: 10px;
-  }
-}
-.dialog {
-  padding: 0 20px;
-  .dialog-header {
-    width: 100%;
-    height: 70px;
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    .dialog-title {
-      font-size: 36px;
-    }
-    .icon-close {
-      cursor: pointer;
-    }
-  }
-  .dialog-content {
-    padding: 10px 0;
-  }
-}
-</style>

+ 5 - 11
src/components/HKVideo/index2.vue

@@ -22,7 +22,7 @@
       <div class="video-header">
         <div class="label" :title="dot_data.name">{{ dot_data.name }}</div>
         <div class="video-header-right">
-          <i v-if="hiddenCollect" :class="tags && tags.length > 0 ? 'collectFill' : 'collect'" @click.stop="handleCollect" />
+          <i v-if="hiddenCollect" :class="dot_data.isTag ? 'collectFill' : 'collect'" @click.stop="handleCollect" />
           <img class="video-enlarge" src="@/assets/images/video/enlarge.png" alt="" @click.stop="handleFullScreen" />
         </div>
       </div>
@@ -40,9 +40,7 @@
       <div class="video-footer">
         <div class="label">{{ props.isIndex ? '首页' : '' }}</div>
         <div class="tags">
-          <div v-for="(item, index) in tags" :key="item.dict_value" class="tag">
-            {{ item.dict_label }}<template v-if="index < tags.length - 1">、</template>
-          </div>
+          {{ dot_data.tagLabels }}
         </div>
       </div>
     </div>
@@ -71,11 +69,13 @@ interface Tag {
 interface DotData {
   id: string;
   video_code: string;
-  tags?: Tag[];
+  tag?: Tag[];
   name?: string;
   status?: string;
   poster?: string;
   collect?: boolean;
+  isTag?: boolean;
+  tagLabels?: string;
 }
 interface Props {
   dot_data: DotData;
@@ -110,9 +110,6 @@ watch(
     posterVisible.value = true;
     errBKVisible.value = false;
     isPlaying.value = false;
-    if (props.dot_data.tags) {
-      tags.value = props.dot_data.tags;
-    }
     nextTick(() => {
       if (props.autoplay) {
         play_now(true);
@@ -146,9 +143,6 @@ let showFullScreenDialog = ref(false);
 const handleFullScreen = () => {
   showFullScreenDialog.value = true;
 };
-const changeTagsData = () => {
-  emits('change');
-};
 // 开始播放
 const play_now = async (check?: boolean) => {
   if (!props.dot_data || (props.dot_data && !props.dot_data.video_code)) {

+ 14 - 13
src/components/Map/YztMap/index.vue

@@ -19,10 +19,10 @@
 import 'ol/ol.css';
 import mmJson from '@/assets/json/mm2.json';
 import { olMap } from '@/utils/olMap/olMap';
-import { getPointInfoList } from '@/api/globalMap';
+import { getPointInfoList2 } from '@/api/globalMap';
 import { getDictLabel } from '@/utils/dict';
 import { methodList, titleList } from '../data';
-import { pointDetailTemplate } from '@/views/globalMap/data/mapData';
+import { iconList, pointDetailTemplate } from '@/views/globalMap/data/mapData';
 import useAppStore from '@/store/modules/app';
 import useMapStore from '@/store/modules/map';
 
@@ -120,16 +120,14 @@ const init = () => {
     onMarkerClick: (data) => {
       // 多点位
       if (data.type === '1') {
-        let path = [];
-        mapStore.pointType.forEach((item) => {
-          path.push(item.component);
-        });
-        getPointInfoList({
-          option: path.toString(),
+        getPointInfoList2({
+          option: mapStore.pointParams.option,
+          dict_value: mapStore.pointParams.dict_value.toString(),
+          zoom_level: mapStore.mapState.zoom,
           longitude: data.longitude.toString(),
           latitude: data.latitude.toString()
         }).then((res) => {
-          const data2 = res.data.list;
+          const data2 = res.data;
           let content = document.createElement('div');
           // content.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
           content.className = 'point-info';
@@ -146,8 +144,10 @@ const init = () => {
           table.className = 'table';
           table.innerHTML = '<div class="point-item"><div class="td3">主题</div><div class="td3">名称</div></div>';
           data2.forEach((item) => {
-            item.longitude = data.longitude;
-            item.latitude = data.latitude;
+            item.image = data.image;
+            item.imageHover = data.imageHover;
+            item.size = data.size;
+            item.scale = data.scale;
             const div = document.createElement('div');
             div.className = 'point-item point-item-hover';
             div.innerHTML =
@@ -163,7 +163,7 @@ const init = () => {
           closeBtn.className = 'close';
           closeBtn.onclick = () => mapUtils.hideInfo(true);
           content.appendChild(closeBtn);
-          mapUtils.showInfo(content, [data.longitude, data.latitude], true);
+          mapUtils.showInfo(content, [data.longitude, data.latitude], -data.scale * data.size[1], true);
         });
       } else {
         handlePointDetails(data);
@@ -257,7 +257,7 @@ const handlePointDetails = (data) => {
       closeBtn.className = 'close';
       closeBtn.onclick = () => mapUtils.hideInfo(true);
       div.appendChild(closeBtn);
-      mapUtils.showInfo(div, [data.longitude, data.latitude], true);
+      mapUtils.showInfo(div, [data.longitude, data.latitude], -data.scale * data.size[1], true);
     }
   });
 };
@@ -315,6 +315,7 @@ let inverseScale = ref({
   inverseScaleY: 1
 });
 const handleResize = () => {
+  if (!containerRef.value) return;
   inverseScale.value.inverseScaleX = 1 / containerScale().scaleX;
   inverseScale.value.inverseScaleY = 1 / containerScale().scaleY;
   const containerWidth = containerRef.value.clientWidth * containerScale().scaleX;

+ 15 - 28
src/components/Map/index.vue

@@ -17,10 +17,10 @@
 <script setup lang="ts" name="Map">
 import { useAMap } from '@/hooks/AMap/useAMap';
 import { useDrawTool } from '@/hooks/AMap/useDrawTool';
-import { getPointInfoList } from '@/api/globalMap';
+import { getPointInfoList2 } from '@/api/globalMap';
 import { getDictLabel } from '@/utils/dict';
 import { methodList, titleList } from './data';
-import { pointDetailTemplate } from '@/views/globalMap/data/mapData';
+import { iconList, pointDetailTemplate } from '@/views/globalMap/data/mapData';
 import useAppStore from '@/store/modules/app';
 import mmJson from '@/assets/json/mm2.json';
 import useMapStore from '@/store/modules/map';
@@ -86,16 +86,14 @@ const mapUtils = useAMap({
   onMarkerClick: (data) => {
     // 多点位
     if (data.type === '1') {
-      let path = [];
-      mapStore.pointType.forEach((item) => {
-        path.push(item.component);
-      });
-      getPointInfoList({
-        option: path.toString(),
+      getPointInfoList2({
+        option: mapStore.pointParams.option,
+        dict_value: mapStore.pointParams.dict_value.toString(),
+        zoom_level: mapStore.mapState.zoom,
         longitude: data.longitude.toString(),
         latitude: data.latitude.toString()
       }).then((res) => {
-        const data2 = res.data.list;
+        const data2 = res.data;
         let content = document.createElement('div');
         // content.style.cssText = 'transform: scale(' + containerScale().scaleX + ');';
         content.className = 'point-info';
@@ -112,8 +110,9 @@ const mapUtils = useAMap({
         table.className = 'table';
         table.innerHTML = '<div class="point-item"><div class="td3">主题</div><div class="td3">名称</div></div>';
         data2.forEach((item) => {
-          item.longitude = data.longitude;
-          item.latitude = data.latitude;
+          item.image = data.image;
+          item.imageHover = data.imageHover;
+          item.size = data.size;
           const div = document.createElement('div');
           div.className = 'point-item point-item-hover';
           div.innerHTML =
@@ -129,27 +128,16 @@ const mapUtils = useAMap({
         closeBtn.className = 'close';
         closeBtn.onclick = hideInfo;
         content.appendChild(closeBtn);
-        showInfo(content, [data.longitude, data.latitude], true);
+        showInfo(content, [data.longitude, data.latitude], -data.size[1], true);
       });
     } else {
       handlePointDetails(data);
     }
   }
 });
-const {
-  getMap,
-  getAMap,
-  switchMap,
-  addMarker,
-  addSearchMarker,
-  clearMarker,
-  showInfo,
-  hideInfo,
-  handleHover,
-  creatMask2,
-  removeMask2,
-  trackPlayback
-} = { ...mapUtils };
+const { getMap, getAMap, switchMap, addSearchMarker, clearMarker, showInfo, hideInfo, handleHover, creatMask2, removeMask2, trackPlayback } = {
+  ...mapUtils
+};
 const handlePointDetails = (data) => {
   let method = methodList[data.dataType];
   let title = !!titleList[data.dataType] ? titleList[data.dataType] : '信息';
@@ -233,7 +221,7 @@ const handlePointDetails = (data) => {
       closeBtn.className = 'close';
       closeBtn.onclick = hideInfo;
       div.appendChild(closeBtn);
-      showInfo(div, [data.longitude, data.latitude], true);
+      showInfo(div, [data.longitude, data.latitude], -data.size[1], true);
     }
   });
 };
@@ -362,7 +350,6 @@ onUnmounted(() => {
 });
 
 defineExpose({
-  addMarker,
   addSearchMarker,
   setCenter,
   clearMarker,

+ 3 - 4
src/components/VideoTagEdit/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <Dialog v-model="show" title="视频标签" height="auto" @close="handleClose" @confirm="handleAdd">
+  <Dialog v-model="show" custom-show title="视频标签" height="auto" draggable @close="handleClose" @confirm="handleAdd">
     <div class="title-box">
       <div class="title">当前标签</div>
     </div>
@@ -19,7 +19,7 @@
 </template>
 
 <script lang="ts" setup name="VideoTagEdit">
-import { addVideoTag } from '@/api/videoMonitor';
+import { addVideoTag, setVideoTag } from '@/api/videoMonitor';
 import { showSuccessMsg } from '@/utils/notification';
 import { getDicts } from '@/api/system/dict/data';
 
@@ -69,10 +69,9 @@ const handleAdd = () => {
   selectTags.value.forEach((item) => {
     tagsId.push(item.value);
   });
-  addVideoTag({ video_code: props.id, dict_value: tagsId, dict_type: 'video_type' }).then(() => {
+  setVideoTag({ video_code: props.id, dict_value_list: tagsId }).then(() => {
     showSuccessMsg('新增成功');
     emits('updateVideoTag');
-    handleClose();
   });
 };
 

+ 77 - 34
src/hooks/AMap/useAMap.ts

@@ -3,7 +3,7 @@ import { nanoid } from 'nanoid';
 import { deepClone, initDrag } from '@/utils';
 import { mergeGeoJsonPolygons, wgs_gcj_encrypts } from '@/utils/gisUtils';
 import carImg from '@/assets/images/car.png';
-import { getImageUrl } from '@/views/globalMap/data/mapData';
+import { getImageUrl, iconList } from '@/views/globalMap/data/mapData';
 
 export function useAMap(options) {
   let AMap, map, scale, cluster;
@@ -230,42 +230,68 @@ export function useAMap(options) {
   };
   // 添加多个点2 后台做点聚合
   const addMarker2 = (obj) => {
-    if (plotLayers['points2']) {
-      plotLayers['points2'] = new AMap.TileLayer({
+    // 新增图层
+    if (!plotLayers['points2']) {
+      plotLayers['points2'] = new AMap.OverlayGroup({
         zIndex: 10, // 设置图层层级
         visible: true
       });
       map.add(plotLayers['points2']);
+    } else {
+      plotLayers['points2'].clearOverlays();
+      addPoints = [];
     }
     Object.keys(obj).forEach((key: string) => {
-      if (obj[key].videos && obj[key].videos.length > 1) {
+      const data = obj[key];
+      if (data.type === '3') {
         // 聚合点
+        const div = document.createElement('div');
+        div.style.backgroundColor = 'rgba(78,179,211,.5)';
+        const size = Math.round(25 + Math.pow(1 / 5, 1 / 5) * 20);
+        div.style.width = div.style.height = size + 'px';
+        div.style.border = 'solid 1px rgba(78,179,211,1)';
+        div.style.borderRadius = size / 2 + 'px';
+        div.innerHTML = data.count;
+        div.style.lineHeight = size + 'px';
+        div.style.color = '#ffffff';
+        div.style.fontSize = '12px';
+        div.style.textAlign = 'center';
+        const marker = new AMap.Marker({
+          position: [data.longitude, data.latitude],
+          content: div,
+          anchor: 'center',
+          offset: new AMap.Pixel(0, 0),
+          map: map
+        });
+        marker.setContent(div);
+        marker.on('click', (e) => {
+          const bounds = e.target.getBounds();
+          map.setZoomAndCenter(map.getZoom() + 1, bounds.getCenter());
+        });
+        plotLayers['points2'].addOverlay(marker);
+        addPoints.push(data);
       } else {
         // 单个点
-        const data = obj[key].videos[0];
-        data.image = getImageUrl('31_lakes_video.png');
-        data.imageHover = getImageUrl('31_lakes_video_hover.png');
-        data.icon = data.image;
-        data.size = [40, 40];
-        data.id = data.cameraIndexCode;
-        const content =
-          '<div style="display: flex;flex-direction: column;align-items: center;justify-content: center">' +
-          '<div style="background: url(' +
-          data.icon +
-          ') no-repeat; width: ' +
-          data.size[0] +
-          'px;height: ' +
-          data.size[1] +
-          'px;cursor: pointer; background-size: cover"></div>' +
-          // '<div style="font-size: 36px;white-space: nowrap">'+ context.data[0].name +'</div>' +
-          '</div>';
+        const iconConfig = iconList[data.dataType] || iconList.common;
+        data.image = iconConfig.image;
+        data.imageHover = iconConfig.imageHover;
+        data.size = iconConfig.size;
+        if (data.materia_name) {
+          data.name = data.materia_name;
+        }
+        if (data.dataType === 43) {
+          data.showName = true;
+        }
+        if (!data.id) {
+          data.id = nanoid(8);
+        }
+        data.lnglat = [data.longitude, data.latitude];
         const marker = new AMap.Marker({
           position: [data.longitude, data.latitude],
-          content: content,
+          content: getContent(data.image, data.size),
           anchor: 'bottom-center',
           offset: new AMap.Pixel(0, 0),
-          map: map,
-          layer: plotLayers['points2']
+          map: map
         });
         marker.setExtData(data);
         marker.on('click', function (e) {
@@ -273,15 +299,13 @@ export function useAMap(options) {
           let index = 0;
           let index2 = 0;
           for (let i = 0; i < addPoints.length; i++) {
-            if (addPoints[i].id === extData.id && addPoints[i].imageHover) {
-              addPoints[i].icon = addPoints[i].imageHover;
-              marker.setContent(content);
+            if (addPoints[i].id === extData.id) {
+              marker.setContent(getContent(data.imageHover, data.size));
               index++;
             } else if (!!clickMarker) {
               const extData2 = clickMarker.getExtData();
               if (addPoints[i].id === extData2.id) {
-                addPoints[i].icon = addPoints[i].image;
-                clickMarker.setContent(content);
+                clickMarker.setContent(getContent(extData2.image, extData2.size));
                 index2++;
               }
             }
@@ -289,14 +313,28 @@ export function useAMap(options) {
               break;
             }
           }
-          // addMarker(addPoints);
           clickMarker = e.target;
           options.onMarkerClick(extData);
         });
+        plotLayers['points2'].addOverlay(marker);
         addPoints.push(data);
       }
     });
   };
+  const getContent = (icon: string, size: number[]) => {
+    const content =
+      '<div style="display: flex;flex-direction: column;align-items: center;justify-content: center">' +
+      '<div style="background: url(' +
+      icon +
+      ') no-repeat; width: ' +
+      size[0] +
+      'px;height: ' +
+      size[1] +
+      'px;cursor: pointer; background-size: cover"></div>' +
+      // '<div style="font-size: 36px;white-space: nowrap">'+ context.data[0].name +'</div>' +
+      '</div>';
+    return content;
+  };
   // 清除所有标加
   const clearMarker = (id) => {
     if (!cluster || !markers[id]) return;
@@ -304,7 +342,10 @@ export function useAMap(options) {
     markers[id] = [];
   };
   const clearMarker2 = (id) => {
-
+    if (!!plotLayers['points2']) {
+      plotLayers['points2'].clearOverlays();
+      addPoints = [];
+    }
   };
 
   const handleHover = (extData, dataType) => {
@@ -337,14 +378,14 @@ export function useAMap(options) {
 
   // 显示信息框
   let infoWindow;
-  const showInfo = (content, position, isCustom) => {
+  const showInfo = (content, position, offsetY, isCustom) => {
     hideInfo();
     // 实例化InfoWindow
     infoWindow = new AMap.InfoWindow({
       // 完全自定义
       isCustom: isCustom,
       autoMove: false,
-      offset: new AMap.Pixel(0, -20) // 信息窗体的偏移量
+      offset: new AMap.Pixel(0, offsetY ? offsetY : 0) // 信息窗体的偏移量
       // 可以根据需要设置其他InfoWindow的属性
     });
     const lnglat = new AMap.LngLat(position[0], position[1]);
@@ -366,8 +407,9 @@ export function useAMap(options) {
         for (let i = 0; i < addPoints.length; i++) {
           if (addPoints[i].id === extData.id) {
             addPoints[i].icon = addPoints[i].image;
+            clickMarker.setContent(getContent(addPoints[i].icon, addPoints[i].size));
             clickMarker = null;
-            addMarker(addPoints);
+            // addMarker(addPoints);
             break;
           }
         }
@@ -746,6 +788,7 @@ export function useAMap(options) {
     addMarker2,
     addSearchMarker,
     clearMarker,
+    clearMarker2,
     getScale,
     showInfo,
     hideInfo,

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

@@ -22,7 +22,7 @@ export const useMapStore = defineStore('map', () => {
   // 地图加载是否完成
   const mapLoaded = ref(false);
   // 当前地图类型
-  const activeMap = ref<string>('satellite');
+  const activeMap = ref<string>('');
   // 是否显示边界遮罩
   const showMask = ref<boolean>(true);
   // 高德地图类型
@@ -41,11 +41,10 @@ export const useMapStore = defineStore('map', () => {
   // 是否在选点
   const isMapSelect = ref(false);
   // 视频打点参数
-  const videoPointParams = ref({
-    // 触发请求
-    flag: false,
+  const pointParams = ref({
     // 选择条件
-    dict_value: ''
+    dict_value: [],
+    option: ''
   });
   // 设置地图加载完成状态
   const setMapLoaded = (loaded: boolean) => {
@@ -72,27 +71,48 @@ export const useMapStore = defineStore('map', () => {
   const setIsMapSelect = (flag: boolean) => {
     isMapSelect.value = flag;
   };
-  // 跳转界面时 初始化所有数据
-  const initData = () => {
-    activeMap.value = 'satellite';
-    showMask.value = true;
-    trackState.show = false;
-    trackState.data = [];
-    isMapSelect.value = false;
-    videoPointParams.value = {
-      flag: false,
-      dict_value: ''
-    };
-    menuState.value = {
-      showMenu: false,
-      activeIndex: 0,
-      menuData: []
-    };
-    initMenuData();
+  // 更多视频界面、设置视频打点标识
+  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;
+                }
+              }
+            }
+          }
+          if (shouldBreak) {
+            break;
+          }
+        }
+      }
+    }
   };
-  // 设置视频打点标识
-  const setVideoPointParams = (data: any) => {
-    videoPointParams.value = data;
+  // 打点option变化
+  const setPointOption = () => {
+    const path = [];
+    pointType.value.forEach((item) => {
+      path.push(item.component);
+    });
+    pointParams.value.option = path.toString();
   };
   // 初始化左侧菜单数据
   const initMenuData = () => {
@@ -135,6 +155,24 @@ export const useMapStore = defineStore('map', () => {
       menuData: []
     };
   };
+  // 跳转界面时 初始化所有数据
+  const initData = () => {
+    activeMap.value = 'satellite';
+    showMask.value = true;
+    trackState.show = false;
+    trackState.data = [];
+    isMapSelect.value = false;
+    pointParams.value = {
+      dict_value: [],
+      option: ''
+    };
+    menuState.value = {
+      showMenu: false,
+      activeIndex: 0,
+      menuData: []
+    };
+    initMenuData();
+  };
   return {
     mapState,
     menuData,
@@ -148,7 +186,7 @@ export const useMapStore = defineStore('map', () => {
     pointType,
     trackState,
     isMapSelect,
-    videoPointParams,
+    pointParams,
     setMapLoaded,
     setZoom,
     setActiveMap,
@@ -156,7 +194,8 @@ export const useMapStore = defineStore('map', () => {
     setTrackState,
     setIsMapSelect,
     initData,
-    setVideoPointParams,
+    setPointParams,
+    setPointOption,
     handleCancelAllChecked
   };
 });

+ 1 - 1
src/types/components.d.ts

@@ -46,7 +46,7 @@ declare module 'vue' {
     HikvisionPlayer: typeof import('./../components/HKVideo/hikvision-player.vue')['default']
     HKVideo: typeof import('./../components/HKVideo/index.vue')['default']
     IFrame: typeof import('./../components/iFrame/index.vue')['default']
-    Index2: typeof import('./../components/Dialog/index2.vue')['default']
+    Index2: typeof import('./../components/HeaderSection/index2.vue')['default']
     InfoDialog: typeof import('./../components/InfoDialog/index.vue')['default']
     LineWidthSelect: typeof import('./../components/LineWidthSelect/index.vue')['default']
     Map: typeof import('./../components/Map/index.vue')['default']

+ 7 - 5
src/types/video.d.ts

@@ -1,7 +1,9 @@
-interface LocationVideosParams {
+interface PointParams {
   zoom_level: number;
-  longitude_max: string;
-  longitude_min: string;
-  latitude_max: string;
-  latitude_min: string;
+  longitude_max: string | number;
+  longitude_min: string | number;
+  latitude_max: string | number;
+  latitude_min: string | number;
+  option?: string;
+  dict_value?: string;
 }

+ 114 - 27
src/utils/olMap/olMap.ts

@@ -40,6 +40,7 @@ import * as turf from '@turf/turf';
 import { nanoid } from 'nanoid';
 import carImg from '@/assets/images/car.png';
 import { globalHeaders } from '@/utils/request';
+import { iconList } from '@/views/globalMap/data/mapData';
 
 const tk = 'a8df87f1695d224d2679aa805c1268d9';
 const commonUrl = import.meta.env.VITE_APP_BASE_API2 + 'api/oneShare/proxyHandler/gd/';
@@ -79,7 +80,6 @@ export class olMap {
     icon: '',
     iconName: ''
   };
-  private plot;
   private drawVector;
   private drawTool;
   private vectorLayer;
@@ -153,37 +153,35 @@ export class olMap {
     this.map.addInteraction(this.select);
     // 监听Select交互的select事件
     this.select.on('select', (event) => {
-      const selectedFeatures = event.selected[0]; // 获取被选中的要素集合
-      const features = selectedFeatures.get('features');
-      if (selectedFeatures && !!features) {
-        const originalFeature = features[0];
-        const size = features.length;
-        if (size === 1) {
-          if (this.selectedFeature !== originalFeature) {
+      const feature = event.selected[0]; // 获取被选中的要素集合
+      const extData = feature.get('extData');
+      if (!!feature) {
+       if(['1', '2'].includes(extData.type)) {
+          // 多点位 单点
+          if (this.selectedFeature !== feature) {
             if (this.selectedFeature) {
               this.selectedFeature.set('icon', this.selectedFeature.get('image'));
             }
-            this.selectedFeature = originalFeature;
-            const icon = originalFeature.get('imageHover');
-            const extData = originalFeature.get('extData');
-            originalFeature.set('icon', icon);
+            this.selectedFeature = feature;
+            feature.setStyle(
+              new Style({
+                image: new Icon({
+                  src: extData.imageHover,
+                  scale: extData.scale,
+                  anchor: [0.5, 0.5],
+                  anchorXUnits: 'fraction',
+                  anchorYUnits: 'fraction'
+                })
+              })
+            );
             options.onMarkerClick(extData);
           }
-        } else {
+        } else if (extData.type === '3') {
           // 聚合要素
           this.select.getFeatures().clear();
           const currentZoom = this.map.getView().getZoom();
           this.map.getView().setZoom(currentZoom + 1);
-          const points = [];
-          features.forEach((feature) => {
-            const geometry = feature.getGeometry(); // 获取要素的几何对象
-            const type = geometry.getType(); // 获取几何类型
-            if (type === 'Point') {
-              points.push(geometry.getCoordinates());
-            }
-          });
-          const newFeature = getPointsCenter(points);
-          this.map.getView().setCenter(newFeature.geometry.coordinates);
+          this.map.getView().setCenter(feature.geometry.coordinates);
           event.selected = [];
         }
       }
@@ -204,7 +202,8 @@ export class olMap {
     this.vectorLayer = new VectorLayer({
       source: new VectorSource({
         features: []
-      })
+      }),
+      zIndex: options.zIndex ? options.zIndex : 100
     });
     this.map.addLayer(this.vectorLayer);
     if (typeof this.options.onLoadCompleted === 'function') {
@@ -701,19 +700,107 @@ export class olMap {
     this.vectorLayer.setStyle(this.clusterStyle);
     this.vectorLayer.setSource(clusterSource);
   }
+  addMarker2(obj) {
+    this.clearMarker2();
+    Object.keys(obj).forEach((key: string) => {
+      const data = obj[key];
+      if (data.type === '3') {
+        // 聚合点
+        const outerCircle = new CircleStyle({
+          radius: 20,
+          fill: new Fill({
+            color: 'rgba(79, 176, 206, 0.5)'
+          }),
+          stroke: new Stroke({
+            color: 'rgba(79, 176, 206, 1)'
+          })
+        });
+        const feature = new Feature({
+          // 必须是数字类型,字符串不识别
+          geometry: new Point([Number(data.longitude), Number(data.latitude)]),
+          name: data.name,
+          pointer: true,
+          extData: data
+        });
+
+        feature.setStyle(
+          new Style({
+            image: outerCircle,
+            text: new Text({
+              text: data.count.toString(),
+              font: '14px sans-serif',
+              fill: new Fill({
+                color: '#ffff'
+              })
+            })
+          })
+        );
+        this.vectorLayer.getSource().addFeature(feature);
+        this.markers.push(data);
+      } else {
+        // 单个点
+        const iconConfig = iconList[data.dataType] || iconList.common;
+        data.image = iconConfig.image;
+        data.imageHover = iconConfig.imageHover;
+        data.size = iconConfig.size;
+        if (data.materia_name) {
+          data.name = data.materia_name;
+        }
+        if (data.dataType === 43) {
+          data.showName = true;
+        }
+        if (!data.id) {
+          data.id = nanoid(8);
+        }
+        data.lnglat = [data.longitude, data.latitude];
+        const feature = new Feature({
+          // 必须是数字类型,字符串不识别
+          geometry: new Point([Number(data.longitude), Number(data.latitude)]),
+          name: data.name,
+          pointer: true,
+          extData: data
+        });
+        // 设置自定义属性
+        const img = new Image();
+        img.onload = () => {
+          // 图片加载完成后,可以访问其 width 和 height 属性
+          const scale = data.size[0] ? data.size[0] / img.width : 1;
+          data.scale = scale;
+          feature.set('extData', data);
+          feature.setStyle(
+            new Style({
+              image: new Icon({
+                src: data.image,
+                scale: scale,
+                anchor: [0.5, 0.5],
+                anchorXUnits: 'fraction',
+                anchorYUnits: 'fraction'
+              })
+            })
+          );
+          this.vectorLayer.getSource().addFeature(feature);
+        };
+        img.src = data.image; // 设置图片的 URL,触发加载
+        this.markers.push(data);
+      }
+    });
+  }
   // 清除所有标加
   clearMarker() {
     if (!this.vectorLayer) return;
     this.vectorLayer.getSource().clear();
   }
-
-  showInfo(content, position, isCustom) {
+  clearMarker2() {
+    if (!this.vectorLayer) return;
+    this.vectorLayer.getSource().clear();
+  }
+  showInfo(content, position, offsetY, isCustom) {
     this.hideInfo();
     if (!this.infoWindow) {
       this.infoWindow = new Overlay({
         element: content,
         positioning: 'bottom-center', // 你可以根据需要调整定位方式
-        offset: [0, -10] // 偏移量,用于调整覆盖层相对于要素的位置
+        offset: [0, offsetY ? offsetY : 0] // 偏移量,用于调整覆盖层相对于要素的位置
       });
     }
     this.infoWindow.setPosition(position);

+ 3 - 3
src/views/emergencyCommandMap/LeftSection/VideoMonitor.vue

@@ -12,7 +12,7 @@
 </template>
 
 <script lang="ts" setup name="VideoMonitor">
-import { getVideoListByUser } from '@/api/videoMonitor';
+import { getVideoListNew } from '@/api/videoMonitor';
 import VideoMonitorEdit from './VideoMonitorEdit.vue';
 import HKVideo from '@/components/HKVideo/index2.vue';
 
@@ -29,13 +29,13 @@ let lngLat = reactive({
 const initData = () => {
   lngLat.longitude = props.longitude ? props.longitude : 110.925176;
   lngLat.latitude = props.latitude ? props.latitude : 21.678993;
-  getVideoListByUser({
+  getVideoListNew({
     longitude: lngLat.longitude,
     latitude: lngLat.latitude,
     page: 1,
     pageSize: 6
   }).then((res) => {
-    listData.value = res.rows;
+    listData.value = res.data;
   });
 };
 const updateData = (data, index) => {

+ 37 - 113
src/views/emergencyCommandMap/LeftSection/VideoMonitorEdit.vue

@@ -3,41 +3,32 @@
     <div class="search-box">
       <div class="box-left">
         <el-form ref="queryFormRef" :model="queryParams" :inline="true" label-position="left">
-          <el-form-item label="区划" prop="area" label-width="90px">
+          <el-form-item label="区划" prop="area_code" label-width="90px">
             <el-select
-              v-model="treeData.area"
+              v-model="queryParams.area_code"
               class="custom-select"
               popper-class="custom-select-popper"
               :teleported="false"
               style="width: 450px; margin-left: 20px"
-              @change="handleAreaChange"
             >
-              <el-option v-for="item in treeData.areaList" :key="item.id" :label="item.label" :value="item.id" />
-            </el-select>
-            <el-select
-              v-model="treeData.town"
-              class="custom-select"
-              popper-class="custom-select-popper"
-              :teleported="false"
-              style="width: 450px; margin-left: 20px"
-              @change="handleTownChange"
-            >
-              <el-option v-for="item in treeData.townList" :key="item.id" :label="item.label" :value="item.id" />
+              <el-option label="茂名市" value="" />
+              <el-option v-for="item in district_type2" :key="item.value" :label="item.label" :value="item.value" />
             </el-select>
+          </el-form-item>
+          <el-form-item label="视频来源" prop="video_from" label-width="180px">
             <el-select
-              v-model="treeData.village"
+              v-model="queryParams.video_from"
               class="custom-select"
               popper-class="custom-select-popper"
               :teleported="false"
               style="width: 450px; margin-left: 20px"
-              @change="handleVillageChange"
             >
-              <el-option v-for="item in treeData.villageList" :key="item.id" :label="item.label" :value="item.id" />
+<!--              <el-option v-for="item in district_type2" :key="item.value" :label="item.label" :value="item.value" />-->
             </el-select>
           </el-form-item>
-          <el-form-item label="实景视频" prop="dict_value" label-width="180px">
+          <el-form-item label="实景视频" prop="video_tag" label-width="180px">
             <el-select
-              v-model="queryParams.dict_value"
+              v-model="queryParams.video_tag"
               class="custom-select"
               popper-class="custom-select-popper"
               :teleported="false"
@@ -46,8 +37,8 @@
               <el-option v-for="item in video_type" :key="item.value" :label="item.label" :value="item.value" />
             </el-select>
           </el-form-item>
-          <el-form-item prop="name">
-            <el-input v-model="queryParams.name" class="custom-input2" placeholder="请输入摄像头名称" style="width: 720px" />
+          <el-form-item prop="video_name">
+            <el-input v-model="queryParams.video_name" class="custom-input2" placeholder="请输入摄像头名称" style="width: 720px" />
           </el-form-item>
           <el-form-item style="margin-right: 0">
             <div class="common-btn-primary" @click="handleQuery">搜索</div>
@@ -78,22 +69,22 @@
       <div v-for="(item, index) in dialogListData" :key="index" class="video-box" @click="selectItem(item)">
         <div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center">
           <div v-if="editVideo">
-            <div v-if="getCheckStatus(item.video_code)" class="active-tag"></div>
-            <div :class="getCheckStatus(item.video_code) ? 'common-checked-active' : 'common-checked'"></div>
-            <div class="img"></div>
+            <div v-if="item.isUserVideos" class="active-tag" />
+            <div :class="item.isUserVideos ? 'common-checked-active' : 'common-checked'" />
+            <div class="img" />
             <div class="video-label">
               <span class="label">{{ item.name }}</span>
             </div>
           </div>
-          <HKVideo v-else :dot_data="item" autoplay :is-index="item.sort" />
+          <HKVideo v-else :dot_data="item" autoplay :is-index="item.isUserVideos" />
         </div>
       </div>
     </div>
     <div class="footer">
       <pagination
-        v-show="total > queryParams.size"
-        v-model:page="queryParams.current"
-        v-model:limit="queryParams.size"
+        v-show="total > queryParams.pageSize"
+        v-model:page="queryParams.page"
+        v-model:limit="queryParams.pageSize"
         :total="total"
         layout="total, prev, pager, next"
         @pagination="getList"
@@ -106,12 +97,11 @@
 </template>
 
 <script lang="ts" setup>
-import { getEmergencyVideoCata, getUserVideoPoints, getVideoList, updateUserVideoPoints } from '@/api/videoMonitor';
+import { getUserVideoPoints, 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';
-import { getRegionalTree } from '@/api/common';
 
 interface LngLat {
   longitude: number;
@@ -131,24 +121,17 @@ const props = defineProps({
 const mapStore = useMapStore();
 const emits = defineEmits(['update:modelValue']);
 const proxy = getCurrentInstance()?.proxy;
-const { video_type } = toRefs<any>(proxy?.useDict('video_type'));
-
+const { district_type2, video_type } = toRefs<any>(proxy?.useDict('district_type2', 'video_type'));
 //查看更多数据
 const queryFormRef = ref();
-const treeData = reactive({
-  area: '',
-  town: '',
-  village: '',
-  areaList: [],
-  townList: [],
-  villageList: []
-});
+
 const queryParams = reactive({
-  current: 1,
-  size: 8,
-  dict_value: '',
-  name: '',
-  area: ''
+  area_code: '',
+  video_from: '',
+  video_tag: '573204ca-e814-11ef-a825-fa163e4bf12e',
+  video_name: '',
+  page: 1,
+  pageSize: 8
 });
 let total = ref(0);
 let editVideo = ref(false);
@@ -172,29 +155,18 @@ const getList = (flag?: boolean) => {
   let newParams = {
     latitude: props.lngLat.latitude,
     longitude: props.lngLat.longitude,
-    current: queryParams.current,
-    size: queryParams.size,
-    query: {
-      name: queryParams.name
-    }
+    ...queryParams
   };
-  if (!!queryParams.dict_value) {
-    newParams.query.dict_value = queryParams.dict_value;
-  }
-  getEmergencyVideoCata(newParams).then((res) => {
-    dialogListData.value = res.rows;
+  getVideoListNew(newParams).then((res) => {
+    dialogListData.value = res.data;
     total.value = res.total;
     getUserVideoPoints().then((res2) => {
-      filterData(res2.data.videoInfos);
       editData.value = deepClone(res2.data.videoInfos);
     });
   });
 };
 const getVideoInfoList = () => {
-  mapStore.setVideoPointParams({
-    flag: true,
-    dict_value: queryParams.dict_value
-  });
+  mapStore.setPointParams(queryParams.video_tag);
 };
 const selectItem = (item) => {
   if (editVideo.value) {
@@ -218,36 +190,21 @@ const reset = () => {
 
 /** 搜索按钮操作 */
 const handleQuery = () => {
-  queryParams.current = 1;
+  queryParams.page = 1;
   getList();
-  // getVideoInfoList();
+  getVideoInfoList();
 };
 
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
-  treeData.area = '';
-  treeData.townList = [];
-  treeData.town = '';
-  treeData.villageList = [];
-  treeData.village = '';
-  queryParams.current = 1;
+  queryParams.page = 1;
   handleQuery();
 };
 // 开启编辑视频
 const activeEdit = () => {
   editVideo.value = true;
 };
-const filterData = (data) => {
-  data.forEach((item) => {
-    for (let i = 0; i < dialogListData.value.length; i++) {
-      if (item.video_code_int === dialogListData.value[i].video_code) {
-        dialogListData.value[i].sort = true;
-        break;
-      }
-    }
-  });
-};
 // 关闭编辑
 const handleCancel = () => {
   editVideo.value = false;
@@ -263,43 +220,10 @@ const handleSave = () => {
     handleCancel();
   });
 };
-// 区变化
-const handleAreaChange = () => {
-  getAreaTreeList('townList', treeData.area);
-  treeData.town = '';
-  treeData.village = '';
-  queryParams.area = treeData.area;
-};
-// 镇变化
-const handleTownChange = () => {
-  getAreaTreeList('villageList', treeData.town);
-  treeData.village = '';
-  queryParams.area = treeData.town;
-};
-// 村变化
-const handleVillageChange = () => {
-  queryParams.area = treeData.village;
-};
-// 获取区划树
-const getAreaTreeList = (datasource, id) => {
-  getRegionalTree(id).then((res) => {
-    treeData[datasource] = res.data;
-  });
-};
-const getCheckStatus = (id) => {
-  let flag = false;
-  for (let i = 0; i < editData.value.length; i++) {
-    if (editData.value[i].video_code_int === id) {
-      flag = true;
-      break;
-    }
-  }
-  return flag;
-};
+
 onMounted(() => {
   getList();
-  getAreaTreeList('areaList', 2);
-  // getVideoInfoList();
+  getVideoInfoList();
 });
 </script>
 

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

@@ -487,7 +487,7 @@ defineExpose({ setMenuChange });
 
   .menu-content {
     margin: 0 35px 0 28px;
-    height: 1540px;
+    height: 1440px;
     overflow-y: auto;
     overflow-x: hidden;
     .content-box {

+ 1 - 1
src/views/globalMap/RightMenu/UAV/DroneDetail.vue

@@ -20,7 +20,7 @@
         </div>
         <div class="btn3" @click="handleSwitchFlyVideo">
           <i class="icon-switch" />
-          <div>{{ isFlyVideo ? '切换监控视频' : '切换飞行视频' }}</div>
+          <div>{{ isFlyVideo ? '切换机库视频' : '切换飞行视频' }}</div>
         </div>
       </div>
       <div class="title-box2">

+ 1 - 1
src/views/globalMap/RightMenu/UAV/index.vue

@@ -28,7 +28,7 @@
         无人机状态
         <i class="icon-info" />
         <div class="flex-content">
-          <el-checkbox-group v-model="queryParams.status_list" class="custom-checkbox-group" @change="handleStatusChange" >
+          <el-checkbox-group v-model="queryParams.status_list" class="custom-checkbox-group" @change="handleStatusChange">
             <el-checkbox v-for="item in drone_status" :key="item.value" :label="item.label" :value="item.value" />
           </el-checkbox-group>
         </div>

+ 10 - 5
src/views/globalMap/data/mapData.ts

@@ -22,11 +22,6 @@ export const iconList = {
     imageHover: getImageUrl('4_easy_flood_point_hover.png'),
     size: [60, 60]
   },
-  'common': {
-    image: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
-    imageHover: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
-    size: [19, 31]
-  },
   '5': {
     image: getImageUrl('5_school.png'),
     imageHover: getImageUrl('5_school_hover.png'),
@@ -221,6 +216,16 @@ export const iconList = {
     image: getImageUrl('45_elderly_care_institution.png'),
     imageHover: getImageUrl('45_elderly_care_institution_hover.png'),
     size: [40, 44]
+  },
+  'video': {
+    image: getImageUrl('31_lakes_video.png'),
+    imageHover: getImageUrl('31_lakes_video_hover.png'),
+    size: [40, 40]
+  },
+  'common': {
+    image: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
+    imageHover: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png',
+    size: [19, 31]
   }
 };
 

+ 88 - 61
src/views/globalMap/index.vue

@@ -10,7 +10,7 @@
         @handle-show-track="handleShowTrack"
       />
       <YztMap
-        v-else
+        v-else-if="!!mapStore.activeMap"
         ref="map2Ref"
         @handle-show-video="handleShowVideo"
         @handle-show-warehouse="handleShowWarehouse"
@@ -43,7 +43,7 @@
       <!--通讯保障-->
       <CommunicationSupport v-if="communicationSupport.show" @close="handleHideCommunicationSupport" />
       <!--应急人员详情-->
-      <EmergencyCrew v-if="showPeople" v-model="showPeople" :id="teamId" />
+      <EmergencyCrew v-if="showPeople" :id="teamId" v-model="showPeople" />
     </div>
   </div>
 </template>
@@ -61,12 +61,12 @@ import CommunicationSupport from './RightMenu/CommunicationSupport.vue';
 import GridPointRainfall from './RightMenu/GridPointRainfall.vue';
 import EmergencyCrew from './RightMenu/EmergencyCrew.vue';
 import useMapStore from '@/store/modules/map';
-import { getPointInfo } from '@/api/globalMap';
 import { getVehicleTrajectory } from '@/api/globalMap/KeyVehicles';
 import { iconList } from './data/mapData';
-import { deepClone } from '@/utils';
+import { debounce, deepClone } from '@/utils';
 import { parseTime } from '@/utils/ruoyi';
-import { getLocationVideos } from '@/api/videoMonitor';
+import { getPointInfo2 } from '@/api/videoMonitor';
+import { toLonLat } from 'ol/proj';
 
 //dom元素
 const rightMenuRef = ref(null);
@@ -89,7 +89,6 @@ const communicationSupport = reactive({
   show: false,
   data: {}
 });
-let markerList = ref([]);
 let addMarkersTimer;
 // 添加打点
 const addMarkers = (item) => {
@@ -100,16 +99,12 @@ const addMarkers = (item) => {
       if (index > -1) {
         mapStore.pointType.splice(index, 1);
       }
-      if (mapStore.pointType && mapStore.pointType.length === 0) {
-        dom.clearMarker('point');
-        return;
-      }
     } else {
       // 右侧图层分析状态
       item.checked2 = true;
       mapStore.pointType.push(item);
     }
-    addMarkersMethod();
+    mapStore.setPointOption();
   }
 };
 const adjustPoint = (data) => {
@@ -137,25 +132,66 @@ const adjustPoint = (data) => {
   return data;
 };
 
-const addMarkersMethod = () => {
-  const dom = mapStore.isAMap ? mapRef.value : map2Ref.value;
-  const path = [];
-  mapStore.pointType.forEach((item) => {
-    path.push(item.component);
-  });
-  getPointInfo(path.toString()).then((res) => {
-    const data = res.data && res.data.list ? res.data?.list : [];
-    markerList.value = adjustPoint(data);
-    dom?.addMarker(data);
-  });
-  if (!path.includes('43') && addMarkersTimer) {
-    clearInterval(addMarkersTimer);
-    addMarkersTimer = null;
-  }
-  if (path.includes('43')) {
-    addMarkersTimer = setInterval(addMarkersMethod, 60 * 1000);
-  }
-};
+const addMarkersMethod = debounce(
+  function () {
+    if (!mapUtils || Object.keys(mapUtils).length === 0) return;
+    const queryParams: PointParams = {
+      zoom_level: mapStore.mapState.zoom,
+      latitude_min: '',
+      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) {
+      return mapUtils.clearMarker2();
+    }
+    if (mapStore.isAMap) {
+      const AMap = mapUtils.getAMap();
+      const pixel = new AMap.Pixel(0, 0);
+      const size = mapRef.value.getMapDomSize();
+      const pixel2 = new AMap.Pixel(size[0], size[1]);
+      const lnglat = map.containerToLngLat(pixel);
+      const lnglat2 = map.containerToLngLat(pixel2);
+      queryParams.longitude_min = lnglat.lng;
+      queryParams.latitude_max = lnglat.lat;
+      queryParams.longitude_max = lnglat2.lng;
+      queryParams.latitude_min = lnglat2.lat;
+    } else {
+      // 获取地图容器尺寸
+      const size = map.getSize();
+      // 获取左上角和右下角像素坐标
+      const topLeftPixel = [0, 0];
+      const bottomRightPixel = [size[0], size[1]];
+      // 转换为地图投影坐标
+      const topLeftMap = map.getCoordinateFromPixel(topLeftPixel);
+      const bottomRightMap = map.getCoordinateFromPixel(bottomRightPixel);
+      // 转换为经纬度
+      const lnglat = toLonLat(topLeftMap, map.getView().getProjection());
+      const lnglat2 = toLonLat(bottomRightMap, map.getView().getProjection());
+      queryParams.longitude_min = lnglat[0];
+      queryParams.latitude_max = lnglat[1];
+      queryParams.longitude_max = lnglat2[0];
+      queryParams.latitude_min = lnglat2[1];
+    }
+    getPointInfo2(queryParams).then((res) => {
+      const data = res.data ? res.data : [];
+      mapUtils.addMarker2(data);
+    });
+    if (!mapStore.pointParams.option.includes('43') && addMarkersTimer) {
+      clearInterval(addMarkersTimer);
+      addMarkersTimer = null;
+    }
+    if (mapStore.pointParams.option.includes('43')) {
+      addMarkersTimer = setInterval(addMarkersMethod, 60 * 1000);
+    }
+  },
+  300,
+  false
+);
 // 跳转指定地点
 const toAddress = (item) => {
   const dom = mapStore.activeMap === 'imageMap' ? map2Ref.value : mapRef.value;
@@ -274,9 +310,7 @@ const getDrawTool = () => {
 };
 const getPlaceSearch = () => {
   const domRef = mapStore.isAMap ? mapRef.value : map2Ref.value;
-  if (!!domRef) {
-    domRef.getPlaceSearch();
-  }
+  return !!domRef ? domRef.getPlaceSearch() : {};
 };
 const trackPlayback = (data) => {
   const domRef = mapStore.isAMap ? mapRef.value : mapUtils;
@@ -396,13 +430,19 @@ const initDataToPlay = (data) => {
     timeAxisRef.value.initDataToPlay(data);
   }
 };
-
+const mapMoveEnd = () => {
+  if (!mapStore.pointParams.dict_value && !mapStore.pointParams.option) return;
+  addMarkersMethod();
+};
 watch(
   () => mapStore.mapLoaded,
   (loaded) => {
     if (loaded) {
       map = getMap();
       mapUtils = getMapUtils();
+      if (!!map && Object.keys(map).length !== 0) {
+        map.on('moveend', mapMoveEnd);
+      }
     }
   },
   {
@@ -411,34 +451,19 @@ watch(
 );
 // 监听视频打点
 watch(
-  () => mapStore.videoPointParams,
+  () => mapStore.pointParams,
   () => {
-    if (!mapStore.videoPointParams.flag) return;
-    const queryParams = {
-      zoom_level: mapStore.mapState.zoom,
-      // zoom_level: 8,
-      latitude_min: '',
-      latitude_max: '',
-      longitude_min: '',
-      longitude_max: '',
-      dict_value: 'slfh'
-      // dict_value: mapStore.videoPointParams.dict_value
-    };
-    if (mapStore.isAMap) {
-      const AMap = mapUtils.getAMap();
-      const pixel = new AMap.Pixel(0, 0);
-      const size = mapRef.value.getMapDomSize();
-      const pixel2 = new AMap.Pixel(size[0], size[1]);
-      const lnglat = map.containerToLngLat(pixel);
-      const lnglat2 = map.containerToLngLat(pixel2);
-      queryParams.longitude_min = lnglat.lng;
-      queryParams.latitude_max = lnglat.lat;
-      queryParams.longitude_max = lnglat2.lng;
-      queryParams.latitude_min = lnglat2.lat;
-    }
-    getLocationVideos(queryParams).then((res) => {
-      mapUtils.addMarker2(res.data);
-    });
+    addMarkersMethod();
+  },
+  {
+    deep: true
+  }
+);
+// 监听层级变化
+watch(
+  () => mapStore.mapState.zoom,
+  () => {
+    mapMoveEnd();
   },
   {
     deep: true
@@ -451,8 +476,10 @@ onBeforeUnmount(() => {
   if (!!map) {
     if (mapStore.isAMap) {
       map.off('click', handleClickMap);
+      map.off('moveend', handleClickMap);
     } else {
       map.un('click', handleClickMap);
+      map.un('moveend', handleClickMap);
     }
     mapStore.setIsMapSelect(false);
   }