From b0daa0c145ff5455de8aacf5a892e84b6d88b462 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Sat, 07 Feb 2026 16:49:24 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js    |   11 +++--
 applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue          |   67 +++++++++++++++++----------------
 AGENTS.md                                                                         |   13 ++++++
 applications/drone-command/src/components/map-container/device-map-container.vue  |    7 ++-
 applications/drone-command/src/components/map-container/components/DronePopup.vue |    3 -
 5 files changed, 60 insertions(+), 41 deletions(-)

diff --git a/AGENTS.md b/AGENTS.md
index fb53b8d..c422872 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -36,3 +36,16 @@
 ## 环境与配置
 - Node.js >= 20,pnpm >= 9。
 - 优先使用根目录工作区脚本,除非必要不要在子目录直接运行脚本。
+
+# AI Rules / AI行为规范
+
+- 对低风险修改,AI可自主执行,无需批准。
+  AI may proceed autonomously for low-risk changes.
+- 仅当修改可能影响架构、核心模块、公共接口、数据结构或安全性时,才需要请求批准。
+  Ask for approval only for high-impact changes.
+- 若问题不影响系统正确性,应自行做出合理决策,而不是提问。
+  DO NOT ask questions that do not affect correctness.
+- 优先最小化修改范围。
+  Prefer minimal changes.
+- 未被明确要求时,禁止大规模重构。
+  Avoid large refactors unless requested.
diff --git a/applications/drone-command/src/components/map-container/components/DronePopup.vue b/applications/drone-command/src/components/map-container/components/DronePopup.vue
index 759e748..316f279 100644
--- a/applications/drone-command/src/components/map-container/components/DronePopup.vue
+++ b/applications/drone-command/src/components/map-container/components/DronePopup.vue
@@ -127,8 +127,7 @@
 	const num = Number(value)
 	if (!Number.isFinite(num)) return '-'
 	const absVal = Math.abs(num).toFixed(6)
-	const dir = type === 'lng' ? (num >= 0 ? 'E' : 'W') : num >= 0 ? 'N' : 'S'
-	return `${absVal} ${dir}`
+	return `${absVal}`
 }
 
 const height = computed(() => formatNumber(props.drone?.flightHeightM, 'm', 0))
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 0e37663..6f48e5a 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
@@ -77,6 +77,7 @@
 const DETAIL_HEIGHT = 10000
 const POLYGON_HEIGHT_M = 0.2
 const DRONE_TRACK_DURATION_S = 30 * 60
+const FIXED_DRONE_TRACK_IDS = ['6000000000602', '6000000000601']
 
 const props = defineProps({
 	allDevices: {
@@ -718,7 +719,9 @@
 	droneTrackPolylineCollection.show = detailVisible.value
 	droneTrackRuntime = []
 	const baseTrackColor = Cesium.Color.fromCssColorString('red')
-		; (list || []).forEach((item, trackIndex) => {
+		; (FIXED_DRONE_TRACK_IDS || []).forEach((trackId, trackIndex) => {
+			const item = (list || []).find(entry => String(entry?.id) === String(trackId))
+			if (!item) return
 			const position = getDevicePosition(item)
 			if (!position) return
 			const points = buildSimulatedTrackPoints({ ...position, height: item.flightHeightM, trackIndex })
@@ -742,7 +745,7 @@
 				width: 3,
 				material: trackMaterial,
 			})
-			const droneId = `drone-alarm-${item?.alarmRecordId ?? item?.id ?? trackIndex}`
+			const droneId = `drone-alarm-${trackId}`
 			const startTime = viewer.clock.startTime
 			const stopTime = viewer.clock.stopTime
 			const positionProperty = new Cesium.SampledPositionProperty()
diff --git a/applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js b/applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js
index 7df67da..207ad4e 100644
--- a/applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js
+++ b/applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js
@@ -91,6 +91,9 @@
 	}
 
 	start() {
+		if (!this.tooltip) {
+			this.tooltip = new MapTooltip(this.viewer)
+		}
 		this.dataSource = new Cesium.CustomDataSource('draw-polygon')
 		this.viewer.dataSources.add(this.dataSource)
 		this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
@@ -139,10 +142,10 @@
 		if (!this.isDrawing) return
 		const tipText = this.getTipText()
 		if (!this.tooltip?.isVisible) {
-			this.tooltip.show(tipText, movement.endPosition)
+			this.tooltip?.show(tipText, movement.endPosition)
 		} else {
-			this.tooltip.show(tipText)
-			this.tooltip.move(movement.endPosition)
+			this.tooltip?.show(tipText)
+			this.tooltip?.move(movement.endPosition)
 		}
 		if (this.positions.length === 0) return
 		const position = this.getPositionFromScreen(movement.endPosition)
@@ -283,7 +286,7 @@
 		this.floatPosition = null
 		this.isIntersecting = false
 		this.notify('getPolygonPositions', this.positions)
-		this.tooltip.hide()
+		this.tooltip?.hide()
 		this.clearPreviewEntities()
 	}
 
diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
index 0d7cb25..de30c67 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -97,7 +97,7 @@
 					<div class="detail-title">绘制区域列表</div>
 					<div class="command-table-container">
 						<div class="command-table-content">
-							<el-table class="command-table" :data="shapeList" row-key="id">
+							<el-table class="command-table" :data="shapeList" row-key="id"  height="240">
 								<el-table-column prop="areaType" label="区域类型">
 									<template v-slot="{ row }">
 										{{ resolveShapeAreaTypeLabel(row) }}
@@ -116,7 +116,7 @@
 					<div class="command-table-container">
 						<div class="command-table-content">
 							<el-table class="command-table" ref="deviceTableRef" :data="deviceOptions" row-key="id"
-								@row-click="handleDeviceRowClick">
+								@row-click="handleDeviceRowClick"  height="240">
 								<el-table-column prop="deviceName" label="设备名称" />
 								<el-table-column prop="deviceType" label="类型">
 									<template v-slot="{ row }">
@@ -169,7 +169,7 @@
 
 					<div class="shape-table-container">
 						<div class="shape-table-title">绘制区域列表</div>
-						<el-table class="command-table" :data="shapeList" row-key="id" height="auto">
+						<el-table class="command-table" :data="shapeList" row-key="id" height="240">
 							<el-table-column prop="areaType" label="区域类型">
 								<template v-slot="{ row }">
 									{{ resolveShapeAreaTypeLabel(row) }}
@@ -201,7 +201,7 @@
 						<el-form-item prop="deviceIds" label-width="0">
 							<el-table class="command-table" ref="deviceTableRef"
 								:data="deviceOptions.filter(item => item.deviceName.includes(searchName))" row-key="id"
-								@selection-change="handleDeviceSelectionChange" @row-click="handleDeviceRowClick">
+								@selection-change="handleDeviceSelectionChange" @row-click="handleDeviceRowClick"  height="240">
 								<el-table-column type="selection" width="55" :reserve-selection="true" />
 								<el-table-column prop="deviceName" label="设备名称" />
 								<el-table-column prop="deviceType" label="类型">
@@ -323,6 +323,7 @@
 let deviceRangeRenderToken = 0
 let deviceListTimer = null
 let deviceListRequestToken = 0
+let deviceMapRequestToken = 0
 
 const rules = {
 	areaName: fieldRules(true, 50),
@@ -519,8 +520,6 @@
 	deviceOptions.value = []
 	selectedDeviceRows.value = []
 	formData.value.deviceIds = ''
-	clearDeviceRangePrimitives()
-	clearDeviceIconEntities()
 	if (deviceTableRef.value) {
 		deviceTableRef.value.clearSelection()
 	}
@@ -661,20 +660,6 @@
 		if (wkt) polygons.push(wkt)
 	})
 	return polygons
-}
-
-async function renderDeviceRangeSingle (device) {
-	if (!viewer) return
-	clearDeviceRangePrimitives()
-	clearDeviceIconEntities()
-	const position = getDeviceLngLat(device)
-	if (!position) return
-	addDeviceIconEntity(device, position)
-	const rangeMeters = normalizeDeviceRange(device.effectiveRangeKm)
-	const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
-	if (!primitive) return
-	deviceRangePrimitiveMap.set(String(device?.id ?? Date.now()), primitive)
-	viewer.scene.primitives.add(primitive)
 }
 
 async function renderDeviceRanges (rows) {
@@ -1384,9 +1369,29 @@
 	suppressDeviceFly.value = true
 	syncDeviceSelection()
 	suppressDeviceFly.value = prevSuppressDeviceFly
-	if (!readonly.value) {
-		renderDeviceRanges(selectedDeviceRows.value)
+	if (readonly.value) {
+		await renderDeviceRanges(deviceOptions.value)
 	}
+}
+
+// 设备上图(新增/编辑用)
+async function getDeviceListForMapDisplay () {
+	if (!visible.value || !viewer) return
+	deviceMapRequestToken += 1
+	const requestToken = deviceMapRequestToken
+	const res = await fwDeviceListByPolygonsApi({
+		areaId: dialogMode.value === 'add' ? '' : formData.value.id,
+		isAreaSelect: 1,
+		isTrack: 1,
+	})
+	if (requestToken !== deviceMapRequestToken) return
+	const list = res?.data?.data ?? []
+	if (!list.length) {
+		clearDeviceRangePrimitives()
+		clearDeviceIconEntities()
+		return
+	}
+	await renderDeviceRanges(list)
 }
 
 // 关联设备变更
@@ -1394,7 +1399,6 @@
 	selectedDeviceRows.value = rows
 	const ids = rows.map(item => item.id)
 	formData.value.deviceIds = ids.join(',')
-	renderDeviceRanges(rows)
 	if (suppressDeviceFly.value) {
 		lastSelectedDeviceIds = [...ids]
 		return
@@ -1409,12 +1413,13 @@
 
 function handleDeviceRowClick (row) {
 	if (readonly.value) {
-		renderDeviceRangeSingle(row)
 		void flyToDevice(row)
 		return
 	}
-	renderDeviceRanges(selectedDeviceRows.value)
-	void flyToDevice(row)
+	const isSelected = selectedDeviceRows.value.some(item => String(item?.id) === String(row?.id))
+	if (isSelected) {
+		void flyToDevice(row)
+	}
 }
 
 // 同步选择状态
@@ -1429,10 +1434,6 @@
 	})
 	selectedDeviceRows.value = rows
 	formData.value.deviceIds = rows.map(item => item.id).join(',')
-	if (readonly.value) {
-		renderDeviceRanges(selectedDeviceRows.value)
-		return
-	}
 	if (!deviceTableRef.value) return
 	deviceTableRef.value.clearSelection()
 	rows.forEach(row => {
@@ -1499,11 +1500,11 @@
 	lastSelectedDeviceIds = selectedDeviceRows.value.map(row => row.id)
 	await nextTick()
 	suppressDeviceFly.value = false
-	if (!readonly.value) {
-		renderDeviceRanges(selectedDeviceRows.value)
-	}
 	isDialogInitializing.value = false
 	queueDeviceListRefresh()
+	if (dialogMode.value === 'add' || dialogMode.value === 'edit') {
+		void getDeviceListForMapDisplay()
+	}
 	void getPoliceStationList()
 }
 

--
Gitblit v1.9.3