修改降雨栅格图显示逻辑
This commit is contained in:
+4
-1
@@ -10,4 +10,7 @@ START_PORT=81
|
||||
VITE_GEOSERVER_BASE_URL=http://47.92.216.173:4019/geoserver/xian
|
||||
|
||||
# WebSocket地址
|
||||
VITE_WEBSOCKET_URL=ws://localhost:8081
|
||||
VITE_WEBSOCKET_URL=http://localhost:8081/websocket
|
||||
|
||||
# 文件地址
|
||||
VITE_FILE_URL=http://localhost:8083
|
||||
+4
-1
@@ -10,4 +10,7 @@ START_PORT=80
|
||||
VITE_GEOSERVER_BASE_URL=http://10.22.245.246/geoserver/xian
|
||||
|
||||
# WebSocket地址
|
||||
VITE_WEBSOCKET_URL=ws://localhost:8080
|
||||
VITE_WEBSOCKET_URL=http://localhost:8080/websocket
|
||||
|
||||
# 文件地址
|
||||
VITE_FILE_URL=http://localhost:8083
|
||||
@@ -12,6 +12,7 @@ interface ImportMetaEnv {
|
||||
readonly START_PORT: number;
|
||||
readonly VITE_GEOSERVER_BASE_URL: string;
|
||||
readonly VITE_WEBSOCKET_URL: string;
|
||||
readonly VITE_FILE_URL: string;
|
||||
readonly MODE: string;
|
||||
readonly DEV: boolean;
|
||||
readonly PROD: boolean;
|
||||
|
||||
@@ -3,6 +3,77 @@
|
||||
<div></div>
|
||||
</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>
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { useLeftLegendStore } from '@/stores/useLeftLegendStore';
|
||||
import { useStatusStore } from '@/stores/useStatusStore';
|
||||
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 = () => {
|
||||
const statusStore = useStatusStore();
|
||||
const leftLegendStore = useLeftLegendStore();
|
||||
const stepStore = useStepStore();
|
||||
|
||||
let layer: ImageryLayer | null = null;
|
||||
/**
|
||||
* 显示步骤
|
||||
*/
|
||||
@@ -23,15 +28,15 @@ export const useRainstormDeduction = () => {
|
||||
list: [
|
||||
{
|
||||
label: '无雨/微雨; <0.1mm/12h',
|
||||
color: 'rgba(200,200,200,0)',
|
||||
color: 'rgba(200, 200, 200, 0)',
|
||||
},
|
||||
{
|
||||
label: '小雨;<5mm/12h',
|
||||
color: 'rgba(0,0,255,0.4)',
|
||||
color: 'rgba(0, 0, 255, 0.4)',
|
||||
},
|
||||
{
|
||||
label: '中雨; <15mm/12h',
|
||||
color: 'rgba(0,255,255,0.5)',
|
||||
color: 'rgba(0, 255, 255, 0.5)',
|
||||
},
|
||||
{
|
||||
label: '大雨; <30mm/12h',
|
||||
@@ -39,19 +44,57 @@ export const useRainstormDeduction = () => {
|
||||
},
|
||||
{
|
||||
label: '暴雨; <70mm/12h',
|
||||
color: 'rgba(255,255,0,0.7)',
|
||||
color: 'rgba(255, 255, 0, 0.7)',
|
||||
},
|
||||
{
|
||||
label: '大暴雨; <140mm/12h',
|
||||
color: 'rgba(255,165,0,0.8)',
|
||||
color: 'rgba(255, 165, 0, 0.8)',
|
||||
},
|
||||
{
|
||||
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 };
|
||||
};
|
||||
|
||||
@@ -183,7 +183,7 @@ export const useStatusStore = defineStore('status', () => {
|
||||
/** 显示降雨栅格 */
|
||||
showRainfallGrid: {
|
||||
show: false,
|
||||
loading: true,
|
||||
loading: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -320,7 +320,7 @@ export const useStatusStore = defineStore('status', () => {
|
||||
// 气象图层显示状态重置
|
||||
weatherLayers.showRainfallGrid = {
|
||||
show: false,
|
||||
loading: true,
|
||||
loading: false,
|
||||
};
|
||||
|
||||
// 功能显示状态重置
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
export interface RainfallGridRequest {
|
||||
// 时间,默认为当前时间
|
||||
time?: string;
|
||||
// 分辨率,默认为0.01,最小为0,最大为0.1
|
||||
resolution?: number;
|
||||
}
|
||||
@@ -1,26 +1,17 @@
|
||||
export interface RainfallFeature {
|
||||
type: 'Feature';
|
||||
geometry: {
|
||||
type: 'Polygon';
|
||||
coordinates: number[][][];
|
||||
};
|
||||
properties: {
|
||||
rainfall: number;
|
||||
color: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RainfallGridResponse {
|
||||
type: 'FeatureCollection';
|
||||
features: RainfallFeature[];
|
||||
metadata: {
|
||||
resolution: number;
|
||||
grid_size: number[];
|
||||
bounds: {
|
||||
min_lon: number;
|
||||
max_lon: number;
|
||||
min_lat: number;
|
||||
max_lat: number;
|
||||
id: number;
|
||||
pngPath: string;
|
||||
queryTime?: string;
|
||||
resolution?: number;
|
||||
stationCount?: number;
|
||||
cesiumConfig?: {
|
||||
rectangle: {
|
||||
west: number;
|
||||
south: number;
|
||||
east: number;
|
||||
north: number;
|
||||
};
|
||||
width?: number;
|
||||
height?: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
export interface WebSocketConfig {
|
||||
/** WebSocket路径 */
|
||||
url: string;
|
||||
url?: string;
|
||||
/** 自动重连间隔(毫秒,默认3000) */
|
||||
reconnectDelay?: number;
|
||||
/** 最大重连次数(默认5,-1表示无限重连) */
|
||||
|
||||
@@ -16,13 +16,14 @@ export class WebSocketService {
|
||||
onDisconnected?: () => void;
|
||||
onError?: (error: unknown) => void;
|
||||
|
||||
constructor(config: WebSocketConfig) {
|
||||
constructor(config?: WebSocketConfig) {
|
||||
config = config || ({} as WebSocketConfig);
|
||||
this.config = {
|
||||
url: config.url,
|
||||
reconnectDelay: config.reconnectDelay || 3000,
|
||||
maxReconnectAttempts: config.maxReconnectAttempts || 5,
|
||||
heartbeatIncoming: config.heartbeatIncoming || 30000,
|
||||
heartbeatOutgoing: config.heartbeatOutgoing || 30000,
|
||||
url: config!.url || import.meta.env.VITE_WEBSOCKET_URL,
|
||||
reconnectDelay: config!.reconnectDelay || 3000,
|
||||
maxReconnectAttempts: config!.maxReconnectAttempts || 5,
|
||||
heartbeatIncoming: config!.heartbeatIncoming || 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) {
|
||||
console.error('WebSocket 未连接');
|
||||
return;
|
||||
@@ -153,3 +154,5 @@ export class WebSocketService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const socketSignalInstance = new WebSocketService();
|
||||
|
||||
Reference in New Issue
Block a user