From bc584dc90042e1afbec04e47aae756415c6bfaa1 Mon Sep 17 00:00:00 2001 From: wzy-warehouse <18135009705@163.com> Date: Sun, 14 Jun 2026 15:08:15 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E6=9A=B4=E9=9B=A8=E7=81=BE=E5=AE=B3?= =?UTF-8?q?=E9=93=BE=E6=A8=A1=E5=9E=8B=E6=8E=A8=E6=BC=94=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/api.ts | 15 +++++++++++++++ src/api/rainfall.ts | 16 ++++++++++++++++ src/component/map/AdministrativeDivision.vue | 4 +++- .../detail-panels/RainfallGridComponent.vue | 17 +++++++++++++++++ src/types/rainstorm/RainPredictResponse.ts | 6 ++++++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/api/rainfall.ts create mode 100644 src/types/rainstorm/RainPredictResponse.ts diff --git a/src/api/api.ts b/src/api/api.ts index ddeca55..da6d729 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -55,6 +55,8 @@ import type { XianSchool } from '@/types/base/XianSchool'; import type { XianBridge } from '@/types/base/XianBridge.ts'; import type { XianReservoirList } from '@/types/base/XianReservoirList'; import type { XianSubwayStations } from '@/types/base/XianSubwayStations'; +import { modelDeduction as rainfallModelDeduction } from './rainfall'; +import type { RainPredictResponse } from '@/types/rainstorm/RainPredictResponse'; /** * API接口统一导出对象 @@ -277,4 +279,17 @@ export const $api = { ): Promise> => getSubwayStationsPointDetailById(id), }, + + // 暴雨推演 + rainfall: { + /** + * 进行模型推演 + * @param disasterName 灾害名称 + * @returns 推演点的概率 + */ + modelDeduction: ( + disasterName: string + ): Promise> => + rainfallModelDeduction(disasterName), + }, }; diff --git a/src/api/rainfall.ts b/src/api/rainfall.ts new file mode 100644 index 0000000..b7360ce --- /dev/null +++ b/src/api/rainfall.ts @@ -0,0 +1,16 @@ +import type { ApiResponse } from '@/types/ApiResponse'; +import type { RainPredictResponse } from '@/types/rainstorm/RainPredictResponse'; +import httpInstance from '@/utils/request/http'; + +/** + * 进行模型推演 + * @param disasterName 灾害名称 + * @returns 推演点的概率 + */ +export const modelDeduction = ( + disasterName: string +): Promise> => { + return httpInstance.post('/algorithm-api/rainfall/predict', { + disaster_name: disasterName, + }); +}; diff --git a/src/component/map/AdministrativeDivision.vue b/src/component/map/AdministrativeDivision.vue index 63720ab..e081c8f 100644 --- a/src/component/map/AdministrativeDivision.vue +++ b/src/component/map/AdministrativeDivision.vue @@ -40,7 +40,9 @@ polygonStyle: { fill: true, fillColor: areasColor[index].withAlpha(areaTransparency), - outline: false, + outline: true, + outlineColor: Color.WHITE, + outlineWidth: 3, }, }, })); diff --git a/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue b/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue index 7ce9c71..e9f0384 100644 --- a/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue +++ b/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue @@ -4,12 +4,14 @@ + + diff --git a/src/config/config.json b/src/config/config.json index 63a4daf..58dbfdc 100644 --- a/src/config/config.json +++ b/src/config/config.json @@ -35,6 +35,7 @@ }, "prefix": { "landslideHiddenPointId": "landslide-hidden-point-", + "collapseHiddenPointId": "collapse-hidden-point-", "debrisFlowHiddenPointId": "debris-flow-hidden-point-", "waterLoggingHiddenPointId": "water-logging-hidden-point-", "flashFloodHiddenPointId": "flash-flood-hidden-point-", diff --git a/src/hooks/earthquake/useEarthquakeDisasterChain.ts b/src/hooks/earthquake/useEarthquakeDisasterChain.ts index 933ed0b..72d786e 100644 --- a/src/hooks/earthquake/useEarthquakeDisasterChain.ts +++ b/src/hooks/earthquake/useEarthquakeDisasterChain.ts @@ -4,6 +4,7 @@ import { useLayerControl } from '../rain-earthquake/useLayerControl.ts'; import { debrisFlowIcon, landslideIcon, + collapseIcon, riskAreaIcon, earthquakeLineIcon, hospitalIcon, @@ -146,6 +147,18 @@ export const useEarthquakeDisasterChain = () => { LoadingResource.DEBRIS_FLOW_HIDDEN_POINT ), }, + { + name: '崩塌隐患点', + statusStore: statusStore.poiLayers, + statusKey: 'showCollapseHiddenPoint' as const, + callback: layerControl.clickCollapseHiddenPoint, + link: collapseIcon, + category: ControlPanelCategory.DISASTER_HAZARD, + count: () => + resourceStore.getResourceCount( + LoadingResource.COLLAPSE_HIDDEN_POINT + ), + }, { name: '风险点', statusStore: statusStore.mapLayers, diff --git a/src/hooks/map/useMap.ts b/src/hooks/map/useMap.ts index 522b0cc..d82191a 100644 --- a/src/hooks/map/useMap.ts +++ b/src/hooks/map/useMap.ts @@ -25,6 +25,7 @@ export const useMap = () => { // 当id改变时候,重置状态 if ( loadingInfoStore.landslideHiddenPoint.id !== id && + loadingInfoStore.collapseHiddenPoint.id !== id && loadingInfoStore.debrisFlowHiddenPoint.id !== id && loadingInfoStore.waterLoggingHiddenPoint.id !== id && loadingInfoStore.flashFloodHiddenPoint.id !== id && @@ -43,6 +44,11 @@ export const useMap = () => { loadingInfoStore.landslideHiddenPoint.id = id; } + // 崩塌隐患点 + else if (pickedObject.id.startsWith(config.prefix.collapseHiddenPointId)) { + loadingInfoStore.collapseHiddenPoint.id = id; + } + // 泥石流隐患点 else if (pickedObject.id.startsWith(config.prefix.debrisFlowHiddenPointId)) { loadingInfoStore.debrisFlowHiddenPoint.id = id; diff --git a/src/hooks/rain-earthquake/useHiddenPoint.ts b/src/hooks/rain-earthquake/useHiddenPoint.ts index 88e9d98..8eccc4f 100644 --- a/src/hooks/rain-earthquake/useHiddenPoint.ts +++ b/src/hooks/rain-earthquake/useHiddenPoint.ts @@ -1,4 +1,5 @@ import { + collapseIcon, debrisFlowIcon, flashFloodIcon, landslideIcon, @@ -33,6 +34,9 @@ export const useHiddenPoint = () => { case 'landslide': case '滑坡': return landslideIcon; + case 'collapse': + case '崩塌': + return collapseIcon; case 'debris_flow': case '泥石流': return debrisFlowIcon; diff --git a/src/hooks/rain-earthquake/useLayerControl.ts b/src/hooks/rain-earthquake/useLayerControl.ts index b5da6ea..4d2b903 100644 --- a/src/hooks/rain-earthquake/useLayerControl.ts +++ b/src/hooks/rain-earthquake/useLayerControl.ts @@ -161,6 +161,13 @@ export const useLayerControl = () => { statusStore.poiLayers.showLandslideHiddenPoint.loading = true; }; + /** + * 显示崩塌隐患点 + */ + const clickCollapseHiddenPoint = () => { + statusStore.poiLayers.showCollapseHiddenPoint.loading = true; + }; + /** * 显示泥石流隐患点 */ @@ -221,6 +228,7 @@ export const useLayerControl = () => { clickReservoir, clickSubwayStation, clickLandslideHiddenPoint, + clickCollapseHiddenPoint, clickDebrisFlowHiddenPoint, clickWaterLoggingHiddenPoint, clickFlashFloodHiddenPoint, diff --git a/src/hooks/rainstorm/useRainDisasterChain.ts b/src/hooks/rainstorm/useRainDisasterChain.ts index ed1cacf..f8fdf78 100644 --- a/src/hooks/rainstorm/useRainDisasterChain.ts +++ b/src/hooks/rainstorm/useRainDisasterChain.ts @@ -4,6 +4,7 @@ import { debrisFlowIcon, flashFloodIcon, landslideIcon, + collapseIcon, riskAreaIcon, waterLoggingIcon, hospitalIcon, @@ -199,6 +200,18 @@ export const useRainDisasterChain = () => { LoadingResource.FLASH_FLOOD_HIDDEN_POINT ), }, + { + name: '崩塌隐患点', + statusStore: statusStore.poiLayers, + statusKey: 'showCollapseHiddenPoint' as const, + callback: layerControl.clickCollapseHiddenPoint, + link: collapseIcon, + category: ControlPanelCategory.DISASTER_HAZARD, + count: () => + resourceStore.getResourceCount( + LoadingResource.COLLAPSE_HIDDEN_POINT + ), + }, { name: '风险点', statusStore: statusStore.mapLayers, diff --git a/src/stores/useLoadingInformation.ts b/src/stores/useLoadingInformation.ts index 28ac7a6..2a34fe5 100644 --- a/src/stores/useLoadingInformation.ts +++ b/src/stores/useLoadingInformation.ts @@ -114,6 +114,14 @@ export const useLoadingInformationStore = defineStore( id: -1, }); + // ============================== 崩塌隐患点状态 ================================ + const collapseHiddenPoint = reactive({ + /** 加载状态 */ + loading: false, + /** 崩塌隐患点ID */ + id: -1, + }); + // ============================== 泥石流隐患点状态 ================================ const debrisFlowHiddenPoint = reactive({ /** 加载状态 */ @@ -190,6 +198,10 @@ export const useLoadingInformationStore = defineStore( landslideHiddenPoint.loading = false; landslideHiddenPoint.id = -1; + // 崩塌隐患点状态重置 + collapseHiddenPoint.loading = false; + collapseHiddenPoint.id = -1; + // 泥石流隐患点状态重置 debrisFlowHiddenPoint.loading = false; debrisFlowHiddenPoint.id = -1; @@ -216,6 +228,7 @@ export const useLoadingInformationStore = defineStore( reservoir, subwayStation, landslideHiddenPoint, + collapseHiddenPoint, debrisFlowHiddenPoint, waterLoggingHiddenPoint, flashFloodHiddenPoint, diff --git a/src/stores/useStatusStore.ts b/src/stores/useStatusStore.ts index 9650e0d..d2cd0a6 100644 --- a/src/stores/useStatusStore.ts +++ b/src/stores/useStatusStore.ts @@ -118,6 +118,11 @@ export const useStatusStore = defineStore('status', () => { show: true, loading: true, }, + /** 显示崩塌隐患点 */ + showCollapseHiddenPoint: { + show: true, + loading: true, + }, /** 显示泥石流隐患点 */ showDebrisFlowHiddenPoint: { show: true, @@ -278,6 +283,10 @@ export const useStatusStore = defineStore('status', () => { show: true, loading: true, }; + poiLayers.showCollapseHiddenPoint = { + show: true, + loading: true, + }; poiLayers.showDebrisFlowHiddenPoint = { show: true, loading: true, diff --git a/src/types/common/DisasterType.ts b/src/types/common/DisasterType.ts index 3df9660..7cabce6 100644 --- a/src/types/common/DisasterType.ts +++ b/src/types/common/DisasterType.ts @@ -14,6 +14,8 @@ export enum DisasterType { export enum PointType { /** 滑坡 */ LANDSLIDE = '滑坡', + /** 崩塌 */ + COLLAPSE = '崩塌', /** 泥石流 */ DEBRIS_FLOW = '泥石流', /** 内涝 */ @@ -29,6 +31,7 @@ export enum PointType { */ export const HiddenDangerPointTypeMap: Record = { [PointType.LANDSLIDE]: 'landslide', + [PointType.COLLAPSE]: 'collapse', [PointType.DEBRIS_FLOW]: 'debris_flow', [PointType.WATER_LOGGING]: 'water_logging', [PointType.FLASH_FLOOD]: 'flash_flood', diff --git a/src/types/common/LoadingResourceType.ts b/src/types/common/LoadingResourceType.ts index 2af50ce..a15878b 100644 --- a/src/types/common/LoadingResourceType.ts +++ b/src/types/common/LoadingResourceType.ts @@ -47,6 +47,11 @@ export enum LoadingResource { */ LANDSLIDE_HIDDEN_POINT = 'LANDSLIDE_HIDDEN_POINT', + /** + * 崩塌隐患点 + */ + COLLAPSE_HIDDEN_POINT = 'COLLAPSE_HIDDEN_POINT', + /** * 泥石流隐患点 */ From 863340d27cb34d5d037cdf5b7b592b203bb92a96 Mon Sep 17 00:00:00 2001 From: wzy-warehouse <18135009705@163.com> Date: Tue, 16 Jun 2026 10:32:25 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E8=84=89=E5=86=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail-panels/RainfallGridComponent.vue | 3 +- src/hooks/rain-earthquake/useRightHandle.ts | 7 +++- src/utils/cesium/CesiumUtils.ts | 41 +++++++++++++++++-- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue b/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue index bc62b7e..7f025d3 100644 --- a/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue +++ b/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue @@ -53,8 +53,7 @@ // 进行模型计算 $api.rainfall .modelDeduction({ - disaster_name: `${Utils.formatDate('YYYYMMDDHHmmss', new Date('2025-09-16 20:00:00'))}暴雨自动推演`, - occurred_time: '2025-09-16 20:00:00', + disaster_name: `${Utils.formatDate('YYYYMMDDHHmmss')}暴雨自动推演`, operation_type: '暴雨灾害链自动推演', }) .then((res) => { diff --git a/src/hooks/rain-earthquake/useRightHandle.ts b/src/hooks/rain-earthquake/useRightHandle.ts index 5b6b90a..f208e07 100644 --- a/src/hooks/rain-earthquake/useRightHandle.ts +++ b/src/hooks/rain-earthquake/useRightHandle.ts @@ -25,6 +25,9 @@ export const useRightHandle = () => { // 添加图例 rainstormDeduction.addLegend(); + + // 如果有脉冲,显示脉冲 + CesiumUtilsSingleton.showPulseEffects(); } else { // 关闭暴雨模拟:隐藏降雨栅格图层 statusStore.weatherLayers.showRainfallGrid.show = false; @@ -35,8 +38,8 @@ export const useRightHandle = () => { // 隐藏步骤条 statusStore.uiComponents.stepBar.show = false; - // 删除脉冲 - CesiumUtilsSingleton.removeAllPulses(); + // 隐藏脉冲 + CesiumUtilsSingleton.hidePulseEffects(); } }; diff --git a/src/utils/cesium/CesiumUtils.ts b/src/utils/cesium/CesiumUtils.ts index 851959b..a7f6ce7 100644 --- a/src/utils/cesium/CesiumUtils.ts +++ b/src/utils/cesium/CesiumUtils.ts @@ -22,6 +22,7 @@ import { Color, JulianDate, CallbackProperty, + ConstantProperty, HeightReference, VerticalOrigin, HorizontalOrigin, @@ -674,6 +675,38 @@ export class CesiumUtils { } } + /** + * 隐藏所有脉冲效果 + */ + hidePulseEffects(): void { + const viewer = this.getViewer(); + if (!viewer) return; + + for (const key of Object.keys(this.#pulseMap)) { + const entry = this.#pulseMap[key]; + const entity = viewer.entities.getById(entry.pulseId); + if (entity && entity.billboard) { + entity.billboard.show = new ConstantProperty(false); + } + } + } + + /** + * 显示所有脉冲效果 + */ + showPulseEffects(): void { + const viewer = this.getViewer(); + if (!viewer) return; + + for (const key of Object.keys(this.#pulseMap)) { + const entry = this.#pulseMap[key]; + const entity = viewer.entities.getById(entry.pulseId); + if (entity && entity.billboard) { + entity.billboard.show = new ConstantProperty(true); + } + } + } + // ===================== 私有方法 ===================== /** @@ -729,24 +762,24 @@ export class CesiumUtils { viewer.entities.add({ id: pulseId, position: Cartesian3.fromDegrees(lon, lat), - properties: {pulseKey: key}, + properties: { pulseKey: key }, billboard: { image: this.#pulseCircleImage, width: new CallbackProperty((time) => { const elapsed = - JulianDate.secondsDifference(time, startTime) % duration; + JulianDate.secondsDifference(time, startTime) % duration; const progress = elapsed / duration; return maxRadius * 2 * Math.abs(Math.sin(progress * Math.PI)); }, false), height: new CallbackProperty((time) => { const elapsed = - JulianDate.secondsDifference(time, startTime) % duration; + JulianDate.secondsDifference(time, startTime) % duration; const progress = elapsed / duration; return maxRadius * 2 * Math.abs(Math.sin(progress * Math.PI)); }, false), color: new CallbackProperty((time) => { const elapsed = - JulianDate.secondsDifference(time, startTime) % duration; + JulianDate.secondsDifference(time, startTime) % duration; const progress = elapsed / duration; const alpha = 0.7 * (1 - progress); return color.withAlpha(alpha); From 044d7fd3d1f7c7029662883627a2db2a0b48751c Mon Sep 17 00:00:00 2001 From: wzy-warehouse <18135009705@163.com> Date: Tue, 16 Jun 2026 10:33:55 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E4=BF=AE=E6=94=B9geoserver=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=E7=AB=AF=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.development b/.env.development index 2a08ab2..98dc148 100644 --- a/.env.development +++ b/.env.development @@ -5,7 +5,7 @@ VITE_BACKEND_BASE_URL=http://localhost:8081 START_PORT=81 # geoserver地址 -VITE_GEOSERVER_BASE_URL=http://47.92.216.173:4019/geoserver/xian +VITE_GEOSERVER_BASE_URL=http://47.92.216.173:4020/geoserver/xian # WebSocket地址 VITE_WEBSOCKET_URL=http://localhost:8081/websocket From b6dcab7f51c1cdfaa8e20f974ee80125f6532638 Mon Sep 17 00:00:00 2001 From: wzy-warehouse <18135009705@163.com> Date: Tue, 16 Jun 2026 18:19:34 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=A8=A1=E6=8B=9F?= =?UTF-8?q?=E7=9B=91=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail-panels/RainfallGridComponent.vue | 5 +++- src/hooks/rain-earthquake/useRightHandle.ts | 9 ++++++ src/stores/useSimulationIdStore.ts | 28 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/stores/useSimulationIdStore.ts diff --git a/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue b/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue index 7f025d3..936cd78 100644 --- a/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue +++ b/src/component/rain-earthquake/detail-panels/RainfallGridComponent.vue @@ -6,6 +6,7 @@