From afbb44a7f2fe594d37cba5ee83cd0c49963e85a9 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Fri, 30 Jan 2026 13:50:03 +0800
Subject: [PATCH] feat:首页数据驾驶舱加载调整处理

---
 applications/drone-command/src/components/map-container/device-map-container.vue |  273 ++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 174 insertions(+), 99 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 d877826..82c1f57 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
@@ -69,11 +69,13 @@
 	createRadialGradientMaterial,
 	getTexturedVertexFormat,
 } from './device-map-materials'
+import { getPointPositionsHeight } from '@/utils/cesium/mapUtil'
 import dzIcon from '@/assets/images/dataCockpit/map/dz-map-layer.png'
 import yxIcon from '@/assets/images/dataCockpit/map/yx-map-layer.png'
 
 const CLUSTER_HEIGHT = 100000
 const DETAIL_HEIGHT = 10000
+const POLYGON_HEIGHT_M = 0.2
 
 const props = defineProps({
 	onlineDevices: {
@@ -112,8 +114,8 @@
 let deviceRingFillPrimitives = []
 let defenseZonePrimitive = null
 let defenseZoneOutlinePrimitive = null
-let partitionPrimitive = null
-let partitionOutlinePrimitive = null
+let partitionFillPrimitives = []
+let partitionOutlinePrimitives = []
 let aggregationSource = null
 let commandPostBillboardCollection = null
 let droneTrackBillboardCollection = null
@@ -284,8 +286,12 @@
 	cockpitPrimitiveLayer.removeAll(false)
 	if (defenseZonePrimitive) cockpitPrimitiveLayer.add(defenseZonePrimitive)
 	if (defenseZoneOutlinePrimitive) cockpitPrimitiveLayer.add(defenseZoneOutlinePrimitive)
-	if (partitionPrimitive) cockpitPrimitiveLayer.add(partitionPrimitive)
-	if (partitionOutlinePrimitive) cockpitPrimitiveLayer.add(partitionOutlinePrimitive)
+	if (partitionFillPrimitives.length) {
+		partitionFillPrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive))
+	}
+	if (partitionOutlinePrimitives.length) {
+		partitionOutlinePrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive))
+	}
 	if (deviceRingFillPrimitives.length) {
 		deviceRingFillPrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive))
 	}
@@ -339,13 +345,13 @@
 
 const clearPartitionEntities = () => {
 	if (!viewer) return
-	if (partitionPrimitive) {
-		removeCockpitPrimitive(partitionPrimitive)
-		partitionPrimitive = null
+	if (partitionFillPrimitives.length) {
+		partitionFillPrimitives.forEach(primitive => removeCockpitPrimitive(primitive))
+		partitionFillPrimitives = []
 	}
-	if (partitionOutlinePrimitive) {
-		removeCockpitPrimitive(partitionOutlinePrimitive)
-		partitionOutlinePrimitive = null
+	if (partitionOutlinePrimitives.length) {
+		partitionOutlinePrimitives.forEach(primitive => removeCockpitPrimitive(primitive))
+		partitionOutlinePrimitives = []
 	}
 }
 
@@ -382,8 +388,16 @@
 	detailVisible.value = visible
 	if (defenseZonePrimitive) defenseZonePrimitive.show = visible
 	if (defenseZoneOutlinePrimitive) defenseZoneOutlinePrimitive.show = visible
-	if (partitionPrimitive) partitionPrimitive.show = visible
-	if (partitionOutlinePrimitive) partitionOutlinePrimitive.show = visible
+	if (partitionFillPrimitives.length) {
+		partitionFillPrimitives.forEach(primitive => {
+			primitive.show = visible
+		})
+	}
+	if (partitionOutlinePrimitives.length) {
+		partitionOutlinePrimitives.forEach(primitive => {
+			primitive.show = visible
+		})
+	}
 	if (commandPostBillboardCollection) commandPostBillboardCollection.show = visible
 	if (deviceBillboardCollection) deviceBillboardCollection.show = visible
 	if (deviceRingFillPrimitives.length) {
@@ -793,49 +807,76 @@
 	return list.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude))
 }
 
+const elevatePositions = async (positions, height = POLYGON_HEIGHT_M) => {
+	if (!Array.isArray(positions) || !positions.length) return []
+	if (!viewer) return positions
+	const points = positions
+		.map(pos => {
+			const carto = Cesium.Cartographic.fromCartesian(pos)
+			if (!carto) return null
+			return {
+				lng: Cesium.Math.toDegrees(carto.longitude),
+				lat: Cesium.Math.toDegrees(carto.latitude),
+			}
+		})
+		.filter(Boolean)
+	if (!points.length) return positions
+	const heights = await getPointPositionsHeight(points, viewer)
+	return heights.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude, (item.ASL ?? 0) + height))
+}
+
 const getAreaTypeStyle = areaType => {
 	return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
 }
 
-const buildZonePrimitives = (zones, lineColor, fillColor1, fillColor2) => {
+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, index) => {
+		; (zones || []).forEach(zone => {
 			if (!zone?.geom) return
 			const positions = getDefenseZonePositions(zone.geom)
 			if (!positions.length) return
-			const polygon = new Cesium.PolygonGeometry({
-				polygonHierarchy: new Cesium.PolygonHierarchy(positions),
-				vertexFormat: texturedVertexFormat,
-			})
-			polygonInstances.push(
-				new Cesium.GeometryInstance({
-					geometry: polygon,
-				})
-			)
-			const linePositions = positions.length > 1 ? [...positions, positions[0]] : positions
-			lineInstances.push(
-				new Cesium.GeometryInstance({
-					geometry: new Cesium.GroundPolylineGeometry({
-						positions: linePositions,
-						width: 2,
-					}),
-					attributes: {
-						color: Cesium.ColorGeometryInstanceAttribute.fromColor(
-							Cesium.Color.fromCssColorString(lineColor)
-						),
-					},
-				})
-			)
+			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.GroundPrimitive({
+		primitive = new Cesium.Primitive({
 			geometryInstances: polygonInstances,
 			appearance: new Cesium.MaterialAppearance({
 				material,
@@ -846,7 +887,7 @@
 	}
 	let outlinePrimitive = null
 	if (lineInstances.length) {
-		outlinePrimitive = new Cesium.GroundPolylinePrimitive({
+		outlinePrimitive = new Cesium.Primitive({
 			geometryInstances: lineInstances,
 			appearance: new Cesium.PolylineColorAppearance(),
 		})
@@ -855,58 +896,84 @@
 	return { primitive, outlinePrimitive }
 }
 
-const buildPartitionPrimitives = shapes => {
-	if (!viewer) return { primitive: null, outlinePrimitive: null }
-	const polygonInstances = []
-	const lineInstances = []
-	const vertexFormat = Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
+const buildPartitionPrimitives = async shapes => {
+	if (!viewer) return { primitives: [], outlinePrimitives: [] }
+	const vertexFormat = getTexturedVertexFormat()
+	const groups = new Map()
+	const tasks = []
 		; (shapes || []).forEach(shape => {
 			if (!shape?.positions || shape.positions.length < 3) return
+			const outlineColor = shape.outlineColor
+			const fillColor = shape.fillColor
+			const key = `${outlineColor.toCssColorString()}|${fillColor.toCssColorString()}`
+			if (!groups.has(key)) {
+				groups.set(key, { outlineColor, fillColor, polygonInstances: [], lineInstances: [] })
+			}
+			const group = groups.get(key)
 			const positions = shape.positions
-			const polygon = new Cesium.PolygonGeometry({
-				polygonHierarchy: new Cesium.PolygonHierarchy(positions),
-				vertexFormat,
+			tasks.push(
+				elevatePositions(positions).then(elevatedPositions => {
+					if (!elevatedPositions.length) return
+					const polygon = new Cesium.PolygonGeometry({
+						polygonHierarchy: new Cesium.PolygonHierarchy(elevatedPositions),
+						perPositionHeight: true,
+						vertexFormat,
+					})
+					group.polygonInstances.push(
+						new Cesium.GeometryInstance({
+							geometry: polygon,
+						})
+					)
+					const linePositions =
+						elevatedPositions.length > 1
+							? [...elevatedPositions, elevatedPositions[0]]
+							: elevatedPositions
+					group.lineInstances.push(
+						new Cesium.GeometryInstance({
+							geometry: new Cesium.PolylineGeometry({
+								positions: linePositions,
+								width: 2,
+							}),
+							attributes: {
+								color: Cesium.ColorGeometryInstanceAttribute.fromColor(outlineColor),
+							},
+						})
+					)
+				})
+			)
+		})
+
+	if (tasks.length) await Promise.all(tasks)
+
+	const primitives = []
+	const outlinePrimitives = []
+	groups.forEach(group => {
+		if (group.polygonInstances.length) {
+			const material = createRadialGradientMaterial(group.outlineColor, group.fillColor, {
+				gamma: 1.7,
+				innerCutoff: 0,
 			})
-			polygonInstances.push(
-				new Cesium.GeometryInstance({
-					geometry: polygon,
-					attributes: {
-						color: Cesium.ColorGeometryInstanceAttribute.fromColor(shape.fillColor),
-					},
-				})
-			)
-			const linePositions = positions.length > 1 ? [...positions, positions[0]] : positions
-			lineInstances.push(
-				new Cesium.GeometryInstance({
-					geometry: new Cesium.GroundPolylineGeometry({
-						positions: linePositions,
-						width: 2,
-					}),
-					attributes: {
-						color: Cesium.ColorGeometryInstanceAttribute.fromColor(
-							shape.outlineColor
-						),
-					},
-				})
-			)
-		})
-	let primitive = null
-	if (polygonInstances.length) {
-		primitive = new Cesium.GroundPrimitive({
-			geometryInstances: polygonInstances,
-			appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, flat: true }),
-		})
-		addCockpitPrimitive(primitive)
-	}
-	let outlinePrimitive = null
-	if (lineInstances.length) {
-		outlinePrimitive = new Cesium.GroundPolylinePrimitive({
-			geometryInstances: lineInstances,
-			appearance: new Cesium.PolylineColorAppearance(),
-		})
-		addCockpitPrimitive(outlinePrimitive)
-	}
-	return { primitive, outlinePrimitive }
+			const primitive = new Cesium.Primitive({
+				geometryInstances: group.polygonInstances,
+				appearance: new Cesium.MaterialAppearance({
+					material,
+					translucent: true,
+				}),
+			})
+			addCockpitPrimitive(primitive)
+			primitives.push(primitive)
+		}
+		if (group.lineInstances.length) {
+			const outlinePrimitive = new Cesium.Primitive({
+				geometryInstances: group.lineInstances,
+				appearance: new Cesium.PolylineColorAppearance(),
+			})
+			addCockpitPrimitive(outlinePrimitive)
+			outlinePrimitives.push(outlinePrimitive)
+		}
+	})
+
+	return { primitives, outlinePrimitives }
 }
 
 const parseGeomJson = geomJson => {
@@ -995,10 +1062,10 @@
 	return shapes
 }
 
-const renderDefenseZones = zones => {
+const renderDefenseZones = async zones => {
 	if (!viewer) return
 	clearDefenseZoneEntities()
-	const result = buildZonePrimitives(zones, '#72F3FF', '#72F3FF', '#0A7C88')
+	const result = await buildZonePrimitives(zones, '#72F3FF', '#72F3FF', '#0A7C88')
 	defenseZonePrimitive = result.primitive
 	defenseZoneOutlinePrimitive = result.outlinePrimitive
 	if (defenseZonePrimitive) defenseZonePrimitive.show = detailVisible.value
@@ -1006,15 +1073,23 @@
 	reorderCockpitPrimitives()
 }
 
-const renderPartitions = zones => {
+const renderPartitions = async zones => {
 	if (!viewer) return
 	clearPartitionEntities()
 	const shapes = resolvePartitionShapes(zones)
-	const result = buildPartitionPrimitives(shapes)
-	partitionPrimitive = result.primitive
-	partitionOutlinePrimitive = result.outlinePrimitive
-	if (partitionPrimitive) partitionPrimitive.show = detailVisible.value
-	if (partitionOutlinePrimitive) partitionOutlinePrimitive.show = detailVisible.value
+	const result = await buildPartitionPrimitives(shapes)
+	partitionFillPrimitives = result.primitives
+	partitionOutlinePrimitives = result.outlinePrimitives
+	if (partitionFillPrimitives.length) {
+		partitionFillPrimitives.forEach(primitive => {
+			primitive.show = detailVisible.value
+		})
+	}
+	if (partitionOutlinePrimitives.length) {
+		partitionOutlinePrimitives.forEach(primitive => {
+			primitive.show = detailVisible.value
+		})
+	}
 	reorderCockpitPrimitives()
 }
 
@@ -1022,9 +1097,9 @@
 	if (!viewer) return
 	try {
 		const res = await fwDefenseZonePageApi({ current: 1, size: DEFAULT_ZONE_PAGE_SIZE })
-		renderDefenseZones(res?.data?.data?.records ?? [])
+		await renderDefenseZones(res?.data?.data?.records ?? [])
 	} catch (error) {
-		renderDefenseZones([])
+		await renderDefenseZones([])
 	}
 }
 
@@ -1032,9 +1107,9 @@
 	if (!viewer) return
 	try {
 		const res = await fwAreaDivideListApi()
-		renderPartitions(res?.data?.data ?? [])
+		await renderPartitions(res?.data?.data ?? [])
 	} catch (error) {
-		renderPartitions([])
+		await renderPartitions([])
 	}
 }
 

--
Gitblit v1.9.3