From fd260aa453dcb181ed113d3cf40d268352b9cbcb Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Fri, 21 Nov 2025 16:56:10 +0800 Subject: [PATCH 1/5] feat(screen): add modal close icons --- .../assets/images/modal/closeIcon.png | Bin 0 -> 508 bytes .../assets/images/modal/大弹窗bottom切图.png | Bin 0 -> 3902 bytes .../assets/images/modal/大弹窗mid切图.png | Bin 0 -> 1695 bytes .../assets/images/modal/大弹窗top切图.png | Bin 0 -> 2912 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/closeIcon.png create mode 100644 packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗bottom切图.png create mode 100644 packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗mid切图.png create mode 100644 packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗top切图.png diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/closeIcon.png b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/closeIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..7523db76fba21d437b34282633f89454ac64ad72 GIT binary patch literal 508 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 Ulv%W8Hh~$CzP7OzO2aAYf0mK6`v3p{ literal 0 HcmV?d00001 diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗mid切图.png b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗mid切图.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4636193a83f56d2524c3db30e6b34f7a3b8143 GIT binary patch literal 1695 zcmYL~dr%Ws6o+@iCM=1eD@0)sF+sttjz|losHAQJ2EiI)K%rVRnQDzP)qtYb2PR-f ztuzP)AC$r}foc_EY<VwSd5O+y9t~8v%7Qex##hn-?_VA zCQatDL)Z`maZ?s1$sx#x`WB-s@ErL|&;miMjFco%#x}UW=hxD}IXsqP-IkMag~C86 zNPL7Nz~H5IFe2h1mQviF8ac72_2{jfrlaSYB6g+67*EeyG`Oqr`l@H=YUGdloI9K& zPDjbc(H7_P>r;GoSi(%c{V@F^FAAUk^Y-wn!Gc5QE8^7!$3u7>H_QTpTmr8N{9|SEmp>gorD8D<6yp<$A2c_?N0*4KX0;B;_DA@EMVCD~F5D*m{v{cm zSv|CQnetuR6ySt9LhTy-GK#E@twSqHBnI1T?Fyt=Fm|d~0K$B6#<<93d{AEKT3-r_ zYOg&M(GIlBn73QLC4~6S>c~^`V}!kjsSMrDwfC7Pa_yaM8P(FO?`eHGS$cZUjx+9% z>ZpO5{`8U#Yy)L(KgDc5NbOfn*jFUJ)*e@{_V{^&9?1{Y>d0vSLaDbZ%*@L|+4sNR zoO0*2@Ffig#mw1c7;opyp=X7X0DxsS>;Nwfq@BmUU1Xgc6#EgKAdzh`Ao^(-OV{6E zE!BUwoMwWc2^sux?DyN!glDXg6Vs>BCm?MrQm1Xz9|I|OrCJi);MLlAyu8yM+dbV) zZhL@@12Y`RL((3i%P*67Q+u+I@6UdUKQP!z&n@#tiw(zob6(JKg9MFjKY(kQuVKpnTz^ny+t@t+D%T`E70QI)Hf5?QoB34pu%yZry!anvwL5HVf z$?yY%`pwO_GEY!qEhASJ?_B@5Lw|M)ie(8DxQkbCHfWLa>D4}izIEPknhVV9@isr0 zF%v{J<%M1Hlny#i$tNOhE$_v<#uGF{3h`b_C%yGq2O;eeWO%G`p{o=Eyh@%Y7C6U7 z+Q<$jG{jzpQik9C?f1!H8)uF86mJ&s>!b0yyiNx<+%03Ocrp<*?e7m4=}_vW8(RBpDYF|P|5;n Jl2NQE{2wgbBC!Af literal 0 HcmV?d00001 diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗top切图.png b/packages/screen/src/views/3DSituationalAwarenessRefactor/assets/images/modal/大弹窗top切图.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ac383ab1837be87b919c9d882b9eb3fe9061bd GIT binary patch literal 2912 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 literal 0 HcmV?d00001 From 5134cf819f57828297a3a98c0e872ad485a7182f Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Fri, 21 Nov 2025 16:57:48 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat(screen):=20=E6=B7=BB=E5=8A=A0=E5=BA=94?= =?UTF-8?q?=E6=80=A5=E9=A2=84=E6=A1=88=E5=86=85=E5=AE=B9=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E5=92=8C=E5=8F=AF=E4=BC=B8=E7=BC=A9=E6=A8=A1=E6=80=81=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 `EmergencyPlanContent.vue`,用于显示包含表单、步骤和资源分配的详细应急响应计划 - 添加 `StretchableModal.vue`,用于实现可定制、可调整大小的模态对话框,使用分段背景图 - 更新 `LeftPanel.vue` 以处理 view-plan 事件,整合计划查看功能 --- .../components/LeftPanel/index.vue | 14 +- .../shared/EmergencyPlanContent.vue | 785 ++++++++++++++++++ .../components/shared/StretchableModal.vue | 308 +++++++ 3 files changed, 1105 insertions(+), 2 deletions(-) create mode 100644 packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue create mode 100644 packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/StretchableModal.vue diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/index.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/index.vue index 205f4a9..f1ee671 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/index.vue +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/LeftPanel/index.vue @@ -18,7 +18,10 @@ - + @@ -107,7 +110,7 @@ const handleCloseVideoModal = () => { } // 定义对外事件 -const emit = defineEmits(['start-dispatch']) +const emit = defineEmits(['start-dispatch', 'view-plan']) /** * 处理力量调度启动事件,向上传递给父组件 @@ -115,6 +118,13 @@ const emit = defineEmits(['start-dispatch']) const handleStartDispatch = (payload) => { emit('start-dispatch', payload) } + +/** + * 处理查看智能应急方案事件,向上传递给父组件 + */ +const handleViewPlan = (plan) => { + emit('view-plan', plan) +} + + diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/StretchableModal.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/StretchableModal.vue new file mode 100644 index 0000000..acf1c44 --- /dev/null +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/StretchableModal.vue @@ -0,0 +1,308 @@ + + + + + From 3445cb31e758f524642a771af43d0891d7eb5c24 Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Fri, 21 Nov 2025 16:58:54 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat(screen):=20=E6=9B=B4=E6=96=B0=E5=8A=9B?= =?UTF-8?q?=E9=87=8F=E9=A2=84=E8=AE=BE=E4=BB=A5=E5=8A=A8=E6=80=81=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E6=9D=A5=E8=87=AA=E7=AB=99=E7=82=B9=E7=9A=84=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重置设备、基础和人员数量为0,然后根据列表中的站点数量更新基础数量。这确保力量预设准确反映当前站点数据。 --- .../composables/useDisasterData.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js index 0e0596d..5c9a03e 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useDisasterData.js @@ -20,9 +20,9 @@ export function useDisasterData() { // 力量预置信息 const forcePreset = ref({ - equipment: 23, - bases: 2, - personnel: 2124, + equipment: 0, + bases: 0, + personnel: 0, searchRadius: 30, // km stations: [ { @@ -150,6 +150,8 @@ export function useDisasterData() { // 更新养护站列表 if (Array.isArray(stations)) { + // 根据养护站列表更新应急基地数 + forcePreset.value.bases = stations.length forcePreset.value.stations = stations.map((station) => ({ id: station.stationId, name: station.stationName?.trim() || '未命名养护站', From d73c5f7ca7766dd4ea5ff981193ea781103194fe Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Fri, 21 Nov 2025 17:00:10 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat(screen):=20=E6=B7=BB=E5=8A=A0=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E5=AE=9E=E4=BD=93=E5=8A=A8=E7=94=BB=E5=92=8C=E5=BA=94?= =?UTF-8?q?=E6=80=A5=E9=A2=84=E6=A1=88=E6=A8=A1=E6=80=81=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加对多个实体(包括设备和其他人员组)动画的支持 - 引入具有一键调度功能的应急预案模态框 - 通过多条红色路径线和起点标记增强路径可视化效果 - 更新相机控制以实现对所有动画实体的最佳观看效果 --- .../composables/useEntityAnimation.js | 208 +++++++++++- .../3DSituationalAwarenessRefactor/index.vue | 300 +++++++++++++++--- 2 files changed, 469 insertions(+), 39 deletions(-) diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useEntityAnimation.js b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useEntityAnimation.js index be38422..1b58500 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useEntityAnimation.js +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/composables/useEntityAnimation.js @@ -1,6 +1,7 @@ import { ref } from 'vue' import * as Cesium from 'cesium' import soldierIcon from '../assets/images/SketchPngfbec927027ff9e49207749ebaafd229429315341fda199251b6dfb1723ff17fb.png' +import deviceIcon from '../assets/images/SketchPng860d54f2a31f5f441fc6a88081224f1e98534bf6d5ca1246e420983bdf690380.png' /** * 实体动画管理 Composable @@ -10,6 +11,9 @@ export function useEntityAnimation() { // 动画实体引用 const animatedEntity = ref(null) + // 多组动画实体引用 + const animatedEntities = ref([]) + // 动画是否正在运行 const isAnimating = ref(false) @@ -31,6 +35,49 @@ export function useEntityAnimation() { { x: -1706343.1007708232, y: 5248165.925888667, z: 3187382.186124808 } ] + // 设备组路径坐标 + const DEVICE_PATH_COORDINATES = [ + { x: -1706935.1617290622, y: 5248501.604252841, z: 3186498.2137252213 }, + { x: -1706870.4952433936, y: 5248490.611178698, z: 3186558.182971472 }, + { x: -1706837.227189178, y: 5248420.334709732, z: 3186690.581380162 }, + { x: -1706838.280444158, y: 5248431.37975438, z: 3186708.4743944216 }, + { x: -1706773.0696515848, y: 5248373.01216906, z: 3186823.943446862 }, + { x: -1706727.805384834, y: 5248323.242719114, z: 3186915.9148211516 }, + { x: -1706710.854065587, y: 5248281.031240471, z: 3186987.549384787 }, + { x: -1706660.1034110512, y: 5248266.553680115, z: 3187047.6342452955 }, + { x: -1706604.7906532797, y: 5248253.292764083, z: 3187082.311741225 }, + { x: -1706556.3289747096, y: 5248217.41920621, z: 3187155.538613598 }, + { x: -1706516.2888762353, y: 5248217.691641104, z: 3187197.012414378 }, + { x: -1706436.9808225571, y: 5248198.704904958, z: 3187267.311000274 }, + { x: -1706345.7538517928, y: 5248165.481249246, z: 3187379.4674185305 } + ] + + // 人员组2路径坐标 + const PERSONNEL_PATH_COORDINATES_2 = [ + { x: -1707020.4106680197, y: 5248239.972166492, z: 3187000.301322692 }, + { x: -1706846.822522451, y: 5248275.0303560095, z: 3186986.011771928 }, + { x: -1706851.3836389545, y: 5248300.681797178, z: 3186942.7035291386 }, + { x: -1706844.580179418, y: 5248304.977808034, z: 3186932.891914393 }, + { x: -1706818.9276717228, y: 5248278.222342581, z: 3186976.253684671 }, + { x: -1706831.3209432173, y: 5248316.447298632, z: 3186957.2249293313 }, + { x: -1706806.3169318594, y: 5248307.832821272, z: 3186919.6375066047 }, + { x: -1706805.9829374112, y: 5248319.428155191, z: 3186900.13906115 }, + { x: -1706795.069820001, y: 5248321.041829423, z: 3186896.925767256 }, + { x: -1706797.8593846853, y: 5248325.909509062, z: 3186906.0008906457 }, + { x: -1706806.3364665583, y: 5248330.644777029, z: 3186917.773814682 }, + { x: -1706778.3135473165, y: 5248282.550132113, z: 3186963.408730601 }, + { x: -1706750.0602398354, y: 5248252.482706784, z: 3187012.7495610164 }, + { x: -1706738.0772460685, y: 5248263.416236532, z: 3187023.8067475185 }, + { x: -1706691.7246759017, y: 5248270.110156667, z: 3187018.588901565 }, + { x: -1706599.6318286993, y: 5248240.149769867, z: 3187087.254778178 }, + { x: -1706564.1779400432, y: 5248218.9292086465, z: 3187146.335302665 }, + { x: -1706486.5598449395, y: 5248207.86588749, z: 3187216.762631293 }, + { x: -1706445.7375556522, y: 5248203.1875622, z: 3187252.8650745875 }, + { x: -1706409.1757614242, y: 5248182.077526832, z: 3187307.1294440767 }, + { x: -1706408.0269636167, y: 5248192.685664652, z: 3187323.2121423096 }, + { x: -1706390.7352810341, y: 5248211.637499602, z: 3187344.1570185754 } + ] + /** * 启动应急人员沿路径移动动画 * @param {Cesium.Viewer} viewer - Cesium viewer 实例 @@ -243,16 +290,175 @@ export function useEntityAnimation() { } } + /** + * 创建单个移动实体 + * @param {Cesium.Viewer} viewer + * @param {Array} pathCoordinates - 路径坐标数组 + * @param {Object} config - 配置 + * @param {Cesium.JulianDate} startTime + * @param {Cesium.JulianDate} stopTime + * @returns {Cesium.Entity} + */ + const createMovingEntity = (viewer, pathCoordinates, config, startTime, stopTime) => { + const positionProperty = new Cesium.SampledPositionProperty() + const numberOfPoints = pathCoordinates.length + const timeInterval = config.duration / (numberOfPoints - 1) + + pathCoordinates.forEach((coord, index) => { + const time = Cesium.JulianDate.addSeconds( + startTime, + index * timeInterval, + new Cesium.JulianDate() + ) + const position = new Cesium.Cartesian3(coord.x, coord.y, coord.z) + positionProperty.addSample(time, position) + }) + + const pulseScale = new Cesium.CallbackProperty((time) => { + const elapsed = Cesium.JulianDate.secondsDifference(time, startTime) + return 1.0 + Math.sin(elapsed * 3) * 0.3 + }, false) + + const icon = config.type === 'device' ? deviceIcon : soldierIcon + const trailColor = config.type === 'device' ? Cesium.Color.ORANGE : Cesium.Color.CYAN + + return viewer.entities.add({ + availability: new Cesium.TimeIntervalCollection([ + new Cesium.TimeInterval({ start: startTime, stop: stopTime }) + ]), + position: positionProperty, + orientation: new Cesium.VelocityOrientationProperty(positionProperty), + billboard: { + image: icon, + width: 48, + height: 56, + scale: pulseScale, + verticalOrigin: Cesium.VerticalOrigin.BOTTOM, + heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + scaleByDistance: new Cesium.NearFarScalar(1000, 1.5, 50000, 0.8) + }, + path: { + resolution: 1, + material: new Cesium.PolylineGlowMaterialProperty({ + glowPower: 0.4, + taperPower: 0.5, + color: trailColor + }), + width: 8, + leadTime: 0, + trailTime: config.duration + }, + properties: { + type: config.type === 'device' ? 'animatedDevice' : 'animatedSoldier', + name: config.name, + department: config.department, + isAnimating: true + } + }) + } + + /** + * 启动多组移动动画(设备组 + 人员组2) + * @param {Cesium.Viewer} viewer + * @param {Object} options + */ + const startMultipleMovements = (viewer, options = {}) => { + if (!viewer) { + console.warn('[useEntityAnimation] startMultipleMovements: viewer 为空') + return [] + } + + const config = { + duration: options.duration ?? 60 + } + + console.log('[useEntityAnimation] 启动多组移动动画...') + + const startTime = Cesium.JulianDate.now() + const stopTime = Cesium.JulianDate.addSeconds(startTime, config.duration, new Cesium.JulianDate()) + + viewer.clock.startTime = startTime.clone() + viewer.clock.stopTime = stopTime.clone() + viewer.clock.currentTime = startTime.clone() + viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP + viewer.clock.multiplier = 1 + viewer.clock.shouldAnimate = true + + // 清除之前的动画实体 + animatedEntities.value.forEach(entity => { + if (entity) viewer.entities.remove(entity) + }) + animatedEntities.value = [] + + // 创建设备组移动实体 + const deviceEntity = createMovingEntity(viewer, DEVICE_PATH_COORDINATES, { + duration: config.duration, + type: 'device', + name: '应急设备车', + department: '应急装备队' + }, startTime, stopTime) + animatedEntities.value.push(deviceEntity) + + // 创建人员组2移动实体 + const personnel2Entity = createMovingEntity(viewer, PERSONNEL_PATH_COORDINATES_2, { + duration: config.duration, + type: 'soldier', + name: '应急救援队员', + department: '应急救援队' + }, startTime, stopTime) + animatedEntities.value.push(personnel2Entity) + + isAnimating.value = true + + const removeListener = viewer.clock.onStop.addEventListener(() => { + console.log('[useEntityAnimation] 多组动画已结束') + isAnimating.value = false + removeListener() + }) + + console.log('[useEntityAnimation] 已启动 2 组额外移动动画') + return animatedEntities.value + } + + /** + * 停止所有移动动画 + * @param {Cesium.Viewer} viewer + */ + const stopAllMovements = (viewer) => { + if (!viewer) return + + viewer.clock.shouldAnimate = false + + if (animatedEntity.value) { + viewer.entities.remove(animatedEntity.value) + animatedEntity.value = null + } + + animatedEntities.value.forEach(entity => { + if (entity) viewer.entities.remove(entity) + }) + animatedEntities.value = [] + + isAnimating.value = false + console.log('[useEntityAnimation] 已停止所有移动动画') + } + return { animatedEntity, + animatedEntities, isAnimating, startPersonnelMovement, + startMultipleMovements, stopPersonnelMovement, + stopAllMovements, pauseAnimation, resumeAnimation, getStartPosition, cartesianToLonLat, - PERSONNEL_PATH_COORDINATES + PERSONNEL_PATH_COORDINATES, + DEVICE_PATH_COORDINATES, + PERSONNEL_PATH_COORDINATES_2 } } diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue index e065d0d..595eb5d 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/index.vue @@ -54,7 +54,10 @@ v-show="!isLeftPanelCollapsed" class="situational-awareness__panel-column situational-awareness__panel-column--left" > - + @@ -164,6 +167,29 @@ :center-data="selectedCenter" @close="showCenterDetail = false" /> + + + + + + + + + @@ -179,6 +205,9 @@ import PersonnelDetail from "./components/Popups/PersonnelDetail.vue"; import EmergencyCenterDetail from "./components/Popups/EmergencyCenterDetail.vue"; import MapTooltip from "./components/shared/MapTooltip.vue"; import SceneLabel from "./components/SceneLabel.vue"; +import StretchableModal from "./components/shared/StretchableModal.vue"; +import ActionButton from "./components/shared/ActionButton.vue"; +import EmergencyPlanContent from "./components/shared/EmergencyPlanContent.vue"; import { useDisasterData } from "./composables/useDisasterData"; import { useDualMapCompare } from "./composables/useDualMapCompare"; import { useMapMarkers } from "./composables/useMapMarkers"; @@ -247,7 +276,7 @@ const { const { tooltipState: mapTooltip, showTooltip, hideTooltip, updateTooltipPosition } = useMapTooltip(); // 实体动画功能 -const { startPersonnelMovement, stopPersonnelMovement, isAnimating } = useEntityAnimation(); +const { startPersonnelMovement, startMultipleMovements, stopPersonnelMovement, isAnimating } = useEntityAnimation(); // 当前显示 tooltip 的实体(用于相机移动时更新位置) const currentTooltipEntity = ref(null); @@ -255,6 +284,16 @@ const currentTooltipEntity = ref(null); // 加载动画状态 const showLoading = ref(false); +// 默认相机配置 +const DEFAULT_CAMERA_VIEW = { + lon: 108.011506, + lat: 30.175827, + height: 5000, + heading: 0, + pitch: -45, + roll: 0, +}; + // 范围圈实体 const rangeCircleEntity = ref(null); @@ -553,16 +592,6 @@ onMounted(() => { console.log("3D态势感知地图已就绪"); - // 默认相机配置 - const DEFAULT_CAMERA_VIEW = { - lon: 108.011506, - lat: 30.175827, - height: 5000, - heading: 0, - pitch: -45, - roll: 0, - }; - // 默认点加上图标标记,使用图片图标,图标路径为 packages\screen\src\views\3DSituationalAwarenessRefactor\assets\images\应急基地.png const defaultPoint = new Cesium.Entity({ position: Cesium.Cartesian3.fromDegrees( @@ -628,6 +657,79 @@ onMounted(() => { console.log(`[index.vue] 已添加 ${simulatedPoints.length} 个模拟点位`); + // 添加三组路径动画的起点标记(用于"一键启动") + // 路径1起点(原有人员) + const path1Start = new Cesium.Cartesian3(-1706079.1327424292, 5247893.165552528, 3187993.9339800295); + const path1StartEntity = viewer.entities.add({ + position: path1Start, + billboard: { + image: soldierIcon, + width: 36, + height: 40, + verticalOrigin: Cesium.VerticalOrigin.BOTTOM, + heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + }, + properties: { + type: 'soldier', + name: '应急救援人员', + department: '应急救援队', + location: '待命中', + estimatedArrival: '待启动', + isPathStartMarker: true, + pathId: 'path1' + } + }); + + // 路径2起点(设备组) + const path2Start = new Cesium.Cartesian3(-1706935.1617290622, 5248501.604252841, 3186498.2137252213); + const path2StartEntity = viewer.entities.add({ + position: path2Start, + billboard: { + image: deviceIcon, + width: 36, + height: 40, + verticalOrigin: Cesium.VerticalOrigin.BOTTOM, + heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + }, + properties: { + type: 'device', + name: '应急设备车', + deviceType: '应急装备', + location: '待命中', + estimatedArrival: '待启动', + isPathStartMarker: true, + pathId: 'path2' + } + }); + + // 路径3起点(人员组2) + const path3Start = new Cesium.Cartesian3(-1707020.4106680197, 5248239.972166492, 3187000.301322692); + const path3StartEntity = viewer.entities.add({ + position: path3Start, + billboard: { + image: soldierIcon, + width: 36, + height: 40, + verticalOrigin: Cesium.VerticalOrigin.BOTTOM, + heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + }, + properties: { + type: 'soldier', + name: '应急救援队员', + department: '应急救援队', + location: '待命中', + estimatedArrival: '待启动', + isPathStartMarker: true, + pathId: 'path3' + } + }); + + console.log('[index.vue] 已添加 3 个路径起点标记'); + + // camera.setView({ // ...DEFAULT_CAMERA_VIEW, // }); @@ -886,6 +988,7 @@ const handleMapToolChange = async ({ tool, active }) => { // 弹窗状态 const showPersonnelDetail = ref(false); const showCenterDetail = ref(false); +const showStretchableModal = ref(false); // 选中的数据 const selectedPersonnel = ref({ @@ -978,7 +1081,7 @@ const handleMapTooltipClose = () => { }; // 路径线实体引用 -const pathLineEntity = ref(null); +const pathLineEntities = ref([]); /** * 绘制红色路径线 @@ -991,13 +1094,13 @@ const drawRedPathLine = (viewer) => { } // 如果已存在路径线,先移除 - if (pathLineEntity.value) { - viewer.entities.remove(pathLineEntity.value); - pathLineEntity.value = null; - } + pathLineEntities.value.forEach(entity => { + if (entity) viewer.entities.remove(entity); + }); + pathLineEntities.value = []; - // 路径坐标点 - const pathCoordinates = [ + // 路径1坐标点(原有人员路径) + const pathCoordinates1 = [ { x: -1706079.1327424292, y: 5247893.165552528, z: 3187993.9339800295 }, { x: -1706116.7863268533, y: 5247923.177994122, z: 3187929.297700776 }, { x: -1706131.4939896727, y: 5247956.7916397555, z: 3187865.1250298577 }, @@ -1011,27 +1114,70 @@ const drawRedPathLine = (viewer) => { { x: -1706343.1007708232, y: 5248165.925888667, z: 3187382.186124808 } ]; - // 将坐标点转换为 Cartesian3 数组 - const positions = pathCoordinates.map(coord => - new Cesium.Cartesian3(coord.x, coord.y, coord.z) - ); + // 路径2坐标点(设备组路径) + const pathCoordinates2 = [ + { x: -1706935.1617290622, y: 5248501.604252841, z: 3186498.2137252213 }, + { x: -1706870.4952433936, y: 5248490.611178698, z: 3186558.182971472 }, + { x: -1706837.227189178, y: 5248420.334709732, z: 3186690.581380162 }, + { x: -1706838.280444158, y: 5248431.37975438, z: 3186708.4743944216 }, + { x: -1706773.0696515848, y: 5248373.01216906, z: 3186823.943446862 }, + { x: -1706727.805384834, y: 5248323.242719114, z: 3186915.9148211516 }, + { x: -1706710.854065587, y: 5248281.031240471, z: 3186987.549384787 }, + { x: -1706660.1034110512, y: 5248266.553680115, z: 3187047.6342452955 }, + { x: -1706604.7906532797, y: 5248253.292764083, z: 3187082.311741225 }, + { x: -1706556.3289747096, y: 5248217.41920621, z: 3187155.538613598 }, + { x: -1706516.2888762353, y: 5248217.691641104, z: 3187197.012414378 }, + { x: -1706436.9808225571, y: 5248198.704904958, z: 3187267.311000274 }, + { x: -1706345.7538517928, y: 5248165.481249246, z: 3187379.4674185305 } + ]; - // 创建红色路径线实体 - pathLineEntity.value = viewer.entities.add({ - polyline: { - positions: positions, - width: 5, - material: Cesium.Color.RED, - clampToGround: true, - // 添加发光效果使路径更醒目 - // material: new Cesium.PolylineGlowMaterialProperty({ - // glowPower: 0.3, - // color: Cesium.Color.RED - // }) - } + // 路径3坐标点(人员组2路径) + const pathCoordinates3 = [ + { x: -1707020.4106680197, y: 5248239.972166492, z: 3187000.301322692 }, + { x: -1706846.822522451, y: 5248275.0303560095, z: 3186986.011771928 }, + { x: -1706851.3836389545, y: 5248300.681797178, z: 3186942.7035291386 }, + { x: -1706844.580179418, y: 5248304.977808034, z: 3186932.891914393 }, + { x: -1706818.9276717228, y: 5248278.222342581, z: 3186976.253684671 }, + { x: -1706831.3209432173, y: 5248316.447298632, z: 3186957.2249293313 }, + { x: -1706806.3169318594, y: 5248307.832821272, z: 3186919.6375066047 }, + { x: -1706805.9829374112, y: 5248319.428155191, z: 3186900.13906115 }, + { x: -1706795.069820001, y: 5248321.041829423, z: 3186896.925767256 }, + { x: -1706797.8593846853, y: 5248325.909509062, z: 3186906.0008906457 }, + { x: -1706806.3364665583, y: 5248330.644777029, z: 3186917.773814682 }, + { x: -1706778.3135473165, y: 5248282.550132113, z: 3186963.408730601 }, + { x: -1706750.0602398354, y: 5248252.482706784, z: 3187012.7495610164 }, + { x: -1706738.0772460685, y: 5248263.416236532, z: 3187023.8067475185 }, + { x: -1706691.7246759017, y: 5248270.110156667, z: 3187018.588901565 }, + { x: -1706599.6318286993, y: 5248240.149769867, z: 3187087.254778178 }, + { x: -1706564.1779400432, y: 5248218.9292086465, z: 3187146.335302665 }, + { x: -1706486.5598449395, y: 5248207.86588749, z: 3187216.762631293 }, + { x: -1706445.7375556522, y: 5248203.1875622, z: 3187252.8650745875 }, + { x: -1706409.1757614242, y: 5248182.077526832, z: 3187307.1294440767 }, + { x: -1706408.0269636167, y: 5248192.685664652, z: 3187323.2121423096 }, + { x: -1706390.7352810341, y: 5248211.637499602, z: 3187344.1570185754 } + ]; + + // 绘制三条路径线 + const allPaths = [pathCoordinates1, pathCoordinates2, pathCoordinates3]; + + allPaths.forEach((pathCoordinates, index) => { + const positions = pathCoordinates.map(coord => + new Cesium.Cartesian3(coord.x, coord.y, coord.z) + ); + + const pathEntity = viewer.entities.add({ + polyline: { + positions: positions, + width: 5, + material: Cesium.Color.RED, + clampToGround: true + } + }); + + pathLineEntities.value.push(pathEntity); }); - console.log('[index.vue] 红色路径线已绘制'); + console.log('[index.vue] 已绘制 3 条红色路径线'); }; /** @@ -1053,8 +1199,20 @@ const handleStartDispatch = (payload) => { setTimeout(() => { showLoading.value = false; - // 启动应急人员沿路径移动动画 if (mapStore.viewer) { + // 移除路径起点标记(因为动画实体会从起点开始显示) + const entitiesToRemove = []; + mapStore.viewer.entities.values.forEach(entity => { + if (entity.properties && entity.properties.isPathStartMarker) { + entitiesToRemove.push(entity); + } + }); + entitiesToRemove.forEach(entity => { + mapStore.viewer.entities.remove(entity); + }); + console.log(`[index.vue] 已移除 ${entitiesToRemove.length} 个路径起点标记`); + + // 启动应急人员沿路径移动动画 console.log('[index.vue] 启动应急人员移动动画...'); startPersonnelMovement(mapStore.viewer, { duration: 60, // 60秒完成整个路径,移动更清晰可见 @@ -1062,12 +1220,78 @@ const handleStartDispatch = (payload) => { personnelName: '应急救援人员', department: '应急救援队' }); + + // 同时启动多组移动动画(设备组 + 人员组2) + startMultipleMovements(mapStore.viewer, { + duration: 60 + }); + + // 缓慢拉近到能看到所有3组移动实体的全景位置 + const { camera } = mapStore.services(); + + console.log('[index.vue] 相机缓慢飞向最佳全景位置...'); + + // 收集所有3组路径的关键点(起点和终点),用于计算最佳视角 + const allPathPoints = [ + // 路径1(原有人员) + new Cesium.Cartesian3(-1706079.1327424292, 5247893.165552528, 3187993.9339800295), // 起点 + new Cesium.Cartesian3(-1706343.1007708232, 5248165.925888667, 3187382.186124808), // 终点 + // 路径2(设备组) + new Cesium.Cartesian3(-1706935.1617290622, 5248501.604252841, 3186498.2137252213), // 起点 + new Cesium.Cartesian3(-1706345.7538517928, 5248165.481249246, 3187379.4674185305), // 终点 + // 路径3(人员组2) + new Cesium.Cartesian3(-1707020.4106680197, 5248239.972166492, 3187000.301322692), // 起点 + new Cesium.Cartesian3(-1706390.7352810341, 5248211.637499602, 3187344.1570185754) // 终点 + ]; + + // 转换为经纬度格式 + const trajectoryPoints = allPathPoints.map(point => { + const cartographic = Cesium.Cartographic.fromCartesian(point); + return { + lon: Cesium.Math.toDegrees(cartographic.longitude), + lat: Cesium.Math.toDegrees(cartographic.latitude) + }; + }); + + // 使用智能聚焦方法飞向能看到所有路径的最佳位置 + camera.fitBoundsWithTrajectory(trajectoryPoints, { + duration: 5, // 5秒缓慢飞行 + padding: 0.2 // 20% 边距,确保所有点都在视野内 + }); } else { console.warn('[index.vue] 地图viewer未就绪,无法启动动画'); } }, 3000); }; +/** + * 处理查看智能应急方案事件 + * 打开智能应急方案弹窗 + */ +const handleViewPlan = (plan) => { + console.log('[index.vue] 查看智能应急方案:', plan); + showStretchableModal.value = true; +}; + +/** + * 处理弹窗中的一键启动按钮点击事件 + * 关闭弹窗并执行一键启动功能 + */ +const handleModalStartDispatch = () => { + console.log('[index.vue] 弹窗中点击一键启动'); + + // 关闭弹窗 + showStretchableModal.value = false; + + // 执行一键启动逻辑(与handleStartDispatch相同) + handleStartDispatch({ + planName: '智能应急方案', + plan: disasterData.forceDispatch.value.plan, + responseLevel: disasterData.forceDispatch.value.responseLevel, + estimatedClearTime: disasterData.forceDispatch.value.estimatedClearTime + }); +}; + /** * 创建或更新范围圈 * @param {Cesium.Viewer} viewer - Cesium viewer 实例 From 677a5fa9accf86d9407060ebbea22b21cc5c7f6c Mon Sep 17 00:00:00 2001 From: Zzc <1373857752@qq.com> Date: Fri, 21 Nov 2025 18:16:29 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat(screen):=20=E6=B7=BB=E5=8A=A0=E5=8F=AF?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E7=9A=84=E8=AE=A1=E5=88=92=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E5=92=8C=E5=9F=BA=E4=BA=8E=E7=AB=99=E7=82=B9=E7=9A=84=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用el-input将静态计划步骤和后续文本转换为可编辑输入框 - 使清场步骤和调度计划具有响应性,支持动态站点分配 - 添加用于添加和删除调度计划的UI元素(当前已禁用) - 为新的交互组件更新样式并改善布局 - 从父组件集成stations属性以实现站点名称的自动分配 --- .../shared/EmergencyPlanContent.vue | 236 ++++++++++++++++-- .../3DSituationalAwarenessRefactor/index.vue | 2 +- 2 files changed, 218 insertions(+), 20 deletions(-) diff --git a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue index 7f9ff39..917003b 100644 --- a/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue +++ b/packages/screen/src/views/3DSituationalAwarenessRefactor/components/shared/EmergencyPlanContent.vue @@ -144,7 +144,12 @@
-
{{ step.content }}
+
@@ -159,7 +164,10 @@ class="title-icon" />

力量调派方案

- +
@@ -168,9 +176,10 @@ :key="plan.id" class="dispatch-card" > +

- {{ plan.name }} + 基地{{ plan.id }}:{{ plan.stationName || 'xxxxx名称' }}

后续处治
- +
@@ -374,6 +475,15 @@ const handleAddPlan = () => { font-family: SourceHanSansCN-Medium, sans-serif; cursor: pointer; transition: all 0.3s ease; + display: flex; + align-items: center; + gap: vw(6); + + .add-icon { + font-size: fs(18); + font-weight: bold; + line-height: 1; + } &:hover { background: var(--primary-light); @@ -591,6 +701,35 @@ const handleAddPlan = () => { background: #052044; border-radius: vw(4); } + + .step-content-input { + flex: 1; + + :deep(.el-textarea__inner) { + background: #052044 !important; + border: 1px solid rgba(28, 161, 255, 0.3) !important; + border-radius: vw(4); + color: var(--text-white); + font-size: fs(13); + font-family: SourceHanSansCN-Regular, sans-serif; + line-height: 1.6; + padding: vh(8) vw(12); + transition: border-color 0.3s ease; + + &:hover { + border-color: var(--primary-color) !important; + } + + &:focus { + border-color: var(--primary-color) !important; + box-shadow: none !important; + } + + &::placeholder { + color: rgba(255, 255, 255, 0.3); + } + } + } } /* 调派预案 */ @@ -605,13 +744,45 @@ const handleAddPlan = () => { border: 1px solid rgba(28, 161, 255, 0.2); border-radius: vw(8); padding: vh(12) vw(14); + position: relative; + + .close-btn { + position: absolute; + top: vh(12); + right: vw(14); + width: vw(24); + height: vw(24); + border-radius: 50%; + border: 1px solid rgba(255, 255, 255, 0.3); + background: transparent; + color: rgba(255, 255, 255, 0.6); + font-size: fs(20); + line-height: 1; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + + &:hover { + background: rgba(255, 77, 79, 0.2); + border-color: #ff4d4f; + color: #ff4d4f; + transform: rotate(90deg); + } + + &:active { + transform: rotate(90deg) scale(0.95); + } + } .plan-name { font-size: fs(15); font-family: SourceHanSansCN-Bold, sans-serif; font-weight: bold; color: var(--text-white); - margin: 0 0 vh(10) 0; + margin: 0 vw(30) vh(10) 0; + .plan-icon { display: inline-block; width: 9px; @@ -660,6 +831,33 @@ const handleAddPlan = () => { background: #052044; border-radius: vw(4); } + +.follow-up-textarea { + :deep(.el-textarea__inner) { + background: #052044 !important; + border: 1px solid rgba(28, 161, 255, 0.3) !important; + border-radius: vw(4); + color: var(--text-white); + font-size: fs(13); + font-family: SourceHanSansCN-Regular, sans-serif; + line-height: 1.8; + padding: vh(10) vw(14); + transition: border-color 0.3s ease; + + &:hover { + border-color: var(--primary-color) !important; + } + + &:focus { + border-color: var(--primary-color) !important; + box-shadow: none !important; + } + + &::placeholder { + color: rgba(255, 255, 255, 0.3); + } + } +}