From 8c450d784fe7bab2b27e3345ef9263e9f295ecaa Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Fri, 30 Jan 2026 10:38:40 +0800
Subject: [PATCH] feat:数据驾驶舱地图渲染及区域划分、场景配置部分逻辑公用

---
 applications/drone-command/src/components/map-container/device-map-container.vue |  155 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 151 insertions(+), 4 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 f7fb7e9..d877826 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
@@ -48,8 +48,10 @@
 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 { fwAreaDividePageApi } from '@/views/areaManage/partition/partitionApi'
+import { fwAreaDivideListApi } from '@/views/areaManage/partition/partitionApi'
 import { fwDefenseSceneListApi } from '@/views/areaManage/sceneConfig/sceneConfigApi'
 import { cockpitAggregationApi } from '@/api/dataCockpit'
 import layerControlIcon from '@/assets/images/dataCockpit/layerControl.png'
@@ -791,6 +793,10 @@
 	return list.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude))
 }
 
+const getAreaTypeStyle = areaType => {
+	return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
+}
+
 const buildZonePrimitives = (zones, lineColor, fillColor1, fillColor2) => {
 	if (!viewer) return { primitive: null, outlinePrimitive: null }
 	const polygonInstances = []
@@ -849,6 +855,146 @@
 	return { primitive, outlinePrimitive }
 }
 
+const buildPartitionPrimitives = shapes => {
+	if (!viewer) return { primitive: null, outlinePrimitive: null }
+	const polygonInstances = []
+	const lineInstances = []
+	const vertexFormat = Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
+		; (shapes || []).forEach(shape => {
+			if (!shape?.positions || shape.positions.length < 3) return
+			const positions = shape.positions
+			const polygon = new Cesium.PolygonGeometry({
+				polygonHierarchy: new Cesium.PolygonHierarchy(positions),
+				vertexFormat,
+			})
+			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 parseGeomJson = geomJson => {
+	if (!geomJson) return null
+	if (typeof geomJson === 'object') return geomJson
+	if (typeof geomJson !== 'string') return null
+	const trimmed = geomJson.trim()
+	if (!trimmed) return null
+	try {
+		return JSON.parse(trimmed)
+	} catch (error) {}
+	return null
+}
+
+const normalizeShapePoint = point => {
+	if (!point) return null
+	const lng = point?.lng ?? point?.longitude
+	const lat = point?.lat ?? point?.latitude
+	const height = Number.isFinite(Number(point?.height)) ? Number(point.height) : 0
+	if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return null
+	return { lng: Number(lng), lat: Number(lat), height }
+}
+
+const buildShapePositions = (points = []) => {
+	const normalized = points.map(normalizeShapePoint).filter(Boolean)
+	return normalized.map(point => Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height))
+}
+
+const getShapeDisplayPoints = shape => {
+	if (Array.isArray(shape?.displayPoints) && shape.displayPoints.length) {
+		return shape.displayPoints
+	}
+	return shape?.points || []
+}
+
+const resolvePartitionShapes = areas => {
+	const shapes = []
+		; (areas || []).forEach(area => {
+			const extList = Array.isArray(area?.fwAreaDivideExtList) ? area.fwAreaDivideExtList : []
+			extList.forEach((item, index) => {
+				const isShapePayload = item?.drawType || item?.points
+				const parsed = isShapePayload ? item : parseGeomJson(item?.geomJson)
+				if (!parsed) return
+				const shape = {
+					id: parsed?.id || `shape_${Date.now()}_${index}_${Math.random().toString(16).slice(2, 6)}`,
+					drawType: parsed?.drawType ?? 'polygon',
+					areaType: parsed?.areaType ?? item?.areaTypeKey ?? item?.areaType ?? '',
+					points: Array.isArray(parsed?.points) ? parsed.points : [],
+					displayPoints: Array.isArray(parsed?.displayPoints) ? parsed.displayPoints : null,
+					meta: parsed?.meta ?? null,
+				}
+				if (shape.drawType === 'buffer' && shape.meta?.bufferRadii?.length && shape.meta?.center) {
+					const center = shape.meta.center
+					const centerCartesian = Cesium.Cartesian3.fromDegrees(
+						center.lng,
+						center.lat,
+						center.height || 0
+					)
+					const radii = shape.meta.bufferRadii
+						.map(radius => Number(radius))
+						.filter(radius => Number.isFinite(radius) && radius > 0)
+					radii.forEach((radius, levelIndex) => {
+						const positions = buildEllipsePositions(centerCartesian, radius, radius)
+					const style = BUFFER_LEVEL_STYLES[levelIndex] || BUFFER_LEVEL_STYLES[BUFFER_LEVEL_STYLES.length - 1]
+						if (positions.length >= 3) {
+							shapes.push({
+								positions,
+								fillColor: style.fill,
+								outlineColor: style.outline,
+							})
+						}
+					})
+					return
+				}
+				const positions = buildShapePositions(getShapeDisplayPoints(shape))
+				if (positions.length >= 3) {
+					const style = getAreaTypeStyle(shape.areaType)
+					shapes.push({
+						positions,
+						fillColor: style.fill,
+						outlineColor: style.outline,
+					})
+				}
+			})
+		})
+	return shapes
+}
+
 const renderDefenseZones = zones => {
 	if (!viewer) return
 	clearDefenseZoneEntities()
@@ -863,7 +1009,8 @@
 const renderPartitions = zones => {
 	if (!viewer) return
 	clearPartitionEntities()
-	const result = buildZonePrimitives(zones, '#FFD772', '#FFD772', '#A86B00')
+	const shapes = resolvePartitionShapes(zones)
+	const result = buildPartitionPrimitives(shapes)
 	partitionPrimitive = result.primitive
 	partitionOutlinePrimitive = result.outlinePrimitive
 	if (partitionPrimitive) partitionPrimitive.show = detailVisible.value
@@ -884,8 +1031,8 @@
 const loadPartitions = async () => {
 	if (!viewer) return
 	try {
-		const res = await fwAreaDividePageApi({ current: 1, size: DEFAULT_ZONE_PAGE_SIZE })
-		renderPartitions(res?.data?.data?.records ?? [])
+		const res = await fwAreaDivideListApi()
+		renderPartitions(res?.data?.data ?? [])
 	} catch (error) {
 		renderPartitions([])
 	}

--
Gitblit v1.9.3