From 7373f7d2f277caef075a77eab80fef44142d18ae Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Tue, 07 Jul 2026 11:13:38 +0800
Subject: [PATCH] feat:历史轨迹增加日期和地图上显示对应图标

---
 applications/drone-command/src/components/map-container/common-cesium-map.vue |  193 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 191 insertions(+), 2 deletions(-)

diff --git a/applications/drone-command/src/components/map-container/common-cesium-map.vue b/applications/drone-command/src/components/map-container/common-cesium-map.vue
index 33b95c8..9969d7e 100644
--- a/applications/drone-command/src/components/map-container/common-cesium-map.vue
+++ b/applications/drone-command/src/components/map-container/common-cesium-map.vue
@@ -1,5 +1,27 @@
 <template>
-	<div :id="mapId" class="common-cesium-map" @contextmenu.prevent></div>
+	<div :id="mapId" class="common-cesium-map" @contextmenu.prevent>
+		<div class="card">
+			<div class="card-content">
+				<div class="card-item" v-for="(item, index) in props.list" @click="clickWeekTime(item, index)">
+					<!-- <div class="time-top" :class="index === selectedImgIndex ? 'active' : ''">
+						{{ item.createTime }}
+					</div> -->
+					<div class="time-point">
+						<img
+							class="active"
+							v-if="index === selectedImgIndex"
+							src="@/assets/images/common/point-active.png"
+							alt=""
+						/>
+						<img v-else src="@/assets/images/common/point.png" alt="" />
+					</div>
+					<div class="time-bottom">{{ item.createTime.slice(11) }}</div>
+				</div>
+				
+			</div>
+		</div>
+		<div class="time-line"></div>
+	</div>
 </template>
 
 <script setup>
@@ -8,6 +30,7 @@
 import { onBeforeUnmount, onMounted, watch } from 'vue'
 import { PublicCesium } from '@/utils/cesium/publicCesium'
 import { loadJaAdminBoundary, removeJaAdminBoundary } from '@/utils/cesium/adminBoundary'
+import positionIcon from '@/assets/images/dataCenter/positionicon.png'
 
 const props = defineProps({
 	active: {
@@ -58,9 +81,13 @@
 		type: Number,
 		default: 10000,
 	},
+	list: {
+		type: Array,
+		default: () => [],
+	},
 })
 
-const emit = defineEmits(['ready', 'height-change', 'stage-change'])
+const emit = defineEmits(['ready', 'height-change', 'stage-change', 'point-change'])
 const mapId = props.domId || `common-cesium-map-${Math.random().toString(36).slice(2, 10)}`
 let viewInstance = null
 let viewer = null
@@ -108,7 +135,68 @@
 		removeCameraListener = () => viewer?.camera?.changed?.removeEventListener(onCameraChanged)
 	}
 	emit('ready', { viewer, publicCesium: viewInstance })
+	// 地图就绪时,若列表已加载则默认标记选中项(首个)
+	showSelectedMarker()
 }
+
+const selectedImgIndex = ref(0)
+// 航线高度(与 TrajectoryDiaLog 里 MOCK_FLIGHT_HEIGHT 保持一致),让标记悬浮在轨迹线上
+const FLIGHT_HEIGHT = 120
+// 当前经纬度位置标记
+let positionEntity = null
+// 点击周期
+const clickWeekTime = (item, index) => {
+	// clickImgSrc.value = item.url
+	selectedImgIndex.value = index
+	showPositionMarker(item)
+	// 通知父组件当前选中的轨迹点,用于右侧表格同步高亮
+	emit('point-change', { item, index })
+}
+
+// 在地图上通过经纬度显示位置图标
+const showPositionMarker = item => {
+	if (!viewer) return
+	const longitude = Number(item?.longitude)
+	const latitude = Number(item?.latitude)
+	if (Number.isNaN(longitude) || Number.isNaN(latitude)) return
+
+	// 与航线相同的高度,让标记悬浮在轨迹线上,而不是贴地
+	const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, FLIGHT_HEIGHT)
+	if (positionEntity) {
+		// 已存在则移动到新的位置
+		positionEntity.position = position
+	} else {
+		positionEntity = viewer.entities.add({
+			position,
+			billboard: {
+				image: positionIcon,
+				width: 32,
+				height: 40,
+				verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+				disableDepthTestDistance: Number.POSITIVE_INFINITY,
+			},
+		})
+	}
+}
+
+// 显示当前选中项的标记(默认首个),地图就绪和列表加载后都会调用
+const showSelectedMarker = () => {
+	const item = props.list?.[selectedImgIndex.value]
+	if (item) showPositionMarker(item)
+}
+
+// 列表数据到位后,默认选中并标记首个点
+watch(
+	() => props.list,
+	list => {
+		if (list && list.length) {
+			selectedImgIndex.value = 0
+			showSelectedMarker()
+			// 默认选中首个,同步通知父组件高亮表格首行
+			emit('point-change', { item: list[0], index: 0 })
+		}
+	}
+)
 
 watch(
 	() => props.active,
@@ -125,6 +213,7 @@
 	if (removeCameraListener) removeCameraListener()
 	removeJaAdminBoundary(viewer, adminBoundarySources)
 	adminBoundarySources = null
+	positionEntity = null
 	viewInstance?.viewerDestroy?.()
 })
 
@@ -223,5 +312,105 @@
 .common-cesium-map {
 	width: 100%;
 	height: 100%;
+	position: relative;
+	.card {
+		position: absolute;
+		bottom: 0px;
+		width: 100%;
+		height: 67px;
+		background: rgba(0, 0, 0, 0.42);
+		border-radius: 0px 0px 20px 20px;
+		padding-left: 6px;
+		// padding-right: 6px;
+		// border: 1px solid red;
+
+		color: #d5d5d5;
+		font-size: 14px;
+
+		.card-content {
+			display: flex;
+			justify-content: center;
+			position: absolute;
+			
+			width: calc(100% - 6px - 6px);
+			height: 100%;
+			overflow-x: scroll;
+			overflow-y: hidden;
+			white-space: nowrap;
+			.card-item {
+				cursor: pointer;
+			}
+
+			& > div {
+				position: relative;
+			}
+
+			.time-top {
+				margin-top: 10px;
+				line-height: 1;
+				text-align: center;
+				cursor: pointer;
+			}
+
+			.active {
+				font-weight: 400;
+				color: #ffffff;
+			}
+
+			.time-point {
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				position: absolute;
+				top: 22px;
+				left: 50%;
+				width: 18px;
+				height: 18px;
+				z-index: 1;
+				transform: translate(-50%, 0);
+
+				img {
+					width: 11.2px;
+					height: 11.2px;
+				}
+
+				img.active {
+					width: 16.89px;
+					height: 16.89px;
+				}
+			}
+
+			.time-bottom {
+				// border: 1px solid red;
+				margin-top: 44px;
+				margin-left: 8px;
+				&:first-child {
+					margin-left: 0;
+				}
+			}
+
+			// .time-line {
+			// 	// position: absolute;
+			// 	// top: 35px;
+			// 	// width: 100%;
+			// 	position: fixed;
+			// 	bottom: 96px;
+			// 	width: 94%;
+			// 	border: 1px solid rgba(237, 237, 237, 0.6);
+			// 	z-index: 0;
+			// }
+		}
+		
+	}
+	.time-line {
+				position: absolute;
+				// top: 35px;
+				width: 100%;
+				// position: fixed;
+				bottom: 36px;
+				width: 100%;
+				border: 1px solid rgba(237, 237, 237, 0.6);
+				z-index: 0;
+			}
 }
 </style>

--
Gitblit v1.9.3