From 4ee55a85df6b5ef0e14832a02df4c76753717c50 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Wed, 04 Feb 2026 11:38:20 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue | 125 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 122 insertions(+), 3 deletions(-)
diff --git a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
index f11d973..ae57019 100644
--- a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
@@ -60,7 +60,11 @@
row-key="id"
>
<el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
- <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型" />
+ <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型">
+ <template v-slot="{ row }">
+ {{ getDictLabel(row.deviceType, dictObj.deviceType) }}
+ </template>
+ </el-table-column>
</el-table>
</div>
</div>
@@ -153,7 +157,11 @@
row-key="id"
>
<el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
- <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型" />
+ <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型">
+ <template v-slot="{ row }">
+ {{ getDictLabel(row.deviceType, dictObj.deviceType) }}
+ </template>
+ </el-table-column>
</el-table>
</div>
</div>
@@ -195,9 +203,15 @@
buildEllipsePositions,
} from '@/utils/cesium/shapeTools'
import { cartesian3Convert } from '@/utils/cesium/mapUtil'
+import {
+ createDeviceRangePrimitive,
+ getDeviceLngLat,
+ normalizeDeviceRange,
+} from '@/utils/cesium/deviceRange'
import { saveOperationLog } from '@ztzf/apis'
import { useRoute } from 'vue-router'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
+import equipmentIcon from '@/assets/images/dataCockpit/map/equipment.png'
const initForm = () => ({
sceneName: '', // 配置名称
@@ -219,6 +233,7 @@
const searchName = ref('')
const areaList = ref([]) // 关联区域列表
const selectedAreaRows = ref([]) //选中列表
+let lastSelectedAreaIds = []
const deviceList = ref([]) // 设备列表
const deviceLoading = ref(false)
const dictObj = inject('dictObj')
@@ -226,6 +241,9 @@
const route = useRoute()
let viewer
let areaDisplaySource
+const deviceRangePrimitiveMap = new Map()
+const deviceIconEntityMap = new Map()
+let deviceRangeRenderToken = 0
const rules = {
sceneName: fieldRules(true, 50),
@@ -279,12 +297,16 @@
async function loadDeviceListByAreaIds(areaIdsKey) {
if (!areaIdsKey) {
deviceList.value = []
+ clearDeviceRangePrimitives()
+ clearDeviceIconEntities()
return
}
deviceLoading.value = true
try {
const res = await fwDeviceListApi({ areaIds: areaIdsKey })
deviceList.value = res?.data?.data ?? []
+ await nextTick()
+ renderDeviceRanges(deviceList.value)
} finally {
deviceLoading.value = false
}
@@ -292,11 +314,17 @@
// 关联区域变更
async function handleAreaSelectionChange(rows) {
+ const prevIds = new Set(lastSelectedAreaIds)
const selectedRows = await ensureAreaExtList(rows)
selectedAreaRows.value = selectedRows
const ids = selectedRows.map(item => item.id)
+ lastSelectedAreaIds = [...ids]
formData.value.areaDivideIds = ids.join(',')
formData.value.areaCount = ids.length
+ if (ids.some(id => !prevIds.has(id))) {
+ await nextTick()
+ fitViewToSelectedAreas()
+ }
}
// 渲染面
@@ -312,6 +340,22 @@
function clearAreaDisplay() {
if (!areaDisplaySource) return
areaDisplaySource.entities.removeAll()
+}
+
+function clearDeviceRangePrimitives() {
+ if (!viewer || !deviceRangePrimitiveMap.size) return
+ for (const primitive of deviceRangePrimitiveMap.values()) {
+ viewer.scene.primitives.remove(primitive)
+ }
+ deviceRangePrimitiveMap.clear()
+}
+
+function clearDeviceIconEntities() {
+ if (!viewer || !deviceIconEntityMap.size) return
+ for (const entity of deviceIconEntityMap.values()) {
+ viewer.entities.remove(entity)
+ }
+ deviceIconEntityMap.clear()
}
function normalizeShapePoint(point) {
@@ -559,6 +603,70 @@
})
}
+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)
+}
+
+async function renderDeviceRanges(rows) {
+ if (!visible.value) return
+ if (!viewer) initMap()
+ if (!viewer) return
+ deviceRangeRenderToken += 1
+ const renderToken = deviceRangeRenderToken
+ const selectedRows = Array.isArray(rows) ? rows : []
+ const nextIds = new Set(selectedRows.map(row => String(row?.id)))
+ for (const [id, primitive] of deviceRangePrimitiveMap.entries()) {
+ if (!nextIds.has(id)) {
+ viewer.scene.primitives.remove(primitive)
+ 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)
+ })
+ if (!pendingRows.length) return
+ const primitives = await Promise.all(
+ pendingRows.map(async row => {
+ const position = getDeviceLngLat(row)
+ if (!position) return { row, primitive: null, position: null }
+ const rangeMeters = normalizeDeviceRange(row.effectiveRangeKm)
+ const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
+ return { row, primitive, position }
+ })
+ )
+ if (renderToken !== deviceRangeRenderToken) return
+ primitives.forEach(({ row, primitive, position }) => {
+ if (position) {
+ addDeviceIconEntity(row, position)
+ }
+ if (!primitive) return
+ const id = String(row?.id)
+ if (!nextIds.has(id)) return
+ deviceRangePrimitiveMap.set(id, primitive)
+ viewer.scene.primitives.add(primitive)
+ })
+}
+
watch(() => selectedAreaRows.value, renderSelectedAreas)
const deviceAreaIdsKey = computed(() =>
selectedAreaRows.value.map(item => item?.id).filter(Boolean).join(',')
@@ -570,9 +678,19 @@
}
)
watch(
+ () => deviceList.value,
+ val => {
+ renderDeviceRanges(val)
+ }
+)
+watch(
() => visible.value,
val => {
- if (!val) clearAreaDisplay()
+ if (!val) {
+ clearAreaDisplay()
+ clearDeviceRangePrimitives()
+ clearDeviceIconEntities()
+ }
}
)
@@ -619,6 +737,7 @@
selectedAreaRows.value = ensuredRows
if (!ensuredRows.length) return
formData.value.areaCount = ensuredRows.length
+ lastSelectedAreaIds = ensuredRows.map(row => row.id)
}
// 初始化地图实例
--
Gitblit v1.9.3