修改降雨栅格图显示逻辑

This commit is contained in:
wzy-warehouse
2026-05-18 21:08:43 +08:00
parent 532648ebd8
commit 133cf6d9a7
10 changed files with 157 additions and 48 deletions
+4 -1
View File
@@ -10,4 +10,7 @@ START_PORT=81
VITE_GEOSERVER_BASE_URL=http://47.92.216.173:4019/geoserver/xian VITE_GEOSERVER_BASE_URL=http://47.92.216.173:4019/geoserver/xian
# WebSocket地址 # WebSocket地址
VITE_WEBSOCKET_URL=ws://localhost:8081 VITE_WEBSOCKET_URL=http://localhost:8081/websocket
# 文件地址
VITE_FILE_URL=http://localhost:8083
+4 -1
View File
@@ -10,4 +10,7 @@ START_PORT=80
VITE_GEOSERVER_BASE_URL=http://10.22.245.246/geoserver/xian VITE_GEOSERVER_BASE_URL=http://10.22.245.246/geoserver/xian
# WebSocket地址 # WebSocket地址
VITE_WEBSOCKET_URL=ws://localhost:8080 VITE_WEBSOCKET_URL=http://localhost:8080/websocket
# 文件地址
VITE_FILE_URL=http://localhost:8083
Vendored
+1
View File
@@ -12,6 +12,7 @@ interface ImportMetaEnv {
readonly START_PORT: number; readonly START_PORT: number;
readonly VITE_GEOSERVER_BASE_URL: string; readonly VITE_GEOSERVER_BASE_URL: string;
readonly VITE_WEBSOCKET_URL: string; readonly VITE_WEBSOCKET_URL: string;
readonly VITE_FILE_URL: string;
readonly MODE: string; readonly MODE: string;
readonly DEV: boolean; readonly DEV: boolean;
readonly PROD: boolean; readonly PROD: boolean;
@@ -3,6 +3,77 @@
<div></div> <div></div>
</template> </template>
<script lang="ts" setup></script> <script lang="ts" setup>
import { useRainstormDeduction } from '@/hooks/rainstorm/useRainstormDeduction';
import { useStatusStore } from '@/stores/useStatusStore';
import type { ApiResponse } from '@/types/ApiResponse';
import type { RainfallGridResponse } from '@/types/rainstorm/RainfallGridResponse';
import { WebSocketService } from '@/utils/request/websocket';
import { onMounted, onUnmounted, watch } from 'vue';
let rainfallWsService: WebSocketService | null = null;
const { triggerLayerShowStatus, addGridLayer } = useRainstormDeduction();
const statusStore = useStatusStore();
// 请求降雨栅格数据
const requestRainfallData = () => {
if (!rainfallWsService) {
console.error('WebSocket 服务未初始化');
return;
}
rainfallWsService.send('/app/rainfall/grid');
};
// 初始化 WebSocket 回调
onMounted(() => {
// 创建 WebSocket 实例
rainfallWsService = new WebSocketService();
// 连接成功回调
rainfallWsService.onConnected = () => {
// 订阅降雨网格数据主题
rainfallWsService!.subscribe<ApiResponse<RainfallGridResponse>>(
'/topic/rainfall/grid/messages',
(response) => {
if (response.code === 200 && response.data) {
// 显示图层
addGridLayer(response.data);
} else {
console.warn('响应错误:', response.message);
}
}
);
// 连接成功后自动请求一次数据
setTimeout(() => {
requestRainfallData();
}, 1000);
};
// 错误回调
rainfallWsService.onError = (error) => {
console.error('WebSocket 错误:', error);
};
// 自动连接
rainfallWsService.connect();
});
onUnmounted(() => {
// 销毁 WebSocket 实例
if (rainfallWsService) {
rainfallWsService.disconnect();
rainfallWsService = null;
}
});
// 监听显示隐藏
watch(
() => statusStore.weatherLayers.showRainfallGrid.show,
(newValue: boolean) => {
triggerLayerShowStatus(newValue);
}
);
</script>
<style scoped></style> <style scoped></style>
+50 -7
View File
@@ -1,11 +1,16 @@
import { useLeftLegendStore } from '@/stores/useLeftLegendStore'; import { useLeftLegendStore } from '@/stores/useLeftLegendStore';
import { useStatusStore } from '@/stores/useStatusStore'; import { useStatusStore } from '@/stores/useStatusStore';
import { useStepStore } from '@/stores/useStepStore'; import { useStepStore } from '@/stores/useStepStore';
import type { RainfallGridResponse } from '@/types/rainstorm/RainfallGridResponse';
import { CesiumUtilsSingleton } from '@/utils/cesium/CesiumUtils';
import { ImageryLayer, Rectangle, SingleTileImageryProvider } from 'cesium';
export const useRainstormDeduction = () => { export const useRainstormDeduction = () => {
const statusStore = useStatusStore(); const statusStore = useStatusStore();
const leftLegendStore = useLeftLegendStore(); const leftLegendStore = useLeftLegendStore();
const stepStore = useStepStore(); const stepStore = useStepStore();
let layer: ImageryLayer | null = null;
/** /**
* 显示步骤 * 显示步骤
*/ */
@@ -23,15 +28,15 @@ export const useRainstormDeduction = () => {
list: [ list: [
{ {
label: '无雨/微雨; <0.1mm/12h', label: '无雨/微雨; <0.1mm/12h',
color: 'rgba(200,200,200,0)', color: 'rgba(200, 200, 200, 0)',
}, },
{ {
label: '小雨;<5mm/12h', label: '小雨;<5mm/12h',
color: 'rgba(0,0,255,0.4)', color: 'rgba(0, 0, 255, 0.4)',
}, },
{ {
label: '中雨; <15mm/12h', label: '中雨; <15mm/12h',
color: 'rgba(0,255,255,0.5)', color: 'rgba(0, 255, 255, 0.5)',
}, },
{ {
label: '大雨; <30mm/12h', label: '大雨; <30mm/12h',
@@ -39,19 +44,57 @@ export const useRainstormDeduction = () => {
}, },
{ {
label: '暴雨; <70mm/12h', label: '暴雨; <70mm/12h',
color: 'rgba(255,255,0,0.7)', color: 'rgba(255, 255, 0, 0.7)',
}, },
{ {
label: '大暴雨; <140mm/12h', label: '大暴雨; <140mm/12h',
color: 'rgba(255,165,0,0.8)', color: 'rgba(255, 165, 0, 0.8)',
}, },
{ {
label: '特大暴雨; >140mm/12h', label: '特大暴雨; >140mm/12h',
color: 'rgba(255,0,0,0.9)', color: 'rgba(255, 0, 0, 0.9)',
}, },
], ],
}; };
}; };
return { showStep, addLegend }; /**
* 添加降雨栅格图层
* @param response - 雨量栅格响应
*/
const addGridLayer = (response: RainfallGridResponse) => {
// 删除旧图层
if (layer) {
CesiumUtilsSingleton.getViewer()!.imageryLayers.remove(layer);
}
const rectangle = Rectangle.fromDegrees(
response.cesiumConfig!.rectangle.west,
response.cesiumConfig!.rectangle.south,
response.cesiumConfig!.rectangle.east,
response.cesiumConfig!.rectangle.north
);
// 创建单张影像提供器
const provider = new SingleTileImageryProvider({
url: `${import.meta.env.VITE_FILE_URL}/${response.pngPath}`.replace(
'//',
'/'
),
rectangle: rectangle,
});
layer =
CesiumUtilsSingleton.getViewer()!.imageryLayers.addImageryProvider(
provider
);
};
/**
* 触发图层显示状态
*/
const triggerLayerShowStatus = (status: boolean) => {
layer!.show = status;
};
return { showStep, addLegend, addGridLayer, triggerLayerShowStatus };
}; };
+2 -2
View File
@@ -183,7 +183,7 @@ export const useStatusStore = defineStore('status', () => {
/** 显示降雨栅格 */ /** 显示降雨栅格 */
showRainfallGrid: { showRainfallGrid: {
show: false, show: false,
loading: true, loading: false,
}, },
}); });
@@ -320,7 +320,7 @@ export const useStatusStore = defineStore('status', () => {
// 气象图层显示状态重置 // 气象图层显示状态重置
weatherLayers.showRainfallGrid = { weatherLayers.showRainfallGrid = {
show: false, show: false,
loading: true, loading: false,
}; };
// 功能显示状态重置 // 功能显示状态重置
@@ -1,6 +0,0 @@
export interface RainfallGridRequest {
// 时间,默认为当前时间
time?: string;
// 分辨率,默认为0.01,最小为0,最大为0.1
resolution?: number;
}
+13 -22
View File
@@ -1,26 +1,17 @@
export interface RainfallFeature {
type: 'Feature';
geometry: {
type: 'Polygon';
coordinates: number[][][];
};
properties: {
rainfall: number;
color: string;
};
}
export interface RainfallGridResponse { export interface RainfallGridResponse {
type: 'FeatureCollection'; id: number;
features: RainfallFeature[]; pngPath: string;
metadata: { queryTime?: string;
resolution: number; resolution?: number;
grid_size: number[]; stationCount?: number;
bounds: { cesiumConfig?: {
min_lon: number; rectangle: {
max_lon: number; west: number;
min_lat: number; south: number;
max_lat: number; east: number;
north: number;
}; };
width?: number;
height?: number;
}; };
} }
+1 -1
View File
@@ -3,7 +3,7 @@
*/ */
export interface WebSocketConfig { export interface WebSocketConfig {
/** WebSocket路径 */ /** WebSocket路径 */
url: string; url?: string;
/** 自动重连间隔(毫秒,默认3000) */ /** 自动重连间隔(毫秒,默认3000) */
reconnectDelay?: number; reconnectDelay?: number;
/** 最大重连次数(默认5,-1表示无限重连) */ /** 最大重连次数(默认5,-1表示无限重连) */
+10 -7
View File
@@ -16,13 +16,14 @@ export class WebSocketService {
onDisconnected?: () => void; onDisconnected?: () => void;
onError?: (error: unknown) => void; onError?: (error: unknown) => void;
constructor(config: WebSocketConfig) { constructor(config?: WebSocketConfig) {
config = config || ({} as WebSocketConfig);
this.config = { this.config = {
url: config.url, url: config!.url || import.meta.env.VITE_WEBSOCKET_URL,
reconnectDelay: config.reconnectDelay || 3000, reconnectDelay: config!.reconnectDelay || 3000,
maxReconnectAttempts: config.maxReconnectAttempts || 5, maxReconnectAttempts: config!.maxReconnectAttempts || 5,
heartbeatIncoming: config.heartbeatIncoming || 30000, heartbeatIncoming: config!.heartbeatIncoming || 30000,
heartbeatOutgoing: config.heartbeatOutgoing || 30000, heartbeatOutgoing: config!.heartbeatOutgoing || 30000,
}; };
} }
@@ -102,7 +103,7 @@ export class WebSocketService {
/** /**
* 发送消息到指定目的地 * 发送消息到指定目的地
*/ */
send(destination: string, body: unknown) { send(destination: string, body?: unknown) {
if (!this.stompClient || !this.connected) { if (!this.stompClient || !this.connected) {
console.error('WebSocket 未连接'); console.error('WebSocket 未连接');
return; return;
@@ -153,3 +154,5 @@ export class WebSocketService {
} }
} }
} }
export const socketSignalInstance = new WebSocketService();