From b2670c2a7f71fa80ebf1e5702bb23f33e4f2dcdc Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Sat, 31 Jan 2026 11:37:38 +0800
Subject: [PATCH] feat: 对等依赖

---
 applications/drone-command/src/components/map-container/device-map-container.vue |  207 +++++++++------------------------------------------
 1 files changed, 39 insertions(+), 168 deletions(-)

diff --git a/applications/drone-command/src/components/map-container/device-map-container.vue b/applications/drone-command/src/components/map-container/device-map-container.vue
index 82c1f57..0e84459 100644
--- a/applications/drone-command/src/components/map-container/device-map-container.vue
+++ b/applications/drone-command/src/components/map-container/device-map-container.vue
@@ -47,12 +47,12 @@
 <script setup>
 import * as Cesium from 'cesium'
 import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
-import { geomAnalysis } from '@ztzf/utils'
 import { buildEllipsePositions } from '@/utils/cesium/shapeTools'
 import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
-import { fwDefenseZonePageApi } from '@/views/areaManage/defenseZone/defenseZoneApi'
 import { fwAreaDivideListApi } from '@/views/areaManage/partition/partitionApi'
-import { fwDefenseSceneListApi } from '@/views/areaManage/sceneConfig/sceneConfigApi'
+
+import { fwDefenseSceneManageListApi } from '@/views/areaManage/sceneManage/sceneManageApi'
+
 import { cockpitAggregationApi } from '@/api/dataCockpit'
 import layerControlIcon from '@/assets/images/dataCockpit/layerControl.png'
 import equipmentIcon from '@/assets/images/dataCockpit/map/equipment.png'
@@ -62,14 +62,14 @@
 import jaGeojsonRaw from '@/assets/geojson/ja.geojson?raw'
 import DevicePopup from './components/DevicePopup.vue'
 import DronePopup from './components/DronePopup.vue'
+import dayjs from 'dayjs'
 import {
-	RING_STYLES,
-	addDeviceRings,
 	createDroneTrackMaterial,
 	createRadialGradientMaterial,
 	getTexturedVertexFormat,
 } from './device-map-materials'
 import { getPointPositionsHeight } from '@/utils/cesium/mapUtil'
+import { createDeviceRangePrimitiveWithHeight } from '@/utils/cesium/deviceRange'
 import dzIcon from '@/assets/images/dataCockpit/map/dz-map-layer.png'
 import yxIcon from '@/assets/images/dataCockpit/map/yx-map-layer.png'
 
@@ -101,7 +101,6 @@
 })
 const emit = defineEmits(['droneSignal', 'droneCounter', 'droneFavorite'])
 
-const DEFAULT_ZONE_PAGE_SIZE = 999
 
 const mapRef = ref(null)
 let viewer = null
@@ -112,8 +111,6 @@
 let deviceBillboardCollection = null
 let deviceRingOutlinePrimitives = []
 let deviceRingFillPrimitives = []
-let defenseZonePrimitive = null
-let defenseZoneOutlinePrimitive = null
 let partitionFillPrimitives = []
 let partitionOutlinePrimitives = []
 let aggregationSource = null
@@ -123,6 +120,7 @@
 let droneTrackTickHandler = null
 let droneTrackStartTime = null
 let droneTrackRuntime = []
+let mapReadyHandled = false
 let favoritePulseRafId = null
 let favoritePulseStartAt = 0
 let favoritePulseElapsed = 0
@@ -254,6 +252,7 @@
 	return range
 }
 
+
 const ensureCockpitPrimitiveLayer = () => {
 	if (!viewer) return
 	if (!cockpitPrimitiveLayer) {
@@ -284,8 +283,6 @@
 	if (!viewer) return
 	ensureCockpitPrimitiveLayer()
 	cockpitPrimitiveLayer.removeAll(false)
-	if (defenseZonePrimitive) cockpitPrimitiveLayer.add(defenseZonePrimitive)
-	if (defenseZoneOutlinePrimitive) cockpitPrimitiveLayer.add(defenseZoneOutlinePrimitive)
 	if (partitionFillPrimitives.length) {
 		partitionFillPrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive))
 	}
@@ -331,17 +328,6 @@
 	}
 }
 
-const clearDefenseZoneEntities = () => {
-	if (!viewer) return
-	if (defenseZonePrimitive) {
-		removeCockpitPrimitive(defenseZonePrimitive)
-		defenseZonePrimitive = null
-	}
-	if (defenseZoneOutlinePrimitive) {
-		removeCockpitPrimitive(defenseZoneOutlinePrimitive)
-		defenseZoneOutlinePrimitive = null
-	}
-}
 
 const clearPartitionEntities = () => {
 	if (!viewer) return
@@ -386,8 +372,6 @@
 
 const setDetailVisibility = visible => {
 	detailVisible.value = visible
-	if (defenseZonePrimitive) defenseZonePrimitive.show = visible
-	if (defenseZoneOutlinePrimitive) defenseZoneOutlinePrimitive.show = visible
 	if (partitionFillPrimitives.length) {
 		partitionFillPrimitives.forEach(primitive => {
 			primitive.show = visible
@@ -717,7 +701,7 @@
 	reorderCockpitPrimitives()
 }
 
-const renderDeviceEntities = devices => {
+const renderDeviceEntities = async devices => {
 	if (!viewer) return
 	ensureCockpitPrimitiveLayer()
 	ensureDeviceCollections()
@@ -732,14 +716,14 @@
 	}
 	devicePickMap.clear()
 	deviceBillboardCollection.show = detailVisible.value
-	const ringFillInstancesByStyle = RING_STYLES.map(() => [])
-	const ringOutlineInstancesByStyle = RING_STYLES.map(() => [])
+	const deviceEntries = []
+	const devicePositions = []
 	devices.forEach((item, index) => {
 		const position = getDevicePosition(item)
 		if (!position) return
 		const entityId = `online-device-${item.id ?? index}-${index}`
 		const rangeMeters = getDeviceRange(item)
-		addDeviceRings(position, ringFillInstancesByStyle, ringOutlineInstancesByStyle, rangeMeters)
+		devicePositions.push({ lng: position.longitude, lat: position.latitude })
 		const billboard = deviceBillboardCollection.add({
 			position: Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, 0),
 			image: equipmentIcon,
@@ -749,62 +733,32 @@
 		})
 		billboard.id = entityId
 		devicePickMap.set(entityId, { data: item, billboard })
+		deviceEntries.push({ position, rangeMeters, billboard })
 	})
 	if (selectedTargetType.value === 'device' && selectedDeviceBillboard && !devicePickMap.has(selectedDeviceBillboard.id)) {
 		closePopup()
 	}
-	ringFillInstancesByStyle.forEach((instances, index) => {
-		if (!instances.length) return
-		const ring = RING_STYLES[index]
-		const alpha = ring.alpha ?? 0.64
-		const innerRatio =
-			typeof ring.innerRatio === 'number'
-				? ring.innerRatio
-				: ring.inner && ring.outer
-					? Math.min(Math.max(ring.inner / ring.outer, 0), 0.9)
-					: 0
-		const material = createRadialGradientMaterial(
-			Cesium.Color.fromCssColorString(ring.gradient[0]).withAlpha(alpha),
-			Cesium.Color.fromCssColorString(ring.gradient[1]).withAlpha(alpha),
-			{
-				gamma: 1.7,
-				innerCutoff: innerRatio,
+	if (deviceEntries.length) {
+		const heights = await getPointPositionsHeight(devicePositions, viewer)
+		deviceEntries.forEach((entry, index) => {
+			const height = Number(heights?.[index]?.ASL)
+			const centerHeight = Number.isFinite(height) ? height : 0
+			if (entry.billboard) {
+				entry.billboard.position = Cesium.Cartesian3.fromDegrees(
+					entry.position.longitude,
+					entry.position.latitude,
+					centerHeight
+				)
 			}
-		)
-		const primitive = new Cesium.GroundPrimitive({
-			geometryInstances: instances,
-			appearance: new Cesium.MaterialAppearance({
-				material,
-				translucent: true,
-			}),
+			if (!Number.isFinite(entry.rangeMeters) || entry.rangeMeters <= 0) return
+			const primitive = createDeviceRangePrimitiveWithHeight(entry.position, entry.rangeMeters, centerHeight)
+			if (!primitive) return
+			primitive.show = detailVisible.value
+			addCockpitPrimitive(primitive)
+			deviceRingFillPrimitives.push(primitive)
 		})
-		primitive.show = detailVisible.value
-		addCockpitPrimitive(primitive)
-		deviceRingFillPrimitives.push(primitive)
-	})
-	ringOutlineInstancesByStyle.forEach(instances => {
-		if (!instances.length) return
-		const primitive = new Cesium.GroundPolylinePrimitive({
-			geometryInstances: instances,
-			appearance: new Cesium.PolylineColorAppearance(),
-		})
-		primitive.show = detailVisible.value
-		addCockpitPrimitive(primitive)
-		deviceRingOutlinePrimitives.push(primitive)
-	})
+	}
 	reorderCockpitPrimitives()
-}
-
-const getDefenseZonePositions = geom => {
-	const points = geomAnalysis(geom)
-	if (points.length < 3) return []
-	const first = points[0]
-	const last = points[points.length - 1]
-	const list =
-		first && last && first.longitude === last.longitude && first.latitude === last.latitude
-			? points.slice(0, -1)
-			: points
-	return list.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude))
 }
 
 const elevatePositions = async (positions, height = POLYGON_HEIGHT_M) => {
@@ -827,73 +781,6 @@
 
 const getAreaTypeStyle = areaType => {
 	return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
-}
-
-const buildZonePrimitives = async (zones, lineColor, fillColor1, fillColor2) => {
-	if (!viewer) return { primitive: null, outlinePrimitive: null }
-	const polygonInstances = []
-	const lineInstances = []
-	const positionGroups = []
-	const texturedVertexFormat = getTexturedVertexFormat()
-		; (zones || []).forEach(zone => {
-			if (!zone?.geom) return
-			const positions = getDefenseZonePositions(zone.geom)
-			if (!positions.length) return
-			positionGroups.push(positions)
-		})
-	if (!positionGroups.length) return { primitive: null, outlinePrimitive: null }
-	const elevatedGroups = await Promise.all(positionGroups.map(group => elevatePositions(group)))
-	elevatedGroups.forEach(elevatedPositions => {
-		if (!elevatedPositions.length) return
-		const polygon = new Cesium.PolygonGeometry({
-			polygonHierarchy: new Cesium.PolygonHierarchy(elevatedPositions),
-			perPositionHeight: true,
-			vertexFormat: texturedVertexFormat,
-		})
-		polygonInstances.push(
-			new Cesium.GeometryInstance({
-				geometry: polygon,
-			})
-		)
-		const linePositions =
-			elevatedPositions.length > 1 ? [...elevatedPositions, elevatedPositions[0]] : elevatedPositions
-		lineInstances.push(
-			new Cesium.GeometryInstance({
-				geometry: new Cesium.PolylineGeometry({
-					positions: linePositions,
-					width: 2,
-				}),
-				attributes: {
-					color: Cesium.ColorGeometryInstanceAttribute.fromColor(
-						Cesium.Color.fromCssColorString(lineColor)
-					),
-				},
-			})
-		)
-	})
-	let primitive = null
-	if (polygonInstances.length) {
-		const baseColor1 = Cesium.Color.fromCssColorString(fillColor1)
-		const baseColor2 = Cesium.Color.fromCssColorString(fillColor2)
-		const material = createRadialGradientMaterial(baseColor1.withAlpha(0.64), baseColor2.withAlpha(0.64))
-		primitive = new Cesium.Primitive({
-			geometryInstances: polygonInstances,
-			appearance: new Cesium.MaterialAppearance({
-				material,
-				translucent: true,
-			}),
-		})
-		addCockpitPrimitive(primitive)
-	}
-	let outlinePrimitive = null
-	if (lineInstances.length) {
-		outlinePrimitive = new Cesium.Primitive({
-			geometryInstances: lineInstances,
-			appearance: new Cesium.PolylineColorAppearance(),
-		})
-		addCockpitPrimitive(outlinePrimitive)
-	}
-	return { primitive, outlinePrimitive }
 }
 
 const buildPartitionPrimitives = async shapes => {
@@ -1062,17 +949,6 @@
 	return shapes
 }
 
-const renderDefenseZones = async zones => {
-	if (!viewer) return
-	clearDefenseZoneEntities()
-	const result = await buildZonePrimitives(zones, '#72F3FF', '#72F3FF', '#0A7C88')
-	defenseZonePrimitive = result.primitive
-	defenseZoneOutlinePrimitive = result.outlinePrimitive
-	if (defenseZonePrimitive) defenseZonePrimitive.show = detailVisible.value
-	if (defenseZoneOutlinePrimitive) defenseZoneOutlinePrimitive.show = detailVisible.value
-	reorderCockpitPrimitives()
-}
-
 const renderPartitions = async zones => {
 	if (!viewer) return
 	clearPartitionEntities()
@@ -1093,20 +969,13 @@
 	reorderCockpitPrimitives()
 }
 
-const loadDefenseZones = async () => {
-	if (!viewer) return
-	try {
-		const res = await fwDefenseZonePageApi({ current: 1, size: DEFAULT_ZONE_PAGE_SIZE })
-		await renderDefenseZones(res?.data?.data?.records ?? [])
-	} catch (error) {
-		await renderDefenseZones([])
-	}
-}
-
 const loadPartitions = async () => {
 	if (!viewer) return
 	try {
-		const res = await fwAreaDivideListApi()
+		const res = await fwAreaDivideListApi({
+			isSetSceneManage: 1,
+			flyTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+		})
 		await renderPartitions(res?.data?.data ?? [])
 	} catch (error) {
 		await renderPartitions([])
@@ -1267,7 +1136,9 @@
 
 const loadCommandPosts = async () => {
 	try {
-		const res = await fwDefenseSceneListApi()
+		const res = await fwDefenseSceneManageListApi({
+			time: dayjs().format('YYYY-MM-DD HH:mm:ss')
+		})
 		renderCommandPosts(res?.data?.data ?? [])
 	} catch (error) {
 		renderCommandPosts([])
@@ -1339,6 +1210,8 @@
 }
 
 const handleMapReady = ({ viewer: mapViewer, publicCesium: mapPublic }) => {
+	if (mapReadyHandled) return
+	mapReadyHandled = true
 	viewer = mapViewer
 	publicCesium = mapPublic
 	ensureCockpitPrimitiveLayer()
@@ -1347,7 +1220,6 @@
 	const stage = getStageByHeight(height)
 	updateStageDisplay(stage)
 	renderDeviceEntities(props.onlineDevices)
-	loadDefenseZones()
 	loadPartitions()
 	loadAggregation()
 	loadCommandPosts()
@@ -1375,7 +1247,6 @@
 onBeforeUnmount(() => {
 	document.removeEventListener('click', handleClickOutside)
 	clearDeviceEntities()
-	clearDefenseZoneEntities()
 	clearPartitionEntities()
 	clearAggregationEntities()
 	clearCommandPostEntities()

--
Gitblit v1.9.3