From a9e2e836e02656e6907d4030bcca8b4838b03c27 Mon Sep 17 00:00:00 2001
From: huangchenhao <123673748@qq.com>
Date: Fri, 28 Nov 2025 05:21:19 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9C=86=E5=9C=88=E4=BC=9A?=
=?UTF-8?q?=E9=87=8D=E5=A4=8D=E6=B7=BB=E5=8A=A0=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../components/LeftPanel/ForcePreset.vue | 5 +-
.../composables/useMapMarkers.js | 2 +
.../composables/useRangeCircle.js | 113 +++++++++---------
.../constants/index.js | 8 +-
.../3DSituationalAwarenessRefactor/index.vue | 4 +-
5 files changed, 70 insertions(+), 62 deletions(-)
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue
index f641f24..88cbb80 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/ForcePreset.vue
@@ -97,7 +97,8 @@
应急人员
- {{ forcePreset.personnel }}
+
+ {{ distance === 30 ? 47 : 69 }}
人
@@ -177,7 +178,9 @@ const closeDropdown = () => {
* 选择选项
* @param {number} value - 选中的距离值
*/
+const distance = ref(30);
const selectOption = (value) => {
+ distance.value = value;
if (onDistanceChange) {
onDistanceChange(value);
}
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js
index b2b90ea..f925685 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useMapMarkers.js
@@ -994,6 +994,8 @@ export function useMapMarkers() {
...reserveCenterEntities.value
].filter(e => e.billboard) // 只需要有billboard的实体
+ console.log('allEntities', allEntities)
+
// 存储原始像素偏移量
const entitiesData = allEntities.map(entity => ({
entity,
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js
index 2875468..85245ee 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useRangeCircle.js
@@ -3,9 +3,9 @@ import { ref } from 'vue'
import { DISASTER_CENTER, RANGE_CIRCLE_STYLE } from '../constants'
export function useRangeCircle() {
- const rangeCircleEntity = ref(null)
- const radiusLineEntity = ref(null) // 单独存储半径线实体
- const labelEntity = ref(null) // 单独存储标签实体
+ const rangeCircleEntities = ref([]) // 改为数组存储所有范围圈实体
+ const radiusLineEntities = ref([]) // 存储所有半径线实体
+ const labelEntities = ref([]) // 存储所有标签实体
const createOrUpdateRangeCircle = (
viewer,
@@ -25,30 +25,24 @@ export function useRangeCircle() {
const radiusMeters = radiusKm * 1000
- // 如果已存在范围圈,先检查半径和中心点是否相同
- if (rangeCircleEntity.value) {
- // 获取现有范围圈的半径(从 semiMajorAxis 获取,单位是米,转换为公里)
- const existingRadiusKm = rangeCircleEntity.value.ellipse.semiMajorAxis / 1000
+ // 检查是否已存在相同半径的范围圈
+ const existingCircleIndex = rangeCircleEntities.value.findIndex(entity => {
+ if (!entity) return false
+ const existingRadiusKm = entity.ellipse.semiMajorAxis / 1000
+ return existingRadiusKm === radiusKm
+ })
- // 检查中心点是否相同
- const existingPosition = rangeCircleEntity.value.position.getValue()
- const newPosition = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 0)
- const centerChanged = !Cesium.Cartesian3.equals(existingPosition, newPosition)
-
- // 如果半径和中心点都相同,则不需要更新
- if (existingRadiusKm === radiusKm && !centerChanged) {
- console.log(`[useRangeCircle] 范围圈半径相同 (${radiusKm}km),无需更新`)
- return
- }
-
- // 移除现有实体
- // clearRangeCircle(viewer)
+ // 如果已存在相同半径的范围圈,则不需要重复创建
+ if (existingCircleIndex !== -1) {
+ showRangeCircle();
+ console.log(`[useRangeCircle] 已存在相同半径的范围圈 (${radiusKm}km),无需重复创建`)
+ return
}
// 创建中心点坐标
const centerCartesian = Cesium.Cartesian3.fromDegrees(centerLon, centerLat)
- // 计算半径线终点(正东方向)- 使用您之前正确的计算方法
+ // 计算半径线终点(正东方向)
const ellipsoid = Cesium.Ellipsoid.WGS84
const surfaceNormal = ellipsoid.geodeticSurfaceNormal(centerCartesian, 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)
const radiusEndCartesian = Cesium.Cartesian3.add(centerCartesian, tangent, new Cesium.Cartesian3())
- // 计算半径线中点
- const midpointCartesian = new Cesium.Cartesian3()
- Cesium.Cartesian3.lerp(centerCartesian, radiusEndCartesian, 0.5, midpointCartesian)
+ // 计算标签位置(3/4处,并向下偏移)
+ const labelPositionCartesian = new Cesium.Cartesian3()
+ 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,
ellipse: {
semiMinorAxis: radiusMeters,
@@ -74,9 +73,10 @@ export function useRangeCircle() {
},
allowPicking: false
})
+ rangeCircleEntities.value.push(circleEntity)
- // 创建半径线实体
- radiusLineEntity.value = viewer.entities.add({
+ // 创建半径线实体并添加到数组
+ const lineEntity = viewer.entities.add({
polyline: {
positions: [centerCartesian, radiusEndCartesian],
width: 2,
@@ -84,10 +84,11 @@ export function useRangeCircle() {
},
allowPicking: false
})
+ radiusLineEntities.value.push(lineEntity)
- // 创建标签实体(单独创建,位置设为半径线中点)
- labelEntity.value = viewer.entities.add({
- position: midpointCartesian,
+ // 创建标签实体并添加到数组
+ const currentLabelEntity = viewer.entities.add({
+ position: labelPositionCartesian,
label: {
text: `${radiusKm - 20} km`,
font: 'bold 16px sans-serif',
@@ -95,55 +96,55 @@ export function useRangeCircle() {
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
- verticalOrigin: Cesium.VerticalOrigin.CENTER,
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 调整垂直原点为底部
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
- pixelOffset: new Cesium.Cartesian2(0, 0),
+ pixelOffset: new Cesium.Cartesian2(0, 10), // 增加像素偏移,确保标签不在半径线上
backgroundColor: Cesium.Color.fromCssColorString('#333').withAlpha(0.7),
backgroundPadding: new Cesium.Cartesian2(8, 6),
showBackground: true,
},
allowPicking: false
})
+ labelEntities.value.push(currentLabelEntity)
- console.log(`[useRangeCircle] 已创建/更新范围圈: ${radiusKm}km`)
+ console.log(`[useRangeCircle] 已创建范围圈: ${radiusKm}km`)
}
+ // 其他函数也需要相应修改为操作数组
const showRangeCircle = () => {
- if (rangeCircleEntity.value) rangeCircleEntity.value.show = true
- if (radiusLineEntity.value) radiusLineEntity.value.show = true
- if (labelEntity.value) labelEntity.value.show = true
+ rangeCircleEntities.value.forEach(entity => entity.show = true)
+ radiusLineEntities.value.forEach(entity => entity.show = true)
+ labelEntities.value.forEach(entity => entity.show = true)
}
const hideRangeCircle = () => {
- if (rangeCircleEntity.value) rangeCircleEntity.value.show = false
- if (radiusLineEntity.value) radiusLineEntity.value.show = false
- if (labelEntity.value) labelEntity.value.show = false
+ rangeCircleEntities.value.forEach(entity => entity.show = false)
+ radiusLineEntities.value.forEach(entity => entity.show = false)
+ labelEntities.value.forEach(entity => entity.show = false)
}
const clearRangeCircle = (viewer) => {
if (!viewer) return
-
- if (rangeCircleEntity.value) {
- viewer.entities.remove(rangeCircleEntity.value)
- rangeCircleEntity.value = null
- }
- 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.forEach(entity => viewer.entities.remove(entity))
+ radiusLineEntities.value.forEach(entity => viewer.entities.remove(entity))
+ labelEntities.value.forEach(entity => viewer.entities.remove(entity))
+
+ // 清空数组
+ rangeCircleEntities.value = []
+ radiusLineEntities.value = []
+ labelEntities.value = []
+
+ console.log('[useRangeCircle] 所有范围圈已清除')
}
return {
- rangeCircleEntity,
+ rangeCircleEntities, // 返回数组
createOrUpdateRangeCircle,
showRangeCircle,
hideRangeCircle,
clearRangeCircle,
}
}
+
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/constants/index.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/constants/index.js
index 8770bcc..373f5fd 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/constants/index.js
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/constants/index.js
@@ -25,7 +25,7 @@ export const VIDEO_MONITORS = [
title: '单兵(张维)设备视角',
videoSrc:
'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,
hasMegaphone: true,
hasZoom: true,
@@ -37,7 +37,7 @@ export const VIDEO_MONITORS = [
title: '无人机(001)视角',
videoSrc:
'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,
hasMegaphone: true,
hasZoom: true,
@@ -49,7 +49,7 @@ export const VIDEO_MONITORS = [
title: '设备操作视角',
videoSrc:
'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,
hasMegaphone: true,
hasZoom: true,
@@ -61,7 +61,7 @@ export const VIDEO_MONITORS = [
title: '指挥会议室视角',
videoSrc:
'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,
hasMegaphone: true,
hasZoom: true,
diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue
index 4117894..f9c976f 100644
--- a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue
+++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue
@@ -564,6 +564,9 @@ const handleVideoModalClose = () => {
const handleStartDispatch = async (payload) => {
console.log("[index.vue] 启动响应调度");
+ await createOrUpdateRangeCircle(mapStore.viewer, 30);
+ await createOrUpdateRangeCircle(mapStore.viewer, 50);
+
// Check if Quick Response has been executed
if (!quickResponseExecuted.value) {
console.log("[index.vue] 快速响应未执行,自动执行...");
@@ -1461,7 +1464,6 @@ const initializeScene = async () => {
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
- priority: 10000, // 这个设置好像并不能让中心点位于所有实体之上 我不知道为什么
});
console.log("[index.vue] 中心点标记已添加");