From 046a69a1a3b50079eae3663cd631bd062748ec4f Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Wed, 28 Jan 2026 14:40:36 +0800
Subject: [PATCH] feat:多边形绘制相关处理

---
 applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditPolygonTool.js      |    4 +
 applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue                          |  101 ++++++++++++++++++++++++++++++++-
 applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js      |    7 ++
 applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditRectangleTool.js    |    4 +
 applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawPolygonTool.js      |    8 ++
 applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js |    7 ++
 applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js |    5 +
 applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawRectangleTool.js    |    8 ++
 applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js      |    5 +
 9 files changed, 144 insertions(+), 5 deletions(-)

diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
index 28240d2..4b4b7cf 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -18,7 +18,7 @@
 				>
 					<div class="panel-header">
 						<span>{{ drawTypeLabelMap[currentShapeType] || '区域' }}</span>
-						<el-icon class="panel-close" @click.stop="showTypePanel = false"><Close /></el-icon>
+						<el-icon class="panel-close" @click.stop="handleTypePanelClose"><Close /></el-icon>
 					</div>
 					<div class="panel-body">
 						<span class="panel-label">区域类型</span>
@@ -27,7 +27,6 @@
 							popper-class="command-select-popper"
 							v-model="formData.areaType"
 							placeholder="请选择"
-							clearable
 							@change="handleAreaTypeChange"
 						>
 							<el-option
@@ -301,12 +300,15 @@
 	buffer: '缓冲圆',
 }
 const showTypePanel = ref(false)
+const suppressTypePanelOnce = ref(false)
 let viewer
 let drawManager
 let editManager
 let activeTool
 let pointList = []
 let viewEntity
+let shapeDisplaySource
+const activeToolMode = ref('')
 
 const rules = {
 	areaName: fieldRules(true, 50),
@@ -399,6 +401,7 @@
 			viewEntity = null
 			clearActiveTool()
 			hideTypePanel()
+			clearShapeDisplay()
 		}
 	}
 )
@@ -436,10 +439,72 @@
 	viewer = map?.viewer || null
 }
 
+function ensureShapeDisplaySource () {
+	if (!viewer) return null
+	if (!shapeDisplaySource) {
+		shapeDisplaySource = new Cesium.CustomDataSource('partition-shape-display')
+		viewer.dataSources.add(shapeDisplaySource)
+	}
+	return shapeDisplaySource
+}
+
+function clearShapeDisplay () {
+	if (!shapeDisplaySource) return
+	shapeDisplaySource.entities.removeAll()
+}
+
+function normalizeShapePoint (point) {
+	const lng = point?.lng ?? point?.longitude
+	const lat = point?.lat ?? point?.latitude
+	if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return null
+	return {
+		lng: Number(lng),
+		lat: Number(lat),
+		height: Number.isFinite(Number(point?.height)) ? Number(point.height) : 0,
+	}
+}
+
+function buildShapePositions (points = []) {
+	const normalized = points.map(normalizeShapePoint).filter(Boolean)
+	return normalized.map(point =>
+		Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)
+	)
+}
+
+function renderShapeList () {
+	if (!viewer || !visible.value || readonly.value) {
+		clearShapeDisplay()
+		return
+	}
+	const dataSource = ensureShapeDisplaySource()
+	if (!dataSource) return
+	dataSource.entities.removeAll()
+	shapeList.value.forEach(shape => {
+		if (!shape?.points?.length) return
+		if (activeToolMode.value === 'edit' && shape.id === activeShapeId.value) return
+		const positions = buildShapePositions(shape.points)
+		if (positions.length < 3) return
+		dataSource.entities.add({
+			name: 'shape-display',
+			customData: { shapeId: shape.id, drawType: shape.drawType },
+			polygon: {
+				hierarchy: new Cesium.PolygonHierarchy(positions),
+				material: Cesium.Color.fromBytes(45, 140, 240, 99),
+				outline: false,
+				heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+			},
+			polyline: {
+				positions: positions.length ? [...positions, positions[0]] : positions,
+				clampToGround: true,
+				width: 2,
+				material: Cesium.Color.fromBytes(45, 140, 240, 255),
+			},
+		})
+	})
+}
+
 // 绘制完成回调
 const drawFinished = async data => {
-	console.log(1)
-
 	if (!Array.isArray(data) || data.length < 3) {
 		pointList = []
 		formData.value.areaSize = null
@@ -459,7 +524,10 @@
 			formData.value.areaType = alarmAreaType
 		}
 	}
-	showTypePanelAtCurrent()
+	if (!suppressTypePanelOnce.value) {
+		showTypePanelAtCurrent()
+	}
+	suppressTypePanelOnce.value = false
 
 	if (!activeShapeId.value) {
 		activeShapeId.value = `shape_${Date.now()}_${Math.random().toString(16).slice(2, 6)}`
@@ -476,6 +544,7 @@
 	} else {
 		shapeList.value.splice(targetIndex, 1, shapePayload)
 	}
+	renderShapeList()
 }
 
 function applyPolygonMetrics(points) {
@@ -508,6 +577,18 @@
 	showTypePanel.value = false
 }
 
+function handleTypePanelClose () {
+	hideTypePanel()
+	if (readonly.value) return
+	if (activeToolMode.value !== 'edit') return
+	const positions = activeTool?.getPositions?.()
+	if (Array.isArray(positions) && positions.length >= 3) {
+		suppressTypePanelOnce.value = true
+		drawFinished(positions)
+	}
+	clearActiveTool()
+}
+
 function handleAreaTypeChange (value) {
 	updateActiveShapeAreaType(value)
 }
@@ -529,10 +610,13 @@
 	activeTool = null
 	drawManager?.destroy()
 	editManager?.destroy()
+	activeToolMode.value = ''
+	renderShapeList()
 }
 
 function startDraw (type) {
 	currentShapeType.value = type
+	activeToolMode.value = 'draw'
 	drawManager ||= new DrawManager(viewer)
 	activeTool = drawManager.start(type)
 	activeTool?.subscribe('getPolygonPositions', drawFinished)
@@ -540,6 +624,7 @@
 
 function startEdit (type, points) {
 	currentShapeType.value = type
+	activeToolMode.value = 'edit'
 	editManager ||= new EditManager(viewer)
 	activeTool = editManager.start(type, points)
 	activeTool?.subscribe('getPolygonPositions', drawFinished)
@@ -552,6 +637,7 @@
 	viewEntity && viewer?.entities?.remove(viewEntity)
 	viewEntity = null
 	hideTypePanel()
+	renderShapeList()
 	if (dialogMode.value === 'edit' && pointList.length >= 3) {
 		const editPoints = _.cloneDeep(pointList)
 		if (editPoints.length > 1) {
@@ -581,10 +667,12 @@
 	formData.value.longitude = null
 	formData.value.latitude = null
 	hideTypePanel()
+	clearShapeDisplay()
 }
 
 function handleShapeEdit (row) {
 	if (!row?.points?.length) return
+	if (activeToolMode.value === 'edit' && activeShapeId.value === row.id) return
 	activeShapeId.value = row.id
 	currentShapeType.value = row.drawType
 	pointList = _.cloneDeep(row.points)
@@ -592,11 +680,13 @@
 	startEdit(row.drawType, row.points)
 	applyPolygonMetrics(pointList)
 	showTypePanelAtCurrent()
+	renderShapeList()
 }
 
 function handleShapeDelete (row) {
 	if (!row) return
 	shapeList.value = shapeList.value.filter(item => item.id !== row.id)
+	renderShapeList()
 	if (activeShapeId.value === row.id) {
 		activeShapeId.value = null
 		clearActiveTool()
@@ -673,6 +763,7 @@
 	activeShapeId.value = null
 	await nextTick()
 	initMap()
+	clearShapeDisplay()
 	viewEntity && viewer?.entities?.remove(viewEntity)
 	viewEntity = null
 	clearActiveTool()
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js
index 0d14a31..16cf36e 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawBufferCircleTool.js
@@ -41,6 +41,7 @@
 			const positions = buildEllipsePositions(this.centerCartesian, this.radius, this.radius)
 			this.notify('getPolygonPositions', positions)
 			this.tooltip.hide()
+			this.clearPreviewEntities()
 		}
 	}
 
@@ -71,6 +72,12 @@
 		})
 	}
 
+	clearPreviewEntities() {
+		if (!this.dataSource) return
+		this.dataSource.entities.removeAll()
+		this.circleEntity = null
+	}
+
 	getSurfaceDistance(startCartesian, endCartesian) {
 		const start = Cesium.Cartographic.fromCartesian(startCartesian)
 		const end = Cesium.Cartographic.fromCartesian(endCartesian)
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js
index 14059ba..9ab98fb 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawEllipseTool.js
@@ -51,6 +51,7 @@
 			const positions = buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor)
 			this.notify('getPolygonPositions', positions)
 			this.tooltip.hide()
+			this.clearPreviewEntities()
 		}
 	}
 
@@ -99,6 +100,12 @@
 		})
 	}
 
+	clearPreviewEntities() {
+		if (!this.dataSource) return
+		this.dataSource.entities.removeAll()
+		this.ellipseEntity = null
+	}
+
 	getPositionFromScreen(screenPosition) {
 		const scene = this.viewer.scene
 		const cartesian = scene.pickPosition(screenPosition)
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawPolygonTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawPolygonTool.js
index 96f60c3..dfddd03 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawPolygonTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawPolygonTool.js
@@ -176,6 +176,14 @@
 		this.floatPosition = null
 		this.notify('getPolygonPositions', this.positions)
 		this.tooltip.hide()
+		this.clearPreviewEntities()
+	}
+
+	clearPreviewEntities() {
+		if (!this.dataSource) return
+		this.dataSource.entities.removeAll()
+		this.polygonEntity = null
+		this.polylineEntity = null
 	}
 
 	getPositionFromScreen(screenPosition) {
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawRectangleTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawRectangleTool.js
index bf297e0..4d1cbc8 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawRectangleTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/draw/DrawRectangleTool.js
@@ -45,6 +45,7 @@
 			const positions = this.getRectanglePositions()
 			this.notify('getPolygonPositions', positions)
 			this.tooltip.hide()
+			this.clearPreviewEntities()
 		}
 	}
 
@@ -94,6 +95,13 @@
 		return rectanglePositionsFromBounds(bounds)
 	}
 
+	clearPreviewEntities() {
+		if (!this.dataSource) return
+		this.dataSource.entities.removeAll()
+		this.rectangleEntity = null
+		this.outlineEntity = null
+	}
+
 	getPositionFromScreen(screenPosition) {
 		const scene = this.viewer.scene
 		const cartesian = scene.pickPosition(screenPosition)
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js
index cdf0f4e..abf1a5e 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditBufferCircleTool.js
@@ -130,6 +130,11 @@
 		this.radiusEntity.position = this.getRadiusPoint()
 	}
 
+	getPositions() {
+		if (!this.centerCartesian) return []
+		return buildEllipsePositions(this.centerCartesian, this.radius, this.radius)
+	}
+
 	getRadiusPoint() {
 		const frame = Cesium.Transforms.eastNorthUpToFixedFrame(this.centerCartesian)
 		const local = new Cesium.Cartesian3(this.radius, 0, 0)
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
index 457c0c7..a957b6c 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditEllipseTool.js
@@ -154,6 +154,11 @@
 		this.minorEntity.position = this.getAxisPoint(0, this.semiMinor)
 	}
 
+	getPositions() {
+		if (!this.centerCartesian) return []
+		return buildEllipsePositions(this.centerCartesian, this.semiMajor, this.semiMinor)
+	}
+
 	getAxisPoint(eastMeters, northMeters) {
 		const frame = Cesium.Transforms.eastNorthUpToFixedFrame(this.centerCartesian)
 		const local = new Cesium.Cartesian3(eastMeters, northMeters, 0)
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditPolygonTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditPolygonTool.js
index 77c226a..1b71743 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditPolygonTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditPolygonTool.js
@@ -142,6 +142,10 @@
 		})
 	}
 
+	getPositions() {
+		return this.positions.slice()
+	}
+
 	getPositionFromScreen(screenPosition) {
 		const scene = this.viewer.scene
 		const cartesian = scene.pickPosition(screenPosition)
diff --git a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditRectangleTool.js b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditRectangleTool.js
index 9513132..7e4c642 100644
--- a/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditRectangleTool.js
+++ b/applications/drone-command/src/views/areaManage/partition/shapeTools/edit/EditRectangleTool.js
@@ -124,6 +124,10 @@
 		})
 	}
 
+	getPositions() {
+		return rectanglePositionsFromBounds(this.bounds)
+	}
+
 	getCornerCartographics() {
 		return rectanglePositionsFromBounds(this.bounds).map(position =>
 			Cesium.Cartographic.fromCartesian(position)

--
Gitblit v1.9.3