feat(flowEditor): 添加流程运行功能及WebSocket支持
- 在ActionBar组件中增加运行/停止按钮及状态控制 - 实现流程运行时的WebSocket连接管理 - 添加useWebSocket自定义hook处理WebSocket通信- 支持运行状态切换和实时消息处理 - 集成用户令牌认证和WebSocket地址配置 - 提供运行启动和停止的完整生命周期管理master
parent
11c796aa75
commit
0230119987
@ -0,0 +1,131 @@
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
|
||||
interface WebSocketOptions {
|
||||
reconnectInterval?: number;
|
||||
maxReconnectAttempts?: number;
|
||||
onOpen?: (event: Event) => void;
|
||||
onClose?: (event: CloseEvent) => void;
|
||||
onError?: (event: Event) => void;
|
||||
onMessage?: (event: MessageEvent) => void;
|
||||
}
|
||||
|
||||
interface WebSocketHook {
|
||||
connect: (url: string) => void;
|
||||
disconnect: () => void;
|
||||
sendMessage: (message: string | object) => void;
|
||||
readyState: number;
|
||||
isConnected: boolean;
|
||||
}
|
||||
|
||||
const useWebSocket = (options: WebSocketOptions = {}): WebSocketHook => {
|
||||
const {
|
||||
reconnectInterval = 3000,
|
||||
maxReconnectAttempts = 0,
|
||||
onOpen,
|
||||
onClose,
|
||||
onError,
|
||||
onMessage
|
||||
} = options;
|
||||
|
||||
const [readyState, setReadyState] = useState<number>(WebSocket.CLOSED);
|
||||
const [isConnected, setIsConnected] = useState<boolean>(false);
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
const reconnectAttemptsRef = useRef<number>(0);
|
||||
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const urlRef = useRef<string>('');
|
||||
|
||||
// 清理重连定时器
|
||||
const clearReconnectTimeout = useCallback(() => {
|
||||
if (reconnectTimeoutRef.current) {
|
||||
clearTimeout(reconnectTimeoutRef.current);
|
||||
reconnectTimeoutRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 断开连接
|
||||
const disconnect = useCallback(() => {
|
||||
clearReconnectTimeout();
|
||||
if (wsRef.current) {
|
||||
wsRef.current.close();
|
||||
wsRef.current = null;
|
||||
}
|
||||
setReadyState(WebSocket.CLOSED);
|
||||
setIsConnected(false);
|
||||
}, [clearReconnectTimeout]);
|
||||
|
||||
// 发送消息
|
||||
const sendMessage = useCallback((message: string | object) => {
|
||||
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
|
||||
const messageStr = typeof message === 'string' ? message : JSON.stringify(message);
|
||||
wsRef.current.send(messageStr);
|
||||
} else {
|
||||
console.warn('WebSocket is not connected. Cannot send message.');
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 连接WebSocket
|
||||
const connect = useCallback((url: string) => {
|
||||
// 先断开现有连接
|
||||
disconnect();
|
||||
|
||||
urlRef.current = url;
|
||||
|
||||
try {
|
||||
const ws = new WebSocket(url);
|
||||
wsRef.current = ws;
|
||||
|
||||
ws.onopen = (event) => {
|
||||
setReadyState(WebSocket.OPEN);
|
||||
setIsConnected(true);
|
||||
reconnectAttemptsRef.current = 0;
|
||||
onOpen?.(event);
|
||||
};
|
||||
|
||||
ws.onclose = (event) => {
|
||||
setReadyState(WebSocket.CLOSED);
|
||||
setIsConnected(false);
|
||||
onClose?.(event);
|
||||
|
||||
// 处理重连
|
||||
if (reconnectAttemptsRef.current < maxReconnectAttempts) {
|
||||
reconnectAttemptsRef.current++;
|
||||
reconnectTimeoutRef.current = setTimeout(() => {
|
||||
connect(url);
|
||||
}, reconnectInterval);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = (event) => {
|
||||
setIsConnected(false);
|
||||
onError?.(event);
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
onMessage?.(event);
|
||||
};
|
||||
|
||||
setReadyState(WebSocket.CONNECTING);
|
||||
} catch (error) {
|
||||
console.error('Failed to create WebSocket connection:', error);
|
||||
setIsConnected(false);
|
||||
setReadyState(WebSocket.CLOSED);
|
||||
}
|
||||
}, [disconnect, maxReconnectAttempts, onOpen, onClose, onError, onMessage, reconnectInterval]);
|
||||
|
||||
// 组件卸载时清理
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
disconnect();
|
||||
};
|
||||
}, [disconnect]);
|
||||
|
||||
return {
|
||||
connect,
|
||||
disconnect,
|
||||
sendMessage,
|
||||
readyState,
|
||||
isConnected
|
||||
};
|
||||
};
|
||||
|
||||
export default useWebSocket;
|
||||
Loading…
Reference in New Issue