吉安感知网项目-前端
chenyao
2026-07-07 7373f7d2f277caef075a77eab80fef44142d18ae
feat:历史轨迹增加日期和地图上显示对应图标
2 files modified
233 ■■■■■ changed files
applications/drone-command/src/components/map-container/common-cesium-map.vue 193 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue 40 ●●●●● patch | view | raw | blame | history
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>
applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
@@ -17,6 +17,8 @@
                    :terrain="true"
                    :layer-mode="4"
                    :boundary="false"
                    :list="list"
                    @point-change="handlePointChange"
                />
            </div>
            <div class="right-container">
@@ -53,7 +55,7 @@
                    <div class="detail-title">轨迹点</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-table" :data="list" :row-class-name="getRowClassName">
                            <el-table ref="pointTableRef" class="command-table" :data="list" :row-class-name="getRowClassName">
                                <el-table-column type="index" width="60" label="序号" />
                                <el-table-column label="经纬度">
                                    <template #default="{ row }">{{ row.longitude }},{{ row.latitude }}</template>
@@ -165,16 +167,36 @@
function handleClosed() {
    formData.value = initForm()
    list.value = []
    selectedPointIndex.value = 0
    viewer = null
    geometricSource = null
    droneLineEntity = null
    startDroneEntity = null
}
function getRowClassName({ row }) {
    console.log(row.isAlarm, 11111111111)
// 当前选中的轨迹点索引(与地图时间轴联动)
const selectedPointIndex = ref(0)
const pointTableRef = ref(null)
    return row?.isAlarm === 1 ? 'alarm-row' : ''
// 地图上点击轨迹点后,同步高亮表格对应行,并滚动到该行
function handlePointChange({ index } = {}) {
    if (typeof index !== 'number') return
    selectedPointIndex.value = index
    scrollToSelectedRow()
}
// 表格行较多时自动滚动到选中行
async function scrollToSelectedRow() {
    await nextTick()
    const rowEl = pointTableRef.value?.$el?.querySelector('.selected-row')
    rowEl?.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
}
function getRowClassName({ row, rowIndex }) {
    const classNames = []
    if (row?.isAlarm === 1) classNames.push('alarm-row')
    if (rowIndex === selectedPointIndex.value) classNames.push('selected-row')
    return classNames.join(' ')
}
let viewer, geometricSource, droneLineEntity, startDroneEntity
@@ -212,4 +234,14 @@
        background-color: transparent !important;
    }
}
// 与地图时间轴联动的选中行高亮
:deep(.selected-row) {
    background: #14335f !important;
    td {
        background-color: transparent !important;
        color: #4faaff !important;
    }
}
</style>