#
luxiaotao1123
2024-10-09 44c9351ced980e671fcd34c13a6d5ace8f818075
#
1个文件已修改
3个文件已添加
186 ■■■■■ 已修改文件
zy-acs-flow/src/map/MapPage.jsx 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/map/Notification.jsx 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/map/tool.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/map/websocket.js 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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;
zy-acs-flow/src/map/Notification.jsx
New file
@@ -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);
};
zy-acs-flow/src/map/tool.js
New file
@@ -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;
}
zy-acs-flow/src/map/websocket.js
New file
@@ -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;
        }
    }
}