From 4b37c1cb3ed6bc9659a347c4d6445b23cd6187b5 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Wed, 25 Feb 2026 16:02:50 +0800
Subject: [PATCH] feat:图层管理调整

---
 applications/drone-command/src/components/map-container/device-map-container.vue |  126 ++++++++++++++++++++++++++---------------
 1 files changed, 80 insertions(+), 46 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 0e37663..a16f191 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
@@ -5,33 +5,35 @@
 			:show-admin-boundary="true" :zoom-to-boundary="true" :enable-stage-emit="true"
 			:cluster-height="CLUSTER_HEIGHT" :detail-height="DETAIL_HEIGHT" @ready="handleMapReady"
 			@stage-change="handleStageChange" />
-		<div v-if="props.showLayerControl" class="layer-control-root" :class="{ collapsed: props.leftCollapsed }">
+		<div v-if="props.showLayerControl" class="layer-control-root" :class="{ collapsed: props.rightCollapsed }">
 			<div class="layer-control-wrap" ref="layerWrapRef">
 				<div class="layer-control" @click="toggleLayerPanel">
 					<img :src="layerControlIcon" alt="图层控制" />
 				</div>
-				<div v-if="showLayerPanel" class="layer-panel">
-					<div class="panel-title">底图切换</div>
-					<div class="base-map-options">
-						<div class="base-map-card" :class="{ active: baseLayerKey === 'base-standard' }"
-							@click="handleBaseLayerSelect('base-standard')">
-							<img class="base-map-thumb standard" :src="dzIcon" alt="">
-							<div class="base-map-label">标准地图</div>
+				<transition name="layer-panel-slide">
+					<div v-if="showLayerPanel" class="layer-panel">
+						<div class="panel-title">底图切换</div>
+						<div class="base-map-options">
+							<div class="base-map-card" :class="{ active: baseLayerKey === 'base-standard' }"
+								@click="handleBaseLayerSelect('base-standard')">
+								<img class="base-map-thumb standard" :src="dzIcon" alt="">
+								<div class="base-map-label">标准地图</div>
+							</div>
+							<div class="base-map-card" :class="{ active: baseLayerKey === 'base-satellite' }"
+								@click="handleBaseLayerSelect('base-satellite')">
+								<img class="base-map-thumb satellite" :src="yxIcon" alt="">
+								<div class="base-map-label">卫星地图</div>
+							</div>
 						</div>
-						<div class="base-map-card" :class="{ active: baseLayerKey === 'base-satellite' }"
-							@click="handleBaseLayerSelect('base-satellite')">
-							<img class="base-map-thumb satellite" :src="yxIcon" alt="">
-							<div class="base-map-label">卫星地图</div>
-						</div>
-					</div>
 
-					<div class="panel-title">图层管理</div>
-					<div class="panel-content">
-						<el-tree ref="layerTreeRef" class="command-tree map-layer-tree" :data="layerTree" show-checkbox
-							default-expand-all node-key="key" :props="layerTreeProps"
-							:default-checked-keys="treeCheckedKeys" @check="handleLayerCheck" />
+						<div class="panel-title">图层管理</div>
+						<div class="panel-content">
+							<el-tree ref="layerTreeRef" class="command-tree map-layer-tree" :data="layerTree" show-checkbox
+								default-expand-all node-key="key" :props="layerTreeProps"
+								:default-checked-keys="treeCheckedKeys" @check="handleLayerCheck" />
+						</div>
 					</div>
-				</div>
+				</transition>
 			</div>
 		</div>
 
@@ -77,6 +79,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: {
@@ -87,7 +90,7 @@
 		type: Array,
 		default: () => [],
 	},
-	leftCollapsed: {
+	rightCollapsed: {
 		type: Boolean,
 		default: false,
 	},
@@ -302,10 +305,10 @@
 	if (deviceRingOutlinePrimitives.length) {
 		deviceRingOutlinePrimitives.forEach(primitive => cockpitPrimitiveLayer.add(primitive))
 	}
+	if (commandPostBillboardCollection) cockpitPrimitiveLayer.add(commandPostBillboardCollection)
+	if (deviceBillboardCollection) cockpitPrimitiveLayer.add(deviceBillboardCollection)
 	if (droneTrackPolylineCollection) cockpitPrimitiveLayer.add(droneTrackPolylineCollection)
 	if (droneTrackBillboardCollection) cockpitPrimitiveLayer.add(droneTrackBillboardCollection)
-	if (deviceBillboardCollection) cockpitPrimitiveLayer.add(deviceBillboardCollection)
-	if (commandPostBillboardCollection) cockpitPrimitiveLayer.add(commandPostBillboardCollection)
 }
 
 const clearDeviceEntities = () => {
@@ -465,7 +468,7 @@
 			},
 			{
 				longitude: 114.963974,
-				latitude:  27.132677,
+				latitude: 27.132677,
 				height: 320
 			},
 			{
@@ -512,22 +515,22 @@
 				height: 400
 			},
 			{
-				longitude: 114.925836, 
+				longitude: 114.925836,
 				latitude: 27.096102,
 				height: 400
 			},
 			{
-				longitude: 114.928384, 
+				longitude: 114.928384,
 				latitude: 27.095866,
 				height: 400
 			},
 			{
-				longitude: 114.929874, 
+				longitude: 114.929874,
 				latitude: 27.096095,
 				height: 400
 			},
 			{
-				longitude: 114.931048, 
+				longitude: 114.931048,
 				latitude: 27.097666,
 				height: 400
 			},
@@ -628,11 +631,11 @@
 		const pos = isEntityPosition
 			? getBillboardPosition(track.billboard)
 			: Cesium.Cartesian3.lerp(
-					track.positions[seg],
-					track.positions[seg + 1],
-					ratio,
-					new Cesium.Cartesian3()
-			  )
+				track.positions[seg],
+				track.positions[seg + 1],
+				ratio,
+				new Cesium.Cartesian3()
+			)
 		if (!pos) return
 		if (!isEntityPosition) {
 			track.billboard.position = pos
@@ -718,7 +721,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 +747,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()
@@ -845,6 +850,7 @@
 				width: 40,
 				height: 56,
 				verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+				disableDepthTestDistance: Number.POSITIVE_INFINITY,
 			})
 			billboard.id = entry.entityId
 			devicePickMap.set(entry.entityId, { data: entry.data, billboard })
@@ -973,7 +979,7 @@
 	if (!trimmed) return null
 	try {
 		return JSON.parse(trimmed)
-	} catch (error) {}
+	} catch (error) { }
 	return null
 }
 
@@ -1026,7 +1032,7 @@
 						.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]
+						const style = BUFFER_LEVEL_STYLES[levelIndex] || BUFFER_LEVEL_STYLES[BUFFER_LEVEL_STYLES.length - 1]
 						if (positions.length >= 3) {
 							shapes.push({
 								positions,
@@ -1234,6 +1240,7 @@
 				width: 40,
 				height: 56,
 				verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+				disableDepthTestDistance: Number.POSITIVE_INFINITY,
 			})
 		})
 	}
@@ -1285,7 +1292,7 @@
 )
 
 watch(
-	() => props.leftCollapsed,
+	() => props.rightCollapsed,
 	isCollapsed => {
 		if (isCollapsed) showLayerPanel.value = false
 	}
@@ -1326,7 +1333,7 @@
 	setDroneVisibility(!showCluster)
 }
 
-const handleMapReady = ({ viewer: mapViewer, publicCesium: mapPublic }) => {
+const  handleMapReady = async ({ viewer: mapViewer, publicCesium: mapPublic }) => {
 	if (mapReadyHandled) return
 	mapReadyHandled = true
 	viewer = mapViewer
@@ -1336,10 +1343,10 @@
 	const height = viewer?.camera?.positionCartographic?.height
 	const stage = getStageByHeight(height)
 	updateStageDisplay(stage)
+	await loadCommandPosts()
 	renderDeviceEntities(props.allDevices)
 	loadPartitions()
 	loadAggregation()
-	loadCommandPosts()
 	renderSimulatedDroneTrack(props.alarmDrones)
 	initDeviceClickHandler()
 }
@@ -1377,6 +1384,20 @@
 	viewer = null
 	publicCesium = null
 })
+
+const getMap = () => {
+	return mapRef.value?.getMap()
+}
+
+// 暴露给父组件调用
+const flyTo = (options) => {
+	mapRef.value?.flyToPoint(options)
+}
+
+defineExpose({
+	getMap,
+	flyTo
+})
 </script>
 
 <style lang="scss" scoped>
@@ -1396,14 +1417,14 @@
 
 .layer-control-root {
 	position: absolute;
-	left: 337px;
-	bottom: 22px;
-	z-index: 9;
+	right: 337px;
+	top: 95px;
+	z-index: 11;
 	transition: transform 0.3s ease-in-out;
 	pointer-events: none;
 
 	&.collapsed {
-		transform: translateX(-317px);
+		transform: translateX(317px);
 	}
 }
 
@@ -1430,12 +1451,13 @@
 	display: flex;
 	flex-direction: column;
 	position: absolute;
-	left: 66px;
-	bottom: 0;
+	right: 66px;
+	top: 0;
 	width: 160px;
 	max-height: 442px;
 	background: #191932;
 	border-radius: 8px 8px 8px 8px;
+	z-index: 99;
 
 	.panel-title {
 		padding: 0 16px;
@@ -1504,4 +1526,16 @@
 		}
 	}
 }
+
+.layer-panel-slide-enter-active,
+.layer-panel-slide-leave-active {
+	transition: transform 0.24s ease, opacity 0.24s ease;
+	transform-origin: right center;
+}
+
+.layer-panel-slide-enter-from,
+.layer-panel-slide-leave-to {
+	transform: translateX(24px);
+	opacity: 0;
+}
 </style>

--
Gitblit v1.9.3