修改降雨栅格图显示逻辑
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
|
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
@@ -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
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
/**
|
/**
|
||||||
* 显示步骤
|
* 显示步骤
|
||||||
*/
|
*/
|
||||||
@@ -53,5 +58,43 @@ export const useRainstormDeduction = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
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: {
|
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;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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表示无限重连) */
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user