修复圆圈会重复添加的bug

This commit is contained in:
huangchenhao 2025-11-28 05:21:19 +08:00
parent 18913c6ae8
commit a9e2e836e0
5 changed files with 70 additions and 62 deletions

View File

@ -97,7 +97,8 @@
<div class="stat-card stat-card--personnel"> <div class="stat-card stat-card--personnel">
<span class="stat-label">应急人员</span> <span class="stat-label">应急人员</span>
<div class="stat-value-wrapper"> <div class="stat-value-wrapper">
<span class="stat-value">{{ forcePreset.personnel }}</span> <!-- <span class="stat-value">{{ forcePreset.personnel }}</span> -->
<span class="stat-value">{{ distance === 30 ? 47 : 69 }}</span>
<span class="stat-unit"></span> <span class="stat-unit"></span>
</div> </div>
</div> </div>
@ -177,7 +178,9 @@ const closeDropdown = () => {
* 选择选项 * 选择选项
* @param {number} value - 选中的距离值 * @param {number} value - 选中的距离值
*/ */
const distance = ref(30);
const selectOption = (value) => { const selectOption = (value) => {
distance.value = value;
if (onDistanceChange) { if (onDistanceChange) {
onDistanceChange(value); onDistanceChange(value);
} }

View File

@ -994,6 +994,8 @@ export function useMapMarkers() {
...reserveCenterEntities.value ...reserveCenterEntities.value
].filter(e => e.billboard) // 只需要有billboard的实体 ].filter(e => e.billboard) // 只需要有billboard的实体
console.log('allEntities', allEntities)
// 存储原始像素偏移量 // 存储原始像素偏移量
const entitiesData = allEntities.map(entity => ({ const entitiesData = allEntities.map(entity => ({
entity, entity,

View File

@ -3,9 +3,9 @@ import { ref } from 'vue'
import { DISASTER_CENTER, RANGE_CIRCLE_STYLE } from '../constants' import { DISASTER_CENTER, RANGE_CIRCLE_STYLE } from '../constants'
export function useRangeCircle() { export function useRangeCircle() {
const rangeCircleEntity = ref(null) const rangeCircleEntities = ref([]) // 改为数组存储所有范围圈实体
const radiusLineEntity = ref(null) // 单独存储半径线实体 const radiusLineEntities = ref([]) // 存储所有半径线实体
const labelEntity = ref(null) // 单独存储标签实体 const labelEntities = ref([]) // 存储所有标签实体
const createOrUpdateRangeCircle = ( const createOrUpdateRangeCircle = (
viewer, viewer,
@ -25,30 +25,24 @@ export function useRangeCircle() {
const radiusMeters = radiusKm * 1000 const radiusMeters = radiusKm * 1000
// 如果已存在范围圈,先检查半径和中心点是否相同 // 检查是否已存在相同半径的范围圈
if (rangeCircleEntity.value) { const existingCircleIndex = rangeCircleEntities.value.findIndex(entity => {
// 获取现有范围圈的半径(从 semiMajorAxis 获取,单位是米,转换为公里) if (!entity) return false
const existingRadiusKm = rangeCircleEntity.value.ellipse.semiMajorAxis / 1000 const existingRadiusKm = entity.ellipse.semiMajorAxis / 1000
return existingRadiusKm === radiusKm
})
// 检查中心点是否相同 // 如果已存在相同半径的范围圈,则不需要重复创建
const existingPosition = rangeCircleEntity.value.position.getValue() if (existingCircleIndex !== -1) {
const newPosition = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 0) showRangeCircle();
const centerChanged = !Cesium.Cartesian3.equals(existingPosition, newPosition) console.log(`[useRangeCircle] 已存在相同半径的范围圈 (${radiusKm}km),无需重复创建`)
// 如果半径和中心点都相同,则不需要更新
if (existingRadiusKm === radiusKm && !centerChanged) {
console.log(`[useRangeCircle] 范围圈半径相同 (${radiusKm}km),无需更新`)
return return
} }
// 移除现有实体
// clearRangeCircle(viewer)
}
// 创建中心点坐标 // 创建中心点坐标
const centerCartesian = Cesium.Cartesian3.fromDegrees(centerLon, centerLat) const centerCartesian = Cesium.Cartesian3.fromDegrees(centerLon, centerLat)
// 计算半径线终点(正东方向)- 使用您之前正确的计算方法 // 计算半径线终点(正东方向)
const ellipsoid = Cesium.Ellipsoid.WGS84 const ellipsoid = Cesium.Ellipsoid.WGS84
const surfaceNormal = ellipsoid.geodeticSurfaceNormal(centerCartesian, new Cesium.Cartesian3()) const surfaceNormal = ellipsoid.geodeticSurfaceNormal(centerCartesian, new Cesium.Cartesian3())
const tangent = Cesium.Cartesian3.cross(surfaceNormal, Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3()) const tangent = Cesium.Cartesian3.cross(surfaceNormal, Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3())
@ -56,12 +50,17 @@ export function useRangeCircle() {
Cesium.Cartesian3.multiplyByScalar(tangent, radiusMeters, tangent) Cesium.Cartesian3.multiplyByScalar(tangent, radiusMeters, tangent)
const radiusEndCartesian = Cesium.Cartesian3.add(centerCartesian, tangent, new Cesium.Cartesian3()) const radiusEndCartesian = Cesium.Cartesian3.add(centerCartesian, tangent, new Cesium.Cartesian3())
// 计算半径线中点 // 计算标签位置3/4处并向下偏移
const midpointCartesian = new Cesium.Cartesian3() const labelPositionCartesian = new Cesium.Cartesian3()
Cesium.Cartesian3.lerp(centerCartesian, radiusEndCartesian, 0.5, midpointCartesian) Cesium.Cartesian3.lerp(centerCartesian, radiusEndCartesian, 0.75, labelPositionCartesian)
// 计算向下偏移的方向(垂直于半径线方向)
const offsetDirection = Cesium.Cartesian3.cross(Cesium.Cartesian3.UNIT_Z, tangent, new Cesium.Cartesian3())
Cesium.Cartesian3.normalize(offsetDirection, offsetDirection)
Cesium.Cartesian3.multiplyByScalar(offsetDirection, - radiusMeters * 0.2, offsetDirection) // 向下偏移 20%
Cesium.Cartesian3.add(labelPositionCartesian, offsetDirection, labelPositionCartesian)
// 创建范围圈实体 // 创建范围圈实体并添加到数组
rangeCircleEntity.value = viewer.entities.add({ const circleEntity = viewer.entities.add({
position: centerCartesian, position: centerCartesian,
ellipse: { ellipse: {
semiMinorAxis: radiusMeters, semiMinorAxis: radiusMeters,
@ -74,9 +73,10 @@ export function useRangeCircle() {
}, },
allowPicking: false allowPicking: false
}) })
rangeCircleEntities.value.push(circleEntity)
// 创建半径线实体 // 创建半径线实体并添加到数组
radiusLineEntity.value = viewer.entities.add({ const lineEntity = viewer.entities.add({
polyline: { polyline: {
positions: [centerCartesian, radiusEndCartesian], positions: [centerCartesian, radiusEndCartesian],
width: 2, width: 2,
@ -84,10 +84,11 @@ export function useRangeCircle() {
}, },
allowPicking: false allowPicking: false
}) })
radiusLineEntities.value.push(lineEntity)
// 创建标签实体(单独创建,位置设为半径线中点) // 创建标签实体并添加到数组
labelEntity.value = viewer.entities.add({ const currentLabelEntity = viewer.entities.add({
position: midpointCartesian, position: labelPositionCartesian,
label: { label: {
text: `${radiusKm - 20} km`, text: `${radiusKm - 20} km`,
font: 'bold 16px sans-serif', font: 'bold 16px sans-serif',
@ -95,55 +96,55 @@ export function useRangeCircle() {
outlineColor: Cesium.Color.BLACK, outlineColor: Cesium.Color.BLACK,
outlineWidth: 2, outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE, style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 调整垂直原点为底部
horizontalOrigin: Cesium.HorizontalOrigin.CENTER, horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
pixelOffset: new Cesium.Cartesian2(0, 0), pixelOffset: new Cesium.Cartesian2(0, 10), // 增加像素偏移,确保标签不在半径线上
backgroundColor: Cesium.Color.fromCssColorString('#333').withAlpha(0.7), backgroundColor: Cesium.Color.fromCssColorString('#333').withAlpha(0.7),
backgroundPadding: new Cesium.Cartesian2(8, 6), backgroundPadding: new Cesium.Cartesian2(8, 6),
showBackground: true, showBackground: true,
}, },
allowPicking: false allowPicking: false
}) })
labelEntities.value.push(currentLabelEntity)
console.log(`[useRangeCircle] 已创建/更新范围圈: ${radiusKm}km`) console.log(`[useRangeCircle] 已创建范围圈: ${radiusKm}km`)
} }
// 其他函数也需要相应修改为操作数组
const showRangeCircle = () => { const showRangeCircle = () => {
if (rangeCircleEntity.value) rangeCircleEntity.value.show = true rangeCircleEntities.value.forEach(entity => entity.show = true)
if (radiusLineEntity.value) radiusLineEntity.value.show = true radiusLineEntities.value.forEach(entity => entity.show = true)
if (labelEntity.value) labelEntity.value.show = true labelEntities.value.forEach(entity => entity.show = true)
} }
const hideRangeCircle = () => { const hideRangeCircle = () => {
if (rangeCircleEntity.value) rangeCircleEntity.value.show = false rangeCircleEntities.value.forEach(entity => entity.show = false)
if (radiusLineEntity.value) radiusLineEntity.value.show = false radiusLineEntities.value.forEach(entity => entity.show = false)
if (labelEntity.value) labelEntity.value.show = false labelEntities.value.forEach(entity => entity.show = false)
} }
const clearRangeCircle = (viewer) => { const clearRangeCircle = (viewer) => {
if (!viewer) return if (!viewer) return
if (rangeCircleEntity.value) { // 清除所有实体
viewer.entities.remove(rangeCircleEntity.value) rangeCircleEntities.value.forEach(entity => viewer.entities.remove(entity))
rangeCircleEntity.value = null radiusLineEntities.value.forEach(entity => viewer.entities.remove(entity))
} labelEntities.value.forEach(entity => viewer.entities.remove(entity))
if (radiusLineEntity.value) {
viewer.entities.remove(radiusLineEntity.value)
radiusLineEntity.value = null
}
if (labelEntity.value) {
viewer.entities.remove(labelEntity.value)
labelEntity.value = null
}
console.log('[useRangeCircle] 范围圈已清除') // 清空数组
rangeCircleEntities.value = []
radiusLineEntities.value = []
labelEntities.value = []
console.log('[useRangeCircle] 所有范围圈已清除')
} }
return { return {
rangeCircleEntity, rangeCircleEntities, // 返回数组
createOrUpdateRangeCircle, createOrUpdateRangeCircle,
showRangeCircle, showRangeCircle,
hideRangeCircle, hideRangeCircle,
clearRangeCircle, clearRangeCircle,
} }
} }

View File

@ -25,7 +25,7 @@ export const VIDEO_MONITORS = [
title: '单兵(张维)设备视角', title: '单兵(张维)设备视角',
videoSrc: videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4', 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/单兵视角.mp4',
dateRange: '2025/9/1-2025/12/1', // dateRange: '2025/9/1-2025/12/1',
hasAudio: true, hasAudio: true,
hasMegaphone: true, hasMegaphone: true,
hasZoom: true, hasZoom: true,
@ -37,7 +37,7 @@ export const VIDEO_MONITORS = [
title: '无人机(001)视角', title: '无人机(001)视角',
videoSrc: videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/无人机视角.mp4', 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/无人机视角.mp4',
dateRange: '2025/9/1-2025/12/1', // dateRange: '2025/9/1-2025/12/1',
hasAudio: false, hasAudio: false,
hasMegaphone: true, hasMegaphone: true,
hasZoom: true, hasZoom: true,
@ -49,7 +49,7 @@ export const VIDEO_MONITORS = [
title: '设备操作视角', title: '设备操作视角',
videoSrc: videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/设备视角.mp4', 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/设备视角.mp4',
dateRange: '2025/9/1-2025/12/1', // dateRange: '2025/9/1-2025/12/1',
hasAudio: true, hasAudio: true,
hasMegaphone: true, hasMegaphone: true,
hasZoom: true, hasZoom: true,
@ -61,7 +61,7 @@ export const VIDEO_MONITORS = [
title: '指挥会议室视角', title: '指挥会议室视角',
videoSrc: videoSrc:
'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/指挥会议室视角.mp4', 'http://222.212.85.86:9000/300bdf2b-a150-406e-be63-d28bd29b409f/demo/ylzg/指挥会议室视角.mp4',
dateRange: '2025/9/1-2025/12/1', // dateRange: '2025/9/1-2025/12/1',
hasAudio: true, hasAudio: true,
hasMegaphone: true, hasMegaphone: true,
hasZoom: true, hasZoom: true,

View File

@ -564,6 +564,9 @@ const handleVideoModalClose = () => {
const handleStartDispatch = async (payload) => { const handleStartDispatch = async (payload) => {
console.log("[index.vue] 启动响应调度"); console.log("[index.vue] 启动响应调度");
await createOrUpdateRangeCircle(mapStore.viewer, 30);
await createOrUpdateRangeCircle(mapStore.viewer, 50);
// Check if Quick Response has been executed // Check if Quick Response has been executed
if (!quickResponseExecuted.value) { if (!quickResponseExecuted.value) {
console.log("[index.vue] 快速响应未执行,自动执行..."); console.log("[index.vue] 快速响应未执行,自动执行...");
@ -1461,7 +1464,6 @@ const initializeScene = async () => {
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY, disableDepthTestDistance: Number.POSITIVE_INFINITY,
}, },
priority: 10000, //
}); });
console.log("[index.vue] 中心点标记已添加"); console.log("[index.vue] 中心点标记已添加");