From 40780bc04d8747f0918ee7e2a551776e69c44232 Mon Sep 17 00:00:00 2001
From: shuishen <1109946754@qq.com>
Date: Wed, 25 Feb 2026 17:08:08 +0800
Subject: [PATCH] feat:图层控制面板调整

---
 applications/drone-command/src/components/map-container/device-map-container.vue |  219 +++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 156 insertions(+), 63 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 a16f191..59adb40 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
@@ -7,30 +7,41 @@
 			@stage-change="handleStageChange" />
 		<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">
+				<div class="layer-control" @click.stop="toggleLayerPanel">
 					<img :src="layerControlIcon" alt="图层控制" />
 				</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="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"
+							<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>
+				</transition>
+			</div>
+		</div>
+		<div v-if="props.showLayerControl" class="base-layer-switch-root" :class="{ collapsed: props.rightCollapsed }">
+			<div class="base-layer-switch-wrap" @mouseenter="showBaseLayerPanel = true"
+				@mouseleave="showBaseLayerPanel = false">
+				<div class="base-layer-trigger">
+					<img class="base-layer-trigger-thumb" :src="currentBaseLayer.icon" :alt="currentBaseLayer.label">
+					<div class="base-layer-trigger-label">{{ currentBaseLayer.shortLabel }}</div>
+				</div>
+				<transition name="layer-panel-slide">
+					<div v-if="showBaseLayerPanel" class="base-layer-panel">
+						<div class="base-map-options">
+							<div class="base-map-card" :class="{ active: baseLayerKey === 'base-satellite' }"
+								@click="handleBaseLayerSelect('base-satellite')">
+								<img class="base-map-thumb" :src="yxIcon" alt="">
+								<div class="base-map-label">卫星地图</div>
+							</div>
+							<div class="base-map-card" :class="{ active: baseLayerKey === 'base-standard' }"
+								@click="handleBaseLayerSelect('base-standard')">
+								<img class="base-map-thumb" :src="dzIcon" alt="">
+								<div class="base-map-label">标准地图</div>
+							</div>
 						</div>
 					</div>
 				</transition>
@@ -141,6 +152,7 @@
 const clusterVisible = ref(false)
 const countyCenterMap = new Map()
 const showLayerPanel = ref(false)
+const showBaseLayerPanel = ref(false)
 const layerWrapRef = ref(null)
 const layerTreeRef = ref(null)
 const selectedDevice = ref(null)
@@ -155,6 +167,11 @@
 const baseLayerKeys = ['base-standard', 'base-satellite']
 const defaultCheckedKeys = ['ja-terrain', 'admin', 'city-base']
 const baseLayerKey = ref('base-satellite')
+const baseLayerMeta = {
+	'base-standard': { icon: dzIcon, label: '标准地图', shortLabel: '标准' },
+	'base-satellite': { icon: yxIcon, label: '卫星地图', shortLabel: '影像' },
+}
+const currentBaseLayer = computed(() => baseLayerMeta[baseLayerKey.value] || baseLayerMeta['base-satellite'])
 const treeCheckedKeys = ref([...defaultCheckedKeys])
 const layerTree = ref([
 	{
@@ -1294,7 +1311,9 @@
 watch(
 	() => props.rightCollapsed,
 	isCollapsed => {
-		if (isCollapsed) showLayerPanel.value = false
+		if (!isCollapsed) return
+		showLayerPanel.value = false
+		showBaseLayerPanel.value = false
 	}
 )
 
@@ -1333,7 +1352,7 @@
 	setDroneVisibility(!showCluster)
 }
 
-const  handleMapReady = async ({ viewer: mapViewer, publicCesium: mapPublic }) => {
+const handleMapReady = async ({ viewer: mapViewer, publicCesium: mapPublic }) => {
 	if (mapReadyHandled) return
 	mapReadyHandled = true
 	viewer = mapViewer
@@ -1355,7 +1374,7 @@
 	updateStageDisplay(stage)
 }
 
-const handleClickOutside = event => {
+const handleLayerClickOutside = event => {
 	if (!showLayerPanel.value) return
 	const target = event.target
 	if (layerWrapRef.value?.contains(target)) return
@@ -1363,13 +1382,13 @@
 }
 
 onMounted(() => {
-	document.addEventListener('click', handleClickOutside)
+	document.addEventListener('click', handleLayerClickOutside)
 	const map = mapRef.value?.getMap()
 	if (map?.viewer) handleMapReady(map)
 })
 
 onBeforeUnmount(() => {
-	document.removeEventListener('click', handleClickOutside)
+	document.removeEventListener('click', handleLayerClickOutside)
 	clearDeviceEntities()
 	clearPartitionEntities()
 	clearAggregationEntities()
@@ -1480,51 +1499,125 @@
 		overflow: auto;
 	}
 
-	.base-map-title {
-		margin-bottom: 8px;
-		font-size: 12px;
-		color: #ffffff;
-		font-weight: 600;
-	}
+}
 
-	.base-map-options {
-		padding: 16px;
-		display: grid;
-		grid-template-columns: repeat(2, minmax(0, 1fr));
-		gap: 8px;
-	}
+.base-layer-switch-root {
+	position: absolute;
+	right: 337px;
+	bottom: 78px;
+	z-index: 11;
+	transition: transform 0.3s ease-in-out;
+	pointer-events: none;
 
-	.base-map-card {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-		gap: 6px;
+	&.collapsed {
+		transform: translateX(317px);
+	}
+}
+
+.base-layer-switch-wrap {
+	position: relative;
+	pointer-events: auto;
+}
+
+.base-layer-trigger {
+	width: 55px;
+	padding: 8px 0;
+	border-radius: 8px;
+	background: #191932;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	gap: 6px;
+	cursor: pointer;
+}
+
+.base-layer-trigger-thumb {
+	width: 36px;
+	height: 36px;
+	border-radius: 6px;
+	display: block;
+	// border: 2px solid #fff;
+	background-size: cover;
+	background-position: center;
+	box-sizing: border-box;
+}
+
+.base-layer-trigger-label {
+	margin-top: 8px;
+	font-size: 12px;
+	line-height: 1;
+	color: #ffffff;
+	font-weight: 700;
+}
+
+.base-layer-panel {
+	position: absolute;
+	right: calc(100% + 10px);
+	bottom: 0;
+	margin-bottom: 0;
+	width: 160px;
+	background: #191932;
+	border-radius: 8px;
+	z-index: 99;
+
+	&::after {
+		content: '';
+		position: absolute;
+		right: -10px;
+		top: 0;
+		width: 10px;
+		height: 100%;
+		background: transparent;
+	}
+}
+
+.base-map-options {
+	padding: 8px;
+	display: grid;
+	grid-template-columns: repeat(2, minmax(0, 1fr));
+	gap: 8px;
+}
+
+.base-map-card {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	gap: 6px;
+	border-radius: 6px;
+	color: #d8e6ff;
+	font-size: 12px;
+	cursor: pointer;
+	transition: all 0.2s ease;
+
+	.base-map-thumb {
+		width: 36px;
+		height: 36px;
 		border-radius: 6px;
-		color: #d8e6ff;
-		font-size: 12px;
-		cursor: pointer;
-		transition: all 0.2s ease;
-
-		.base-map-thumb {
-			width: 46px;
-			height: 46px;
-			border-radius: 4px;
-			background-size: cover;
-			background-position: center;
-			box-sizing: border-box;
-		}
-
-		&.active {
-			.base-map-thumb {
-				border: 2px solid #2ea8ff;
-			}
-
-			.base-map-label {
-				color: #2ea8ff;
-			}
-		}
+		// border: 2px solid #fff;
+		background-size: cover;
+		background-position: center;
+		box-sizing: border-box;
 	}
+
+	.base-map-label {
+		margin-top: 8px;
+		font-size: 12px;
+		line-height: 1;
+		color: #ffffff;
+		font-weight: 700;
+	}
+
+
+	// &.active {
+	// 	.base-map-thumb {
+	// 		border: 2px solid #2ea8ff;
+	// 	}
+
+	// 	.base-map-label {
+	// 		color: #2ea8ff;
+	// 	}
+	// }
 }
 
 .layer-panel-slide-enter-active,

--
Gitblit v1.9.3