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