From b775b3077324cb9dd7dfdedbed8baaf7d40bf9f1 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Thu, 17 Apr 2025 20:45:18 +0800
Subject: [PATCH] feat:事件点、聚合点---点击事件抽离

---
 src/hooks/useSingleDroneMap/useSingleDroneMap.js |  135 +++----------------
 src/hooks/components/useMapHandlerClick.js       |   89 +++++++++---
 src/hooks/useMapAggregation/useMapAggregation.js |  139 ++++---------------
 3 files changed, 117 insertions(+), 246 deletions(-)

diff --git a/src/hooks/components/useMapHandlerClick.js b/src/hooks/components/useMapHandlerClick.js
index a4854ce..82d59c5 100644
--- a/src/hooks/components/useMapHandlerClick.js
+++ b/src/hooks/components/useMapHandlerClick.js
@@ -2,33 +2,72 @@
  * @Author: shuishen 1109946754@qq.com
  * @Date: 2025-04-15 22:41:40
  * @LastEditors: shuishen 1109946754@qq.com
- * @LastEditTime: 2025-04-16 19:02:39
+ * @LastEditTime: 2025-04-17 19:43:36
  * @FilePath: \command-center-dashboard\src\hooks\components\useMapHandlerClick.js
  * @Description: 
  * 
  * Copyright (c) 2025 by shuishen, All Rights Reserved. 
  */
 import * as Cesium from 'cesium'
+import { render } from 'vue'
+import { useStore } from 'vuex'
+
+import DevicePopUpBox from '@/hooks/components/DevicePopUpBox.vue'
 import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue'
 
 /**
  * 
  * @param {Object} options - 配置选项
  */
-export function useMapHandlerClick (viewer, options = {
-  type: 'single-drone-event',
-  customDom: EventPopUpBox
-}) {
-  const { type } = options
+export function useMapHandlerClick (options = {}) {
+  const {
+    popupType = 'event-popup',
+    eventType = 'single-drone-event',
+    styleTransform = 'translate(-50%,-110%)',
+    getViewer
+  } = options
 
-  const currentClickEntity = ref(null)
+  const store = useStore()
+
+  const popupData = {
+    'event-popup': EventPopUpBox,
+    'device-popup': DevicePopUpBox
+  }
+
+  const MapPopUpBox = popupData[popupType]
+
+  let viewer = null
   let handler = null
+  let currentClickEntity = null
 
   // 查找特定类型的实体
   const findEntityByType = (entities, type) => {
-    return entities.find(entity =>
-      entity?.properties?.customData?._value?.data?.type === type
-    )
+    let types = []
+
+    Array.isArray(type) ? types = type : types = [type]
+
+    return types.reduce((pre, curType) => {
+      let entity = entities.find(entity => entity?.properties?.customData?._value?.data?.type === curType)
+
+      return entity ? (pre.push({
+        type: curType,
+        entity
+      }), pre) : pre
+    }, [])
+  }
+
+  const publicEvent = (entity) => {
+    viewer.scene.postRender.addEventListener(labelBoxRender)
+  }
+
+  const typeEvent = {
+    'deviceAggregation': publicEvent,
+    'single-drone-event': publicEvent,
+    'event': publicEvent,
+    'device': (entity) => {
+      const device = entity.properties.customData._value.data
+      store.commit('setSingleUavHome', device)
+    }
   }
 
   // 左键单机事件
@@ -36,17 +75,21 @@
     let clickedEntities = viewer?.scene.drillPick(click.position).map(item => item.id)
     if (!clickedEntities.length) return
 
-    currentClickEntity.value = findEntityByType(clickedEntities, type)
+    let curClick = findEntityByType(clickedEntities, eventType)
 
     removeLabel()
 
-    if (currentClickEntity.value) {
-      viewer?.scene.postRender.addEventListener(labelBoxRender)
+    if (curClick.length > 0 && typeEvent[curClick[0].type]) {
+      currentClickEntity = curClick[0].entity
+
+      typeEvent[curClick[0].type](currentClickEntity)
     }
   }
 
   // 事件初始化
   const handlerInit = () => {
+    !viewer && (viewer = getViewer())
+
     if (handler) return
 
     handler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas)
@@ -62,7 +105,7 @@
 
   // 获取弹框box
   const getLabelDom = data => {
-    const vNode = h(customDom, { data, removeLabel })
+    const vNode = h(MapPopUpBox, { data, removeLabel })
     const tooltipContainer = document.createElement('div')
     tooltipContainer.id = 'mapPopUpBox'
     tooltipContainer.style.position = 'absolute'
@@ -75,12 +118,12 @@
 
   // 弹框位置刷新
   const labelBoxRender = () => {
-    if (!currentEntity) return
+    if (!currentClickEntity) return
     let dom = document.querySelector('#mapPopUpBox')
     if (!dom) {
-      dom = getLabelDom(currentEntity.properties.customData._value.data)
+      dom = getLabelDom(currentClickEntity.properties.customData._value.data)
     }
-    const screenPosition = viewer?.scene.cartesianToCanvasCoordinates(currentEntity?.position?._value)
+    const screenPosition = viewer?.scene.cartesianToCanvasCoordinates(currentClickEntity?.position?._value)
     if (screenPosition) {
       dom.style.left = `${screenPosition.x}px`
       dom.style.top = `${screenPosition.y}px`
@@ -101,15 +144,19 @@
     removeDom()
   }
 
-  // 自动清理
-  onUnmounted(() => {
+  const removeAll = () => {
     removeHandler()
     removeLabel()
+  }
+
+  // 自动清理
+  onUnmounted(() => {
+    removeAll()
   })
 
   return {
-    currentClickEntity,
     handlerInit,
-    removeHandler
+    removeAll,
+    removeLabel
   }
 }
\ No newline at end of file
diff --git a/src/hooks/useMapAggregation/useMapAggregation.js b/src/hooks/useMapAggregation/useMapAggregation.js
index 5557967..d46d74a 100644
--- a/src/hooks/useMapAggregation/useMapAggregation.js
+++ b/src/hooks/useMapAggregation/useMapAggregation.js
@@ -3,30 +3,19 @@
 import eventAggregationImg from '@/assets/images/home/useUavHome/eventAggregationImg.png'
 import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
 
-// 事件图标
-import eventSingle from '@/assets/images/home/useEventOperate/eventSingle.png'
+import { getEventImage } from '@/utils/stateToImageMap/event'
+import { getDroneStatusImage } from '@/utils/stateToImageMap/drone'
 
-import eventPending from '@/assets/images/home/useEventOperate/eventPending.png' // 待处理 0
-import eventWaitAudit from '@/assets/images/home/useEventOperate/eventWaitAudit.png' // 待审核 2
-import eventProcessing from '@/assets/images/home/useEventOperate/eventProcessing.png' // 处理中 3
-import eventCompleted from '@/assets/images/home/useEventOperate/eventCompleted.png' // 已完成 4
-import eventClosed from '@/assets/images/home/useEventOperate/eventClosed.png' // 已完结 5
-
-import DevicePopUpBox from '@/hooks/components/DevicePopUpBox.vue'
-import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue'
-
-
-// 机巢图标
-import endingImg from '@/assets/images/aiNowFly/ending.png'
-import endingHighImg from '@/assets/images/aiNowFly/ending-high.png'
-
-import { render } from 'vue'
 import { useStore } from 'vuex'
 import { getCenterPoint } from '@/utils/cesium/mapUtil'
 import cesiumOperation from '@/utils/cesium-tsa'
 import { getDeviceRegion, getDeviceRegionCount, getEventDetails, getMapEvents } from '@/api/home/aggregation'
 import { PolyGradientMaterial } from '@/utils/cesium/Material'
 import { start } from 'nprogress'
+
+// hook
+import { useMapHandlerClick } from '@/hooks/components/useMapHandlerClick'
+
 /**
  * 机巢聚合功能
  */
@@ -51,8 +40,21 @@
   const { flyTo } = cesiumOperation()
 
   const mergeImg = type === 'device' ? aggregationImg : eventAggregationImg
-  const MapPopUpBox = type === 'device' ? DevicePopUpBox : EventPopUpBox
   const styleTransform = type === 'device' ? 'translateY(-50%)' : 'translate(-50%,-110%)'
+  const eventType = type === 'device' ? ['deviceAggregation', 'device'] : 'event'
+
+  const {
+    handlerInit: mapHandlerInit,
+    removeAll: removeMapHandlerAll,
+    removeLabel: removeMapLabel
+  } = useMapHandlerClick({
+    popupType: `${type}-popup`,
+    eventType: eventType,
+    styleTransform,
+    getViewer () {
+      return viewer
+    }
+  })
 
   let scalingJudgment = [
     { name: '县', splashedList: [], gJson: null, show: false, outline: {}, value: [0, 48651], height: 31753 },
@@ -69,8 +71,6 @@
   ]
   let viewer = null
   let active = null
-  let handler = null
-  let currentEntity = null
 
   const store = useStore()
   const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode)
@@ -104,7 +104,7 @@
         if (active === item.name) return
         active = item.name
         removeEntities()
-        removeLabel()
+        removeMapLabel()
         renderOutline(item)
         if (!item.gJson && !item.splashedList?.length) return
         item.gJson ? aggregation(item) : splashed(item)
@@ -288,7 +288,7 @@
 
       needFly = true
       if (!viewer) return
-      handlerInit()
+      mapHandlerInit()
 
       viewer.scene.postRender.removeEventListener(determineScaling)
 
@@ -302,15 +302,7 @@
   //散点机巢
   function splashed (row) {
     row.splashedList.forEach((item, index) => {
-      const eventImage = {
-        0: eventPending,
-        2: eventWaitAudit,
-        3: eventProcessing,
-        4: eventCompleted,
-        5: eventClosed
-      }
-
-      const image = type === 'device' ? (item.status === "OFFLINE" ? endingHighImg : endingImg) : eventImage[item.status] || eventSingle
+      const image = type === 'device' ? getDroneStatusImage(item.status) : getEventImage(item.status)
 
       viewer.entities.add({
         id: `aggregation-splashed-${index}`,
@@ -470,33 +462,6 @@
     })
   }
 
-  // 获取弹框box
-  const getLabelDom = data => {
-    const vNode = h(MapPopUpBox, { data, removeLabel })
-    const tooltipContainer = document.createElement('div')
-    tooltipContainer.id = 'mapPopUpBox'
-    tooltipContainer.style.position = 'absolute'
-    tooltipContainer.style.transform = styleTransform
-    tooltipContainer.style.pointerEvents = 'none'
-    document.querySelector('.page-index').append(tooltipContainer)
-    render(vNode, tooltipContainer)
-    return tooltipContainer
-  }
-
-  // 弹框位置刷新
-  const labelBoxRender = () => {
-    if (!currentEntity) return
-    let dom = document.querySelector('#mapPopUpBox')
-    if (!dom) {
-      dom = getLabelDom(currentEntity.properties.customData._value.data)
-    }
-    const screenPosition = viewer.scene.cartesianToCanvasCoordinates(currentEntity?.position?._value)
-    if (screenPosition) {
-      dom.style.left = `${screenPosition.x}px`
-      dom.style.top = `${screenPosition.y}px`
-      dom.style.display = 'block'
-    }
-  }
 
   /**
    * 根据条件获取项
@@ -506,41 +471,6 @@
    */
   const findTypeItem = (arr, condition) => {
     return arr.find(item => condition(item))
-  }
-
-  // 左键单机事件
-  const singleMachineEvent = async click => {
-    let clickTargets = viewer.scene.drillPick(click.position).map(item => item.id)
-    if (!clickTargets.length) return
-
-    let deviceAggregationFind = findTypeItem(
-      clickTargets,
-      item => item?.properties?.customData?._value?.data?.type === 'deviceAggregation'
-    )
-    let deviceFind = findTypeItem(clickTargets, item => item?.properties?.customData?._value?.data?.type === 'device')
-    // "event"
-    let eventFind = findTypeItem(clickTargets, item => item?.properties?.customData?._value?.data?.type === 'event')
-    // let eventFind = findTypeItem(clickTargets, (item) => item?.properties?.customData?._value?.data?.type === 'eventAggregation')
-    currentEntity = deviceAggregationFind || deviceFind || eventFind
-
-    if (!currentEntity) return
-    if (!currentEntity?.position?._value) return
-    // 一定要移除
-    removeLabel()
-    if (deviceAggregationFind || eventFind) {
-      viewer.scene.postRender.addEventListener(labelBoxRender)
-    }
-    if (deviceFind) {
-      const device = deviceFind.properties.customData._value.data
-      store.commit('setSingleUavHome', device)
-    }
-  }
-
-  const removeDom = () => {
-    const dom = document.querySelector('#mapPopUpBox')
-    if (dom && dom.parentNode) {
-      dom.parentNode.removeChild(dom)
-    }
   }
 
   // 移除 点 和 gjson 实体
@@ -556,11 +486,7 @@
       item.includes('aggregation-') && viewer.entities.removeById(item)
     })
   }
-  // 移除弹框标签
-  const removeLabel = () => {
-    viewer?.scene.postRender.removeEventListener(labelBoxRender)
-    removeDom()
-  }
+
 
   // 移除所有监听事件,变量置空
   const removeAll = () => {
@@ -571,14 +497,12 @@
   const clearMapEntity = () => {
     if (!viewer) return
     removeEntities()
-    removeLabel()
+    removeMapHandlerAll()
+
     // viewer.camera.moveEnd.removeEventListener(determineScaling);
     viewer.scene.postRender.removeEventListener(determineScaling)
-    handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
-    handler?.destroy()
+
     active = null
-    handler = null
-    currentEntity = null
   }
 
   const init = () => {
@@ -588,14 +512,7 @@
       viewer.scene.postRender.addEventListener(determineScaling)
     })
 
-    handlerInit()
-  }
-
-  const handlerInit = () => {
-    if (handler) return
-
-    handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
-    handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK)
+    mapHandlerInit()
   }
 
   onBeforeUnmount(() => { })
diff --git a/src/hooks/useSingleDroneMap/useSingleDroneMap.js b/src/hooks/useSingleDroneMap/useSingleDroneMap.js
index ff7f0c3..b8b7aa7 100644
--- a/src/hooks/useSingleDroneMap/useSingleDroneMap.js
+++ b/src/hooks/useSingleDroneMap/useSingleDroneMap.js
@@ -2,25 +2,18 @@
  * @Author: shuishen 1109946754@qq.com
  * @Date: 2025-04-15 22:41:40
  * @LastEditors: shuishen 1109946754@qq.com
- * @LastEditTime: 2025-04-17 15:05:32
+ * @LastEditTime: 2025-04-17 20:24:19
  * @FilePath: \command-center-dashboard\src\hooks\useSingleDroneMap\useSingleDroneMap.js
  * @Description: 
  * 
  * Copyright (c) 2025 by shuishen, All Rights Reserved. 
  */
 import * as Cesium from 'cesium'
-import { render } from 'vue'
-import endingImg from '@/assets/images/aiNowFly/ending.png'
-import endingHighImg from '@/assets/images/aiNowFly/ending-high.png'
-import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue'
 
-import eventSingle from '@/assets/images/home/useEventOperate/eventSingle.png'
+import { getEventImage } from '@/utils/stateToImageMap/event'
+import { getDroneFlagImage } from '@/utils/stateToImageMap/drone'
 
-import eventPending from '@/assets/images/home/useEventOperate/eventPending.png' // 待处理 0
-import eventWaitAudit from '@/assets/images/home/useEventOperate/eventWaitAudit.png' // 待审核 2
-import eventProcessing from '@/assets/images/home/useEventOperate/eventProcessing.png' // 处理中 3
-import eventCompleted from '@/assets/images/home/useEventOperate/eventCompleted.png' // 已完成 4
-import eventClosed from '@/assets/images/home/useEventOperate/eventClosed.png' // 已完结 5
+import { useMapHandlerClick } from '@/hooks/components/useMapHandlerClick'
 
 /**
  * 
@@ -31,20 +24,18 @@
   eventApi: null,
   eventApiParams: {}
 }) {
-  const styleTransform = 'translate(-50%,-110%)'
-
   const { eventPositions, eventApi, eventApiParams } = options
-  const eventImage = {
-    0: eventPending,
-    2: eventWaitAudit,
-    3: eventProcessing,
-    4: eventCompleted,
-    5: eventClosed
-  }
 
   let viewer = null
-  let handler = null
-  let currentEntity = null
+
+  const {
+    handlerInit: mapHandlerInit,
+    removeAll: removeMapHandlerAll
+  } = useMapHandlerClick({
+    getViewer () {
+      return viewer
+    }
+  })
 
   // 初始化机场位置
   const initDroneEntity = (dronePosition) => {
@@ -52,7 +43,7 @@
 
     if (!lng || !lat) return
 
-    const markerImg = status ? endingHighImg : endingImg
+    const markerImg = getDroneFlagImage(status)
     const position = Cesium.Cartesian3.fromDegrees(+lng, +lat, 0)
 
     const droneEntity = viewer?.entities.add({
@@ -93,7 +84,7 @@
     eventData.length && eventData.forEach((item, index) => {
       const { longitude, latitude, status, id } = item
 
-      const curImg = eventImage[status] || eventSingle
+      const curImg = getEventImage(status)
 
       const position = Cesium.Cartesian3.fromDegrees(+longitude, +latitude, 0)
 
@@ -109,7 +100,7 @@
           customData: {
             data: {
               ...item,
-              eventId: item.id,
+              eventId: id,
               type: 'single-drone-event'
             }
           }
@@ -155,104 +146,20 @@
     })
   }
 
-  // 查找特定类型的实体
-  const findEntityByType = (entities, type) => {
-    return entities.find(entity =>
-      entity?.properties?.customData?._value?.data?.type === type
-    )
-  }
-
-  // 左键单机事件
-  const singleMachineEvent = async click => {
-    currentEntity = null
-
-    let clickedEntities = viewer?.scene.drillPick(click.position).map(item => item.id)
-
-    if (!clickedEntities?.length) return
-
-    currentEntity = findEntityByType(clickedEntities, 'single-drone-event')
-
-    removeLabel()
-
-    if (currentEntity) {
-      viewer?.scene.postRender.addEventListener(labelBoxRender)
-    }
-  }
-
-  // 事件初始化
-  const handlerInit = () => {
-    if (handler) return
-
-    handler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas)
-    handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK)
-  }
-
-  // 事件移除
-  const removeHandler = () => {
-    handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
-    handler?.destroy()
-    handler = null
-  }
-
-  // 获取弹框box
-  const getLabelDom = data => {
-    const vNode = h(EventPopUpBox, { data, removeLabel })
-    const tooltipContainer = document.createElement('div')
-    tooltipContainer.id = 'mapPopUpBox'
-    tooltipContainer.style.position = 'absolute'
-    tooltipContainer.style.transform = styleTransform
-    tooltipContainer.style.pointerEvents = 'none'
-    document.querySelector('.page-index').append(tooltipContainer)
-    render(vNode, tooltipContainer)
-    return tooltipContainer
-  }
-
-  // 弹框位置刷新
-  const labelBoxRender = () => {
-    if (!currentEntity) return
-    let dom = document.querySelector('#mapPopUpBox')
-
-    if (!dom) {
-      dom = getLabelDom(currentEntity.properties.customData._value.data)
-    }
-    const screenPosition = viewer?.scene.cartesianToCanvasCoordinates(currentEntity?.position?._value)
-    if (screenPosition) {
-      dom.style.left = `${screenPosition.x}px`
-      dom.style.top = `${screenPosition.y}px`
-      dom.style.display = 'block'
-    }
-  }
-
-  const removeDom = () => {
-    const dom = document.querySelector('#mapPopUpBox')
-    if (dom && dom.parentNode) {
-      dom.parentNode.removeChild(dom)
-    }
-  }
-
-  // 移除弹框标签
-  const removeLabel = () => {
-    viewer?.scene.postRender.removeEventListener(labelBoxRender)
-    removeDom()
-  }
-
-
   const init = () => {
     viewer = window.$viewer
 
-    handlerInit()
+    mapHandlerInit()
   }
 
   const removeAll = () => {
     removeLayer()
-    removeHandler()
-    removeLabel()
+    removeMapHandlerAll()
   }
 
-  onMounted(() => {
-    nextTick(() => {
-      init()
-    })
+  onMounted(async () => {
+    await nextTick()
+    init()
   })
 
   // 自动清理

--
Gitblit v1.9.3