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