From 44c9351ced980e671fcd34c13a6d5ace8f818075 Mon Sep 17 00:00:00 2001 From: luxiaotao1123 <t1341870251@163.com> Date: 星期三, 09 十月 2024 10:35:27 +0800 Subject: [PATCH] # --- zy-acs-flow/src/map/websocket.js | 83 ++++++++++++++++++++ zy-acs-flow/src/map/tool.js | 20 +++++ zy-acs-flow/src/map/Notification.jsx | 51 ++++++++++++ zy-acs-flow/src/map/MapPage.jsx | 32 ++++++- 4 files changed, 181 insertions(+), 5 deletions(-) diff --git a/zy-acs-flow/src/map/MapPage.jsx b/zy-acs-flow/src/map/MapPage.jsx index 031d5b1..668d32c 100644 --- a/zy-acs-flow/src/map/MapPage.jsx +++ b/zy-acs-flow/src/map/MapPage.jsx @@ -8,6 +8,7 @@ SpeedDial, SpeedDialAction, useTheme, + Snackbar, } from '@mui/material'; import { MoreVert as MoreVertIcon, @@ -18,16 +19,19 @@ Share as ShareIcon, } from '@mui/icons-material'; import Player from './player'; +import * as Tool from './tool'; +import { NotificationProvider, useNotification } from './Notification'; let player; -const MapPage = () => { +const Map = () => { const mapRef = useRef(); const contentRef = React.useRef(); const [app, setApp] = useState(null); const [mapContainer, setMapContainer] = React.useState(null); + const notify = useNotification(); - const [mode, setMode] = useState('monitoring'); + const [mode, setMode] = useState(MapModel.OBSERVER_MODEL); const theme = useTheme(); const themeMode = theme.palette.mode; @@ -43,6 +47,8 @@ player = new Player(mapRef.current, themeMode); setApp(player.app); setMapContainer(player.mapContainer); + Tool.setApp(player.app); + Tool.setMapContainer(player.mapContainer); } initialize(); @@ -56,6 +62,8 @@ }; handleResize(); window.addEventListener('resize', handleResize); + + notify('Welcome to Rcs', 'info'); return () => { player.destroy(); @@ -122,9 +130,9 @@ borderRadius: 1, }} > - <MenuItem value="monitoring">鐩戞帶妯″紡</MenuItem> - <MenuItem value="edit">缂栬緫妯″紡</MenuItem> - <MenuItem value="configuration">閰嶇疆妯″紡</MenuItem> + <MenuItem value={MapModel.OBSERVER_MODEL}>鐩戞帶妯″紡</MenuItem> + <MenuItem value={MapModel.MOVABLE_MODEL}>缂栬緫妯″紡</MenuItem> + <MenuItem value={MapModel.SETTINGS_MODEL}>閰嶇疆妯″紡</MenuItem> </Select> <Button variant="contained" @@ -181,4 +189,18 @@ ); } +const MapPage = () => { + return ( + <NotificationProvider> + <Map /> + </NotificationProvider> + ) +} + +export const MapModel = Object.freeze({ + OBSERVER_MODEL: "1", + MOVABLE_MODEL: "2", + SETTINGS_MODEL: "3", +}) + export default MapPage; diff --git a/zy-acs-flow/src/map/Notification.jsx b/zy-acs-flow/src/map/Notification.jsx new file mode 100644 index 0000000..ecfb3e7 --- /dev/null +++ b/zy-acs-flow/src/map/Notification.jsx @@ -0,0 +1,51 @@ +import React, { createContext, useContext, useState, useCallback } from 'react'; +import { Snackbar, Alert, Portal, Slide } from '@mui/material'; + +const NotificationContext = createContext(); + +const SlideTransition = (props) => { + return <Slide {...props} direction="up" />; +} + +export const NotificationProvider = ({ children }) => { + const [notification, setNotification] = useState({ + open: false, + message: '', + severity: 'info', + }); + + const showNotification = useCallback((message, severity = 'info') => { + setNotification({ open: true, message, severity }); + }, []); + + const handleClose = () => { + setNotification({ ...notification, open: false }); + }; + + return ( + <NotificationContext.Provider value={showNotification}> + {children} + <Portal> + <Snackbar + open={notification.open} + autoHideDuration={4000} + onClose={handleClose} + TransitionComponent={SlideTransition} + anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} + sx={{ + // mt: 12, + zIndex: 2000, + }} + > + <Alert onClose={handleClose} severity={notification.severity} sx={{ width: '300px', zIndex: 2000 }}> + {notification.message} + </Alert> + </Snackbar> + </Portal> + </NotificationContext.Provider> + ); +}; + +export const useNotification = () => { + return useContext(NotificationContext); +}; diff --git a/zy-acs-flow/src/map/tool.js b/zy-acs-flow/src/map/tool.js new file mode 100644 index 0000000..a445b38 --- /dev/null +++ b/zy-acs-flow/src/map/tool.js @@ -0,0 +1,20 @@ +import * as PIXI from 'pixi.js'; +import * as TWEEDLE from 'tweedle.js'; + +let app, mapContainer; + +export function setApp(param) { + app = param; +} + +export function setMapContainer(param) { + mapContainer = param; +} + +export function getApp() { + return app; +} + +export function getMapContainer() { + return mapContainer; +} diff --git a/zy-acs-flow/src/map/websocket.js b/zy-acs-flow/src/map/websocket.js new file mode 100644 index 0000000..3c9ec74 --- /dev/null +++ b/zy-acs-flow/src/map/websocket.js @@ -0,0 +1,83 @@ +import { WEBSOCKET_BASE_URL } from '@/config/setting'; + +export default class WebSocketClient { + + constructor(path) { + this.url = WEBSOCKET_BASE_URL + path; + this.webSocket = null; + this.heartbeatInterval = null; // Store the interval ID + this.heartbeatFrequency = 30000; // Heartbeat every 30 seconds + } + + connect() { + if (!this.url) { + console.error('WebSocketClient: Cannot connect without url.'); + return; + } + + this.webSocket = new WebSocket(this.url); + + this.webSocket.onopen = (event) => { + console.log('websocket connection opened.'); + // Start the heartbeat + this.startHeartbeat(); + }; + + this.webSocket.onmessage = (event) => { + // console.log('websocket message received:', event.data); + this.onMessage(event.data); + }; + + this.webSocket.onerror = (event) => { + console.error('websocket error observed:', event); + }; + + this.webSocket.onclose = (event) => { + console.log('websocket connection closed!'); + // Clear the heartbeat + this.stopHeartbeat(); + this.reconnect(); + }; + } + + sendMessage(message) { + if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) { + this.webSocket.send(message); + } else { + console.error('WebSocketClient: Cannot send message, WebSocket connection is not open.'); + } + } + + // Override + onMessage(data) { + } + + close() { + if (this.webSocket && this.webSocket.readyState === WebSocket.OPEN) { + this.webSocket.close(); + } + } + + reconnect() { + setTimeout(() => { + console.log('WebSocketClient: Attempting to reconnect...'); + this.connect(); + }, 3000); + } + + startHeartbeat() { + if (this.heartbeatInterval) { + clearInterval(this.heartbeatInterval); + } + this.heartbeatInterval = setInterval(() => { + this.sendMessage('1'); + }, this.heartbeatFrequency); + } + + stopHeartbeat() { + if (this.heartbeatInterval) { + clearInterval(this.heartbeatInterval); + this.heartbeatInterval = null; + } + } +} \ No newline at end of file -- Gitblit v1.9.1