فهرست منبع

地图打点更新接口和逻辑

Hwf 3 ماه پیش
والد
کامیت
f86b8b642d

+ 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({

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

@@ -109,10 +109,27 @@ 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
+  });
+}

+ 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,

+ 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
   };
 });

+ 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);

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

@@ -132,7 +132,6 @@ const mapStore = useMapStore();
 const emits = defineEmits(['update:modelValue']);
 const proxy = getCurrentInstance()?.proxy;
 const { video_type } = toRefs<any>(proxy?.useDict('video_type'));
-
 //查看更多数据
 const queryFormRef = ref();
 const treeData = reactive({
@@ -146,7 +145,7 @@ const treeData = reactive({
 const queryParams = reactive({
   current: 1,
   size: 8,
-  dict_value: '',
+  dict_value: '573204ca-e814-11ef-a825-fa163e4bf12e',
   name: '',
   area: ''
 });
@@ -191,10 +190,7 @@ const getList = (flag?: boolean) => {
   });
 };
 const getVideoInfoList = () => {
-  mapStore.setVideoPointParams({
-    flag: true,
-    dict_value: queryParams.dict_value
-  });
+  mapStore.setPointParams(queryParams.dict_value);
 };
 const selectItem = (item) => {
   if (editVideo.value) {
@@ -220,7 +216,7 @@ const reset = () => {
 const handleQuery = () => {
   queryParams.current = 1;
   getList();
-  // getVideoInfoList();
+  getVideoInfoList();
 };
 
 /** 重置按钮操作 */
@@ -299,7 +295,7 @@ const getCheckStatus = (id) => {
 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 {

+ 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]
   }
 };
 

+ 87 - 58
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;
@@ -396,13 +432,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) {
+        map.on('moveend', mapMoveEnd);
+      }
     }
   },
   {
@@ -411,34 +453,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 +478,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);
   }