From 91bb9f7781ce95e3a7acde3602eeae0c1c3613ff Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Tue, 03 Feb 2026 17:20:42 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 applications/drone-command/env/.env.production                                                |    3 
 applications/drone-command/src/styles/common/cockpit.scss                                     |    2 
 applications/drone-command/src/views/areaManage/sceneConfig/index.vue                         |    2 
 uniapps/work-wx/src/subPackages/userDetail/password/index.vue                                 |    1 
 applications/drone-command/env/.env.test                                                      |    3 
 uniapps/work-wx/src/subPackages/deviceRegistration/add.vue                                    |    6 
 uniapps/work-wx/src/subPackages/flightApplication/add.vue                                     |   56 +++---
 applications/drone-command/src/views/permissionManage/permissionDept/index.vue                |   58 ++++++
 applications/task-work-order/env/.env.production                                              |    3 
 applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue                      |   48 +++++
 applications/task-work-order/env/.env                                                         |    4 
 applications/drone-command/src/views/api.txt                                                  |   90 ++++++++--
 applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue           |    2 
 applications/task-work-order/env/.env.test                                                    |   24 ++
 applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue          |   26 +-
 applications/drone-command/env/.env.development                                               |    4 
 uniapps/work-wx/src/subPackages/deviceRegistration/details.vue                                |   31 ++-
 applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue |   35 ++--
 applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue                    |   55 ++++++
 applications/task-work-order/src/styles/theme/white.scss                                      |    4 
 applications/drone-command/env/.env                                                           |   12 +
 applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue            |    4 
 22 files changed, 349 insertions(+), 124 deletions(-)

diff --git a/applications/drone-command/env/.env b/applications/drone-command/env/.env
index 2fef687..fc813f9 100644
--- a/applications/drone-command/env/.env
+++ b/applications/drone-command/env/.env
@@ -1,3 +1,13 @@
+/*
+ * @Author       : yuan
+ * @Date         : 2026-01-07 14:58:30
+ * @LastEditors  : yuan
+ * @LastEditTime : 2026-02-03 15:43:33
+ * @FilePath     : \applications\drone-command\env\.env
+ * @Description  : 
+ * Copyright 2026 OBKoro1, All Rights Reserved. 
+ * 2026-01-07 14:58:30
+ */
 #接口地址
 VITE_APP_API=/api
 
@@ -12,3 +22,5 @@
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli
 VITE_BUILD_COMPRESS=gzip
+
+VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_c_uas/
diff --git a/applications/drone-command/env/.env.development b/applications/drone-command/env/.env.development
index e005479..67d4a44 100644
--- a/applications/drone-command/env/.env.development
+++ b/applications/drone-command/env/.env.development
@@ -2,7 +2,7 @@
  # @Author       : yuan
  # @Date         : 2026-01-31 14:34:31
  # @LastEditors  : yuan
- # @LastEditTime : 2026-02-03 09:34:48
+ # @LastEditTime : 2026-02-03 15:52:27
  # @FilePath     : \applications\drone-command\env\.env.development
  # @Description  : 
  # Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -30,8 +30,6 @@
 # 航线文件地址
 VITE_APP_AIRLINE_URL=https://wrj.shuixiongit.com/minio/cloud-bucket
 
-# 地形存放
-VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_c_uas/
 # 行政区划存放地址
 VITE_APP_REGION_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_region
 # 算法仓库图片地址
diff --git a/applications/drone-command/env/.env.production b/applications/drone-command/env/.env.production
index 02a980f..6121cb1 100644
--- a/applications/drone-command/env/.env.production
+++ b/applications/drone-command/env/.env.production
@@ -19,9 +19,6 @@
 # 航线文件地址
 VITE_APP_AIRLINE_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket
 
-# 图片存放地址
-VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_terrain/
-
 # 算法仓库图片地址
 VITE_APP_PICTURE_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket
 
diff --git a/applications/drone-command/env/.env.test b/applications/drone-command/env/.env.test
index 4600bb8..923fe31 100644
--- a/applications/drone-command/env/.env.test
+++ b/applications/drone-command/env/.env.test
@@ -18,9 +18,6 @@
 # 航线文件地址
 VITE_APP_AIRLINE_URL = https://wrj.shuixiongit.com/minio/cloud-bucket
 
-# 图片存放地址
-VITE_APP_TERRAIN_URL = https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_terrain/
-
 # 算法仓库图片地址
 VITE_APP_PICTURE_URL = https://wrj.shuixiongit.com/aiskyminio/cloud-bucket
 
diff --git a/applications/drone-command/src/styles/common/cockpit.scss b/applications/drone-command/src/styles/common/cockpit.scss
index 1cafd18..be0e93d 100644
--- a/applications/drone-command/src/styles/common/cockpit.scss
+++ b/applications/drone-command/src/styles/common/cockpit.scss
@@ -1316,7 +1316,7 @@
                     align-items: center;
 
                     .label {
-                        width: 88px;
+                        min-width: 88px;
                         font-family: Source Han Sans CN, Source Han Sans CN;
                         font-weight: 500;
                         font-size: 14px;
diff --git a/applications/drone-command/src/views/api.txt b/applications/drone-command/src/views/api.txt
index 7626b6d..ab098cd 100644
--- a/applications/drone-command/src/views/api.txt
+++ b/applications/drone-command/src/views/api.txt
@@ -3,7 +3,7 @@
 ## 列表
 
 
-**接口地址**:`/area/fwPoliceStation/list`
+**接口地址**:`/device/fwDevice/list`
 
 
 **请求方式**:`GET`
@@ -15,7 +15,7 @@
 **响应数据类型**:`*/*`
 
 
-**接口描述**:<p>获取全部派出所</p>
+**接口描述**:<p>传入isAreaSelect、areaId、areaIds(多个用,隔开获取对应区域绑定设备数据)、status</p>
 
 
 
@@ -25,7 +25,13 @@
 **请求参数**:
 
 
-暂无
+| 参数名称 | 参数说明 | 请求类型    | 是否必须 | 数据类型 | schema |
+| -------- | -------- | ----- | -------- | -------- | ------ |
+|areaId|areaId|query|false|integer(int64)||
+|areaIds|areaIds(多个用,隔开)|query|false|string||
+|isAreaSelect|isAreaSelect|query|false|integer(int32)||
+|isTrack|isTrack|query|false|integer(int32)||
+|status|status|query|false|integer(int32)||
 
 
 **响应状态**:
@@ -33,7 +39,7 @@
 
 | 状态码 | 说明 | schema |
 | -------- | -------- | ----- | 
-|200|OK|R«List«FwPoliceStationVO»»|
+|200|OK|R«List«FwDeviceVO»»|
 |401|Unauthorized||
 |403|Forbidden||
 |404|Not Found||
@@ -45,21 +51,41 @@
 | 参数名称 | 参数说明 | 类型 | schema |
 | -------- | -------- | ----- |----- | 
 |code|状态码|integer(int32)|integer(int32)|
-|data|承载数据|array|FwPoliceStationVO|
-|&emsp;&emsp;address|派出所地址|string||
-|&emsp;&emsp;areaCode|区域编码|string||
-|&emsp;&emsp;contactPerson|联系人|string||
-|&emsp;&emsp;contactPhone|联系方式|string||
+|data|承载数据|array|FwDeviceVO|
+|&emsp;&emsp;azimuth|方位角 0-360°|integer(int32)||
+|&emsp;&emsp;batteryPct|电量百分比 0-100|integer(int32)||
+|&emsp;&emsp;belongDept|所属部门id|integer(int64)||
+|&emsp;&emsp;belongDeptName|所属部门名称|string||
+|&emsp;&emsp;charger|负责人|string||
+|&emsp;&emsp;contactPhone|联系电话|string||
 |&emsp;&emsp;createDept|创建部门|integer(int64)||
 |&emsp;&emsp;createTime|创建时间|string(date-time)||
 |&emsp;&emsp;createUser|创建人|integer(int64)||
-|&emsp;&emsp;id|主键id|integer(int64)||
-|&emsp;&emsp;latitude|纬度|number(double)||
-|&emsp;&emsp;longitude|经度|number(double)||
-|&emsp;&emsp;stationName|派出所名称|string||
-|&emsp;&emsp;status|状态(0正常 1停用)|integer(int32)||
+|&emsp;&emsp;detectTargetCnt|侦测目标数量|integer(int32)||
+|&emsp;&emsp;deviceAtt|设备属性(无线电/光电/雷达)|string||
+|&emsp;&emsp;deviceModel|型号|string||
+|&emsp;&emsp;deviceName|设备名称|string||
+|&emsp;&emsp;deviceSn|设备sn|string||
+|&emsp;&emsp;deviceSpecification|规格|string||
+|&emsp;&emsp;deviceType|设备类型(察打一体/便捷侦测箱/反制枪)|string||
+|&emsp;&emsp;effectiveRangeKm|有效范围 km|number||
+|&emsp;&emsp;elevation|俯仰角 -90-+90°|integer(int32)||
+|&emsp;&emsp;id|主键|integer(int64)||
+|&emsp;&emsp;isShared|是否被共享给当前机构|boolean||
+|&emsp;&emsp;latitude|纬度|string||
+|&emsp;&emsp;longitude|经度|string||
+|&emsp;&emsp;manufacturer|生产厂商|string||
+|&emsp;&emsp;outTarget|出库去向|string||
+|&emsp;&emsp;purpose|用途|string||
+|&emsp;&emsp;remark|备注|string||
+|&emsp;&emsp;sceneName|场景名称|string||
+|&emsp;&emsp;shareId|共享记录ID|integer(int64)||
+|&emsp;&emsp;source|来源|string||
+|&emsp;&emsp;status|运行状态(0:在线/1:离线/2:故障/3:报废)|integer(int32)||
+|&emsp;&emsp;trackStatus|设备出入库状态 0未出库1已出库|integer(int32)||
 |&emsp;&emsp;updateTime|更新时间|string(date-time)||
 |&emsp;&emsp;updateUser|更新人|integer(int64)||
+|&emsp;&emsp;workMode|工作模式:1.侦测中/2.信号干扰中/3.诱导驱离中/4.待机|string||
 |msg|返回消息|string||
 |success|是否成功|boolean||
 
@@ -70,23 +96,43 @@
 	"code": 0,
 	"data": [
 		{
-			"address": "",
-			"areaCode": "",
-			"contactPerson": "",
+			"azimuth": 0,
+			"batteryPct": 0,
+			"belongDept": 0,
+			"belongDeptName": "",
+			"charger": "",
 			"contactPhone": "",
 			"createDept": 0,
 			"createTime": "",
 			"createUser": 0,
+			"detectTargetCnt": 0,
+			"deviceAtt": "",
+			"deviceModel": "",
+			"deviceName": "",
+			"deviceSn": "",
+			"deviceSpecification": "",
+			"deviceType": "",
+			"effectiveRangeKm": 0,
+			"elevation": 0,
 			"id": 0,
-			"latitude": 0,
-			"longitude": 0,
-			"stationName": "",
+			"isShared": true,
+			"latitude": "",
+			"longitude": "",
+			"manufacturer": "",
+			"outTarget": "",
+			"purpose": "",
+			"remark": "",
+			"sceneName": "",
+			"shareId": 0,
+			"source": "",
 			"status": 0,
+			"trackStatus": 0,
 			"updateTime": "",
-			"updateUser": 0
+			"updateUser": 0,
+			"workMode": ""
 		}
 	],
 	"msg": "",
 	"success": true
 }
-```
\ No newline at end of file
+```
diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
index 3c51a03..342b43c 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -260,6 +260,7 @@
 import ellipseIcon from '@/assets/images/areaMap/ellipse.png'
 import bufferIcon from '@/assets/images/areaMap/buffer.png'
 import trashIcon from '@/assets/images/areaMap/trash.png'
+import equipmentIcon from '@/assets/images/dataCockpit/map/equipment.png'
 
 const initForm = () => ({
 	areaName: '', // 区域名称
@@ -314,6 +315,7 @@
 let viewEntity
 let shapeDisplaySource
 const deviceRangePrimitiveMap = new Map()
+const deviceIconEntityMap = new Map()
 const activeToolMode = ref('')
 const suppressDeviceFly = ref(false)
 const isDialogInitializing = ref(false)
@@ -437,6 +439,7 @@
 			hideTypePanel()
 			clearShapeDisplay()
 			clearDeviceRangePrimitives()
+			clearDeviceIconEntities()
 		}
 	}
 )
@@ -504,10 +507,20 @@
 	deviceRangePrimitiveMap.clear()
 }
 
+function clearDeviceIconEntities () {
+	if (!viewer || !deviceIconEntityMap.size) return
+	for (const entity of deviceIconEntityMap.values()) {
+		viewer.entities.remove(entity)
+	}
+	deviceIconEntityMap.clear()
+}
+
 function clearDeviceListState () {
 	deviceOptions.value = []
 	selectedDeviceRows.value = []
 	formData.value.deviceIds = ''
+	clearDeviceRangePrimitives()
+	clearDeviceIconEntities()
 	if (deviceTableRef.value) {
 		deviceTableRef.value.clearSelection()
 	}
@@ -599,8 +612,10 @@
 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
@@ -620,6 +635,12 @@
 			deviceRangePrimitiveMap.delete(id)
 		}
 	}
+	for (const [id, entity] of deviceIconEntityMap.entries()) {
+		if (!nextIds.has(id)) {
+			viewer.entities.remove(entity)
+			deviceIconEntityMap.delete(id)
+		}
+	}
 	const pendingRows = selectedRows.filter(row => {
 		const id = String(row?.id)
 		return id && !deviceRangePrimitiveMap.has(id)
@@ -628,14 +649,17 @@
 	const primitives = await Promise.all(
 		pendingRows.map(async row => {
 			const position = getDeviceLngLat(row)
-			if (!position) return { row, primitive: null }
+			if (!position) return { row, primitive: null, position: null }
 			const rangeMeters = normalizeDeviceRange(row.effectiveRangeKm)
 			const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
-			return { row, primitive }
+			return { row, primitive, position }
 		})
 	)
 	if (renderToken !== deviceRangeRenderToken) return
-	primitives.forEach(({ row, primitive }) => {
+	primitives.forEach(({ row, primitive, position }) => {
+		if (position) {
+			addDeviceIconEntity(row, position)
+		}
 		if (!primitive) return
 		const id = String(row?.id)
 		if (!nextIds.has(id)) return
@@ -665,6 +689,23 @@
 function clearShapeDisplay () {
 	if (!shapeDisplaySource) return
 	shapeDisplaySource.entities.removeAll()
+}
+
+function addDeviceIconEntity (device, position) {
+	if (!viewer || !position) return
+	const id = String(device?.id ?? '')
+	if (!id || deviceIconEntityMap.has(id)) return
+	const entity = viewer.entities.add({
+		position: Cesium.Cartesian3.fromDegrees(position.lng, position.lat, position.height || 0),
+		billboard: {
+			image: equipmentIcon,
+			width: 28,
+			height: 38,
+			verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+			heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+		},
+	})
+	deviceIconEntityMap.set(id, entity)
 }
 
 function normalizeShapePoint (point) {
@@ -1357,6 +1398,7 @@
 	initMap()
 	clearShapeDisplay()
 	clearDeviceRangePrimitives()
+	clearDeviceIconEntities()
 	viewEntity && viewer?.entities?.remove(viewEntity)
 	viewEntity = null
 	clearActiveTool()
diff --git a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
index a7dc186..f11d973 100644
--- a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
@@ -50,6 +50,20 @@
 							</el-table>
 						</div>
 					</div>
+					<div class="detail-title">设备列表</div>
+					<div class="command-table-container">
+						<div class="command-table-content">
+							<el-table
+								class="command-table"
+								:data="deviceList"
+								:loading="deviceLoading"
+								row-key="id"
+							>
+								<el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
+								<el-table-column prop="deviceType" show-overflow-tooltip label="设备类型" />
+							</el-table>
+						</div>
+					</div>
 				</div>
 
 				<el-form
@@ -128,6 +142,21 @@
 							</el-table>
 						</el-form-item>
 					</div>
+
+					<div class="detail-title">设备列表</div>
+					<div class="command-table-container">
+						<div class="command-table-content">
+							<el-table
+								class="command-table"
+								:data="deviceList"
+								:loading="deviceLoading"
+								row-key="id"
+							>
+								<el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
+								<el-table-column prop="deviceType" show-overflow-tooltip label="设备类型" />
+							</el-table>
+						</div>
+					</div>
 				</el-form>
 
 				<div class="footer">
@@ -160,6 +189,7 @@
 import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
 import * as Cesium from 'cesium'
 import { fwAreaDivideDetailApi, fwAreaDivideListApi } from '../partition/partitionApi'
+import { fwDeviceListApi } from '@/views/basicManage/deviceStock/fwDevice'
 import {
 	addBufferRadiusLabelEntity,
 	buildEllipsePositions,
@@ -189,6 +219,8 @@
 const searchName = ref('')
 const areaList = ref([]) // 关联区域列表
 const selectedAreaRows = ref([]) //选中列表
+const deviceList = ref([]) // 设备列表
+const deviceLoading = ref(false)
 const dictObj = inject('dictObj')
 const mapRef = ref(null)
 const route = useRoute()
@@ -242,6 +274,20 @@
 	if (areaList.value.length) return
 	const res = await fwAreaDivideListApi({ filterSelected: 1, sceneId: formData.value.id })
 	areaList.value = res?.data?.data ?? []
+}
+
+async function loadDeviceListByAreaIds(areaIdsKey) {
+	if (!areaIdsKey) {
+		deviceList.value = []
+		return
+	}
+	deviceLoading.value = true
+	try {
+		const res = await fwDeviceListApi({ areaIds: areaIdsKey })
+		deviceList.value = res?.data?.data ?? []
+	} finally {
+		deviceLoading.value = false
+	}
 }
 
 // 关联区域变更
@@ -514,6 +560,15 @@
 }
 
 watch(() => selectedAreaRows.value, renderSelectedAreas)
+const deviceAreaIdsKey = computed(() =>
+	selectedAreaRows.value.map(item => item?.id).filter(Boolean).join(',')
+)
+watch(
+	() => deviceAreaIdsKey.value,
+	val => {
+		loadDeviceListByAreaIds(val)
+	}
+)
 watch(
 	() => visible.value,
 	val => {
diff --git a/applications/drone-command/src/views/areaManage/sceneConfig/index.vue b/applications/drone-command/src/views/areaManage/sceneConfig/index.vue
index 7ef87d3..e0bca9e 100644
--- a/applications/drone-command/src/views/areaManage/sceneConfig/index.vue
+++ b/applications/drone-command/src/views/areaManage/sceneConfig/index.vue
@@ -54,7 +54,7 @@
 					</el-table-column>
 					<el-table-column prop="areaCount" show-overflow-tooltip label="区域数量" />
 					<el-table-column prop="counterDeviceCount" show-overflow-tooltip label="反制设备数量" />
-					<el-table-column prop="detectDeviceCount" show-overflow-tooltip label="探测设备数量" />
+					<el-table-column prop="detectDeviceCount" show-overflow-tooltip label="侦测设备数量" />
 					<el-table-column label="操作" class-name="operation-btns">
 						<template v-slot="{ row }">
 							<el-link @click="openForm('view', row)">查看</el-link>
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
index 13edcb7..757fb42 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
@@ -24,7 +24,7 @@
 							placeholder="请选择"
 							clearable
 						>
-							<el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.label" />
+							<el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" />
 						</el-select>
 					</el-form-item>
 				</el-col>
@@ -137,9 +137,11 @@
 	submitting.value = true
 	try {
 		const selected = areaOptions.value.find(item => item.value === formData.value.outTarget)
+
 		const payload = {
 			...formData.value,
 			outTarget: selected?.label ?? formData.value.outTarget,
+			outTargetCode: formData.value.outTarget
 		}
 		await fwDeviceTrackSubmitApi(payload)
 		saveOperationLog({
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
index d9adc8c..bacb202 100644
--- a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
@@ -258,7 +258,7 @@
 		})
 		ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功')
 		visible.value = false
-		emit('success')
+		emit('success', { parentId: formData.value.parentId || null, mode: dialogMode.value, isAddChild: isAddChild.value })
 	} finally {
 		submitting.value = false
 	}
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/index.vue b/applications/drone-command/src/views/permissionManage/permissionDept/index.vue
index 0255304..572f9bf 100644
--- a/applications/drone-command/src/views/permissionManage/permissionDept/index.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/index.vue
@@ -87,7 +87,7 @@
 			</div>
 		</div>
 
-		<FormDiaLog ref="dialogRef" @success="getList" v-model="visible" v-if="visible" />
+		<FormDiaLog ref="dialogRef" @success="handleFormSuccess" v-model="visible" v-if="visible" />
 		<ShareDiaLog ref="shareDialogRef" @success="getList" v-model="shareVisible" v-if="shareVisible" />
 	</basic-container>
 </template>
@@ -123,6 +123,8 @@
 const list = ref([])
 const total = ref(0)
 const selectedIds = ref([])
+const selectedRows = ref([])
+const lastActionParentRow = ref(null)
 const queryParamsRef = ref(null)
 const dialogRef = ref(null)
 const shareDialogRef = ref(null)
@@ -133,6 +135,7 @@
 })
 const deptTree = ref([])
 const route = useRoute()
+const treeResolveMap = new Map()
 
 provide('dictObj', dictObj)
 provide('deptTree', deptTree)
@@ -167,6 +170,7 @@
 }
 
 function handleAddChild(row) {
+	lastActionParentRow.value = row
 	visible.value = true
 	nextTick(() => {
 		dialogRef.value?.open({ mode: 'add', parent: row })
@@ -203,6 +207,7 @@
 		cancelButtonClass: 'command-message-box-cancel',
 	})
 	const ids = row ? row.id : selectedIds.value.join(',')
+	const rows = row ? [row] : selectedRows.value
 	await remove(ids)
 	saveOperationLog({
 		requestUri: route.path,
@@ -211,11 +216,18 @@
 	})
 	ElMessage.success('删除成功')
 	selectedIds.value = []
-	getList()
+	selectedRows.value = []
+	const parentIds = Array.from(new Set(rows.map(item => item.parentId).filter(Boolean)))
+	const hasRoot = rows.some(item => !item.parentId)
+	if (hasRoot) {
+		getList()
+	}
+	parentIds.forEach(parentId => refreshChildNodes(parentId))
 }
 
 function handleSelectionChange(rows) {
 	selectedIds.value = rows.map(item => item.id)
+	selectedRows.value = rows
 }
 
 function getDictList() {
@@ -236,11 +248,49 @@
 }
 
 function loadChildren(row, treeNode, resolve) {
+	treeResolveMap.set(row.id, { resolve, row })
 	getChildLazyTree({ parentId: row.id })
 		.then(res => {
-			resolve(res?.data?.data ?? [])
+			const children = res?.data?.data ?? []
+			row.hasChildren = children.length > 0
+			resolve(children)
 		})
-		.catch(() => resolve([]))
+		.catch(() => {
+			row.hasChildren = false
+			resolve([])
+		})
+}
+
+function refreshChildNodes(parentId) {
+	const cache = treeResolveMap.get(parentId)
+	if (!cache?.resolve) return
+	getChildLazyTree({ parentId })
+		.then(res => {
+			const children = res?.data?.data ?? []
+			if (cache.row) {
+				cache.row.hasChildren = children.length > 0
+			}
+			cache.resolve(children)
+		})
+		.catch(() => {
+			if (cache.row) {
+				cache.row.hasChildren = false
+			}
+			cache.resolve([])
+		})
+}
+
+function handleFormSuccess(payload = {}) {
+	if (payload?.parentId) {
+		refreshChildNodes(payload.parentId)
+		if (payload.isAddChild && lastActionParentRow.value?.id === payload.parentId) {
+			lastActionParentRow.value.hasChildren = true
+		}
+		lastActionParentRow.value = null
+		return
+	}
+	lastActionParentRow.value = null
+	getList()
 }
 
 onMounted(() => {
diff --git a/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue b/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
index 869bdae..36a6d36 100644
--- a/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
+++ b/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
@@ -9,7 +9,15 @@
 	>
 		<div class="dialog-container">
 			<div class="left-container">
-				<div class="leftMap command-cesium" id="leftMapContainer"></div>
+				<CommonCesiumMap
+					ref="mapRef"
+					class="leftMap command-cesium"
+					:active="visible"
+					:flat-mode="false"
+					:terrain="true"
+					:layer-mode="4"
+					:boundary="false"
+				/>
 			</div>
 			<div class="right-container">
 				<div class="header">
@@ -67,11 +75,10 @@
 import { Close } from '@element-plus/icons-vue'
 
 import { computed, nextTick, ref } from 'vue'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
 import { fwDroneFlightRecordDetailApi } from '@/views/recordManage/historyTracks/fwDroneFlightRecord'
 import { fwDroneFlightRecordDetailPageApi } from '@/views/recordManage/historyTracks/flyTrajectory'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
 import * as Cesium from 'cesium'
-import { flyVisual } from '@ztzf/utils'
 import { ArrowLineMaterialProperty } from '@/utils/cesium/Material'
 import droneIcon from '@/assets/images/dataCockpit/map/drone.png'
 
@@ -83,11 +90,11 @@
 	stayDuration: '',
 })
 let list = ref([])
-const emit = defineEmits(['success'])
 const formData = ref(initForm()) // 表单数据
 const visible = ref(false) // 弹框显隐
 const dialogMode = ref('add') // 弹框模式
 const dialogReadonly = computed(() => dialogMode.value === 'view')
+const mapRef = ref(null)
 const dialogTitle = computed(() => {
 	if (dialogMode.value === 'edit') {
 		return '编辑'
@@ -170,14 +177,9 @@
 let viewer, geometricSource, droneLineEntity, startDroneEntity
 function initMap() {
 	if (viewer) return
-	const publicCesiumInstance = new PublicCesium({
-		dom: 'leftMapContainer',
-		flatMode: false,
-		terrain: true,
-		layerMode: 4,
-		boundary: false,
-	})
-	viewer = publicCesiumInstance.getViewer()
+	const map = mapRef.value?.getMap?.()
+	if (!map?.viewer) return
+	viewer = map.viewer
 	geometricSource = new Cesium.CustomDataSource('geometricSource')
 	viewer.dataSources.add(geometricSource)
 }
diff --git a/applications/task-work-order/env/.env b/applications/task-work-order/env/.env
index fb9ce69..fd35dce 100644
--- a/applications/task-work-order/env/.env
+++ b/applications/task-work-order/env/.env
@@ -20,6 +20,6 @@
 VITE_BUILD_COMPRESS=gzip
 
 # 预览地址 previewURL
-VITE_APP_PREVIEW_URL=http://192.168.1.204:8012
+VITE_APP_PREVIEW_URL=http://192.168.1.36:8012
 
-VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_c_uas/
+VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_c_uas/
\ No newline at end of file
diff --git a/applications/task-work-order/env/.env.production b/applications/task-work-order/env/.env.production
index 19eb420..ec45574 100644
--- a/applications/task-work-order/env/.env.production
+++ b/applications/task-work-order/env/.env.production
@@ -16,8 +16,5 @@
 # 航线文件地址
 VITE_APP_AIRLINE_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket
 
-# 图片存放地址
-VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_terrain/
-
 # 行政区划存放地址
 VITE_APP_REGION_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_region
diff --git a/applications/task-work-order/env/.env.test b/applications/task-work-order/env/.env.test
index 40b3bf8..71ff553 100644
--- a/applications/task-work-order/env/.env.test
+++ b/applications/task-work-order/env/.env.test
@@ -1,3 +1,23 @@
+###
+ # @Author       : yuan
+ # @Date         : 2026-02-03 13:46:08
+ # @LastEditors  : yuan
+ # @LastEditTime : 2026-02-03 15:44:11
+ # @FilePath     : \applications\task-work-order\env\.env.test
+ # @Description  : 
+ # Copyright 2026 OBKoro1, All Rights Reserved. 
+ # 2026-02-03 13:46:08
+### 
+###
+ # @Author       : yuan
+ # @Date         : 2026-02-03 13:46:08
+ # @LastEditors  : yuan
+ # @LastEditTime : 2026-02-03 15:44:01
+ # @FilePath     : \applications\task-work-order\env\.env.test
+ # @Description  : 
+ # Copyright 2026 OBKoro1, All Rights Reserved. 
+ # 2026-02-03 13:46:08
+### 
 NODE_ENV='test'
 
 #开发环境配置
@@ -14,10 +34,6 @@
 
 # 航线文件地址
 VITE_APP_AIRLINE_URL=https://wrj.shuixiongit.com/minio/cloud-bucket
-
-# 图片存放地址
-VITE_APP_TERRAIN_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_terrain/
-
 
 # 行政区划存放地址
 VITE_APP_REGION_URL=https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_region
diff --git a/applications/task-work-order/src/styles/theme/white.scss b/applications/task-work-order/src/styles/theme/white.scss
index 5799dcc..6755133 100644
--- a/applications/task-work-order/src/styles/theme/white.scss
+++ b/applications/task-work-order/src/styles/theme/white.scss
@@ -88,6 +88,10 @@
         color: #666
       }
 
+      .iconfont{
+        font-size: 14px;
+      }
+
       &:hover {
         background: transparent;
 
diff --git a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
index d5e84a7..5ecf6e8 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
@@ -450,49 +450,46 @@
 })
 // 获取航线详情
 function getAirDetails() {
-	console.log(formData.value)
+	const dockHeight = formData.value.height
 	queryAirById(formData.value.patrolRouteUrl).then(res => {
-		const list = res.data.data.airlineWaypoints
+		const {airlineWaypoints,airlineSetting:{globalAirlineHeight,airlineHeightMode}} = res.data.data
+		const relative = airlineHeightMode === 'relativeToStartPoint'
+		const list = airlineWaypoints
 		if (!list.length) return mapRef.value?.flyBoundary()
-		const result = list.map(item => [Number(item.longitude), Number(item.latitude)]).flat()
+		const result = list.map(item => {
+			let height = item?.globalHeight || globalAirlineHeight
+			if (relative){
+				height = height + Number(dockHeight)
+			}
+			return [Number(item.longitude), Number(item.latitude),height || 0]
+		})
 		viewer.entities.add({
 			polyline: {
-				positions: Cesium.Cartesian3.fromDegreesArray(result),
-				clampToGround: true,
+				positions: Cesium.Cartesian3.fromDegreesArrayHeights(result.flat()),
 				width: 4,
 				material: arrowLineMaterialProperty,
 			},
 		})
 		// 渲染起点(蓝色)
-		const startPoint = list[0]
+		const startPoint = result[0]
 		viewer.entities.add({
-			position: Cesium.Cartesian3.fromDegrees(
-				Number(startPoint.longitude),
-				Number(startPoint.latitude),
-				startPoint.height || 0
-			),
+			position: Cesium.Cartesian3.fromDegrees(Number(startPoint[0]), Number(startPoint[1]), startPoint[2]),
 			point: {
 				pixelSize: 12,
 				color: Cesium.Color.BLUE,
 				outlineColor: Cesium.Color.WHITE,
 				outlineWidth: 2,
-				heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
 			},
 		})
 		// 渲染终点(红色)
-		const endPoint = list[list.length - 1]
+		const endPoint = result[result.length - 1]
 		viewer.entities.add({
-			position: Cesium.Cartesian3.fromDegrees(
-				Number(endPoint.longitude),
-				Number(endPoint.latitude),
-				endPoint.height || 0
-			),
+			position: Cesium.Cartesian3.fromDegrees(Number(endPoint[0]), Number(endPoint[1]), endPoint[2]),
 			point: {
 				pixelSize: 12,
 				color: Cesium.Color.RED,
 				outlineColor: Cesium.Color.WHITE,
 				outlineWidth: 2,
-				heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
 			},
 		})
 		flyVisual({
diff --git a/uniapps/work-wx/src/subPackages/deviceRegistration/add.vue b/uniapps/work-wx/src/subPackages/deviceRegistration/add.vue
index 6541906..08034e4 100644
--- a/uniapps/work-wx/src/subPackages/deviceRegistration/add.vue
+++ b/uniapps/work-wx/src/subPackages/deviceRegistration/add.vue
@@ -258,7 +258,7 @@
             </view>
                 <u-radio-group
                 v-if="!loadingManufacturer"
-                    v-model="formParams.spacecraftId"
+                    v-model="formParams.manufacturer"
                     placement="column"
                     @change="radioChange"
                 >
@@ -426,7 +426,7 @@
     formParams.value.region = e[2] || '' // 用逗号分隔的区域码
     // 通过arrRegion的数组值为[36,3608,360824] 从areaData里面反查出名称
     const regionNames = findRegionNamesByCodes(e, areaData.value)
-    formParams.value.regionText = regionNames.join('-') || '' // 用连字符连接的区域名称
+    formParams.value.regionText = regionNames.join(',') || '' // 用连字符连接的区域名称
     isShowRegion.value = false
 }
 // 是否有保险
@@ -671,7 +671,7 @@
     // 检查响应
     if (response.statusCode === 200) {
         areaData.value = response.data
-        console.log('请求成功:', data)
+        // console.log('请求成功:', data)
         // 处理数据
     } else {
         console.error('请求失败:', response)
diff --git a/uniapps/work-wx/src/subPackages/deviceRegistration/details.vue b/uniapps/work-wx/src/subPackages/deviceRegistration/details.vue
index e10db1d..8bc3a92 100644
--- a/uniapps/work-wx/src/subPackages/deviceRegistration/details.vue
+++ b/uniapps/work-wx/src/subPackages/deviceRegistration/details.vue
@@ -313,12 +313,6 @@
         current: 1,
         size: 1000,
     }).then(res => {
-        // manufacturerList.value = res.data.data.records.map(item => ({
-        //     ...item,
-        //     label: item.unitName,
-        //     value: item.id,
-        // }))
-        console.log(formParams.value.manufacturer, res.data.data.records.find(item => item.id === formParams.value.manufacturer))
         formParams.value.manufacturerText = res.data.data.records.find(item => item.id === formParams.value.manufacturer)?.unitName || ''
     })
 }
@@ -329,7 +323,9 @@
         formParams.value.hasInsurance = res.data.data.hasInsurance === '1' ? '有' : '无'
         // formParams.value.manufacturer = manufacturerList.value.find(item => item.value === res.data.data.manufacturer)?.label || ''
         formParams.value.type = typeList.value.find(item => item.value === res.data.data.type)?.label || ''
-        formParams.value.region = res.data.data.region
+        // formParams.value.region = res.data.data.region
+        // 360824 截取留前两位 3608 截取留前四位
+        formParams.value.region = findRegionNamesByCodes([res.data.data.region.slice(0,2),res.data.data.region.slice(0,4),res.data.data.region], areaData.value)
         getManufacturerInfoApi()
     })
     
@@ -339,8 +335,25 @@
     // getManufacturerInfoApi()
     getProTypeApi()
     // 动态导入xzqhData,确保在使用前已初始化
-    const { xzqhData } = await import('@/static/xzqh/index')
-    areaData.value = xzqhData
+    // const { xzqhData } = await import('@/static/xzqh/index')
+    // areaData.value = xzqhData
+    const response = await uni.request({
+        url: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ja-app-wx/xzqh/index.json',
+        method: 'GET',
+        timeout: 10000, // 10秒超时
+        dataType: 'json'
+    })
+
+    // 检查响应
+    if (response.statusCode === 200) {
+        
+        areaData.value = response.data
+        // console.log('请求成功:', data)
+        // 处理数据
+    } else {
+        console.error('请求失败:', response)
+        throw new Error(`请求失败: ${response.statusCode}`)
+    }
 })
 </script>
 <style scoped lang="scss">
diff --git a/uniapps/work-wx/src/subPackages/flightApplication/add.vue b/uniapps/work-wx/src/subPackages/flightApplication/add.vue
index 9bccfe4..ec51e8f 100644
--- a/uniapps/work-wx/src/subPackages/flightApplication/add.vue
+++ b/uniapps/work-wx/src/subPackages/flightApplication/add.vue
@@ -360,32 +360,30 @@
     <u-popup
     :show="isShowAircraftInfo"
     mode="bottom"
-    round="20"
+    round="0"
     @close="isShowAircraftInfo = false"
   >
   <scroll-view scroll-y>
     <view class="select-header">
-        <view>请选择飞行器</view>
-        <view class="select-header-btn">
-            <view class="cancel-btn" @click="isShowAircraftInfo = false">取消</view>
-            <view @click="onPickerAircraftInfo">确定</view>
-        </view>
+        <!-- <view>请选择飞行器</view> -->
+        <view class="cancel-btn" @click="isShowAircraftInfo = false">取消</view>
+        <view class="confirm-btn" @click="onPickerAircraftInfo">确定</view>
     </view>
     <view class="select-content">
-          <up-checkbox-group
+          <u-checkbox-group
             v-model="formParams.spacecraftId"
             placement="column"
             @change="checkboxChange"
         >
-            <up-checkbox
+            <u-checkbox
                 :customStyle="{marginBottom: '8px'}"
                 v-for="(item, index) in aircraftInfoList"
                 :key="item.id"
                 :label="item.label"
                 :name="item.value"
             >
-            </up-checkbox>
-        </up-checkbox-group>
+            </u-checkbox>
+        </u-checkbox-group>
     </view>
     </scroll-view>
   </u-popup>
@@ -400,32 +398,30 @@
     <u-popup
     :show="isShowPilotInfo"
     mode="bottom"
-    round="20"
+    round="0"
     @close="isShowPilotInfo = false"
   >
   <scroll-view scroll-y>
     <view class="select-header">
-        <view>请选择飞手</view>
-        <view class="select-header-btn">
-            <view class="cancel-btn" @click="isShowPilotInfo = false">取消</view>
-            <view @click="onPickerPilotInfo">确定</view>
-        </view>
+        <!-- <view>请选择飞手</view> -->
+        <view class="cancel-btn" @click="isShowPilotInfo = false">取消</view>
+        <view class="confirm-btn" @click="onPickerPilotInfo">确定</view>
     </view>
     <view class="select-content">
-          <up-checkbox-group
+          <u-checkbox-group
             v-model="formParams.pilotId"
             placement="column"
             @change="checkboxPilotChange"
         >
-            <up-checkbox
+            <u-checkbox
                 :customStyle="{marginBottom: '8px'}"
                 v-for="(item, index) in pilotInfoList"
                 :key="item.id"
                 :label="item.label"
                 :name="item.value"
             >
-            </up-checkbox>
-        </up-checkbox-group>
+            </u-checkbox>
+        </u-checkbox-group>
     </view>
     </scroll-view>
   </u-popup>
@@ -645,7 +641,7 @@
 //   isShowAircraftInfo.value = false
 // }
 function checkboxChange(val) {
-    formParams.value.spacecraftId = val.join(',')
+    formParams.value.spacecraftId = val
     formParams.value.spacecraftText = aircraftInfoList.value.filter(item => val.includes(item.value)).map(item => item.label).join(',')
 }
 const onPickerAircraftInfo = () => {
@@ -666,7 +662,7 @@
     })
 }
 function checkboxPilotChange(val) {
-    formParams.value.pilotId = val.join(',')
+    formParams.value.pilotId = val
     formParams.value.pilotText = pilotInfoList.value.filter(item => val.includes(item.value)).map(item => item.label).join(',')
 }
 const onPickerPilotInfo = (e) => {
@@ -775,6 +771,8 @@
 const submitForm = async () => {
   await formRef.value.validate()
   isSubmitDisabled.value = true
+  formParams.value.pilotId = formParams.value.pilotId.join(',')
+  formParams.value.spacecraftId = formParams.value.spacecraftId.join(',')
   flightPlanSaveApi(formParams.value).then(res => {
     if (res.data.code === 200) {
         isSubmitDisabled.value = true
@@ -953,19 +951,17 @@
         padding: 20rpx 20rpx;
         font-size: 32rpx;
         color: #222324;
-        .select-header-btn {
-            display: flex;
-            font-size: 28rpx;
+        .cancel-btn {
+            color: #86909C;
+            margin-right: 20rpx;
+        }
+        .confirm-btn {
             color: #1D6FE9;
-            .cancel-btn {
-                color: #86909C;
-                margin-right: 20rpx;
-            }
         }
     }
 
     .select-content {
-        height: 600rpx;
+        height: 480rpx;
         text-align: center;
         padding: 20rpx 20rpx;
     }
diff --git a/uniapps/work-wx/src/subPackages/userDetail/password/index.vue b/uniapps/work-wx/src/subPackages/userDetail/password/index.vue
index 282c67b..8381ad7 100644
--- a/uniapps/work-wx/src/subPackages/userDetail/password/index.vue
+++ b/uniapps/work-wx/src/subPackages/userDetail/password/index.vue
@@ -287,6 +287,7 @@
 
 
 				.rowTitle {
+					width: 160rpx;
 					font-family: Source Han Sans CN, Source Han Sans CN;
 					font-weight: 400;
 					font-size: 30rpx;

--
Gitblit v1.9.3