From 1e16e30681860ed3dc828a67ec2ec7cb219befe9 Mon Sep 17 00:00:00 2001 From: MatrixSeven Date: Fri, 19 Sep 2025 18:19:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=B9=E8=BF=9B=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=A3=80=E6=9F=A5=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6=E4=BC=A0=E8=BE=93=E5=92=8C?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=96=87=E4=BB=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chuan-next/build-static.sh | 0 .../src/components/ConnectionStatus.tsx | 34 +++-- .../file-transfer/useFileTransferBusiness.ts | 137 +++++++++++------- chuan-next/src/lib/config.ts | 2 +- 4 files changed, 106 insertions(+), 67 deletions(-) mode change 100644 => 100755 chuan-next/build-static.sh diff --git a/chuan-next/build-static.sh b/chuan-next/build-static.sh old mode 100644 new mode 100755 diff --git a/chuan-next/src/components/ConnectionStatus.tsx b/chuan-next/src/components/ConnectionStatus.tsx index c9cc4f5..fb2ff24 100644 --- a/chuan-next/src/components/ConnectionStatus.tsx +++ b/chuan-next/src/components/ConnectionStatus.tsx @@ -15,16 +15,23 @@ interface ConnectionStatusProps { } // 连接状态枚举 -const getConnectionStatus = (currentRoom: { code: string; role: Role } | null) => { - - const { getConnectState } = useReadConnectState(); // 确保状态管理器被初始化 - const connection = getConnectState(); - const isWebSocketConnected = connection?.isWebSocketConnected || false; - const isPeerConnected = connection?.isPeerConnected || false; - const isConnecting = connection?.isConnecting || false; - const error = connection?.error || null; - const currentConnectType = connection?.currentConnectType || 'webrtc'; - const isJoinedRoom = connection?.isJoinedRoom || false; +const getConnectionStatus = ( + currentRoom: { code: string; role: Role } | null, + connection: { + isWebSocketConnected: boolean; + isPeerConnected: boolean; + isConnecting: boolean; + error: string | null; + currentConnectType: 'webrtc' | 'websocket'; + isJoinedRoom: boolean; + } +) => { + const isWebSocketConnected = connection.isWebSocketConnected; + const isPeerConnected = connection.isPeerConnected; + const isConnecting = connection.isConnecting; + const error = connection.error; + const currentConnectType = connection.currentConnectType; + const isJoinedRoom = connection.isJoinedRoom; if (!currentRoom) { return { @@ -198,6 +205,10 @@ export function ConnectionStatus(props: ConnectionStatusProps) { // 使用全局WebRTC状态 const webrtcState = useWebRTCStore(); + // 获取连接状态 + const { getConnectState } = useReadConnectState(); + const connectionState = getConnectState(); + // 创建connection对象以兼容现有代码 const connection = { isWebSocketConnected: webrtcState.isWebSocketConnected, @@ -205,6 +216,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) { isConnecting: webrtcState.isConnecting, error: webrtcState.error, currentConnectType: webrtcState.currentConnectType, + isJoinedRoom: connectionState?.isJoinedRoom || false, }; const isConnected = webrtcState.isWebSocketConnected && webrtcState.isPeerConnected; @@ -214,7 +226,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) { return {getConnectionStatusText(connection)}; } - const status = getConnectionStatus(currentRoom ?? null); + const status = getConnectionStatus(currentRoom ?? null, connection); if (compact) { return ( diff --git a/chuan-next/src/hooks/file-transfer/useFileTransferBusiness.ts b/chuan-next/src/hooks/file-transfer/useFileTransferBusiness.ts index d9b594c..f68e6a4 100644 --- a/chuan-next/src/hooks/file-transfer/useFileTransferBusiness.ts +++ b/chuan-next/src/hooks/file-transfer/useFileTransferBusiness.ts @@ -385,19 +385,26 @@ export function useFileTransferBusiness(connection: IWebConnection) { retryCount = 0 ): Promise => { return new Promise((resolve) => { - // 主要检查数据通道状态,因为数据通道是文件传输的实际通道 + // 改进数据传输前的连接状态检查 const channelState = connection.getConnectState(); - if (channelState.state === 'closed') { - console.warn(`数据通道已关闭,停止发送文件块 ${chunkIndex}`); + const isChannelUsable = + channelState.state === 'open' || + channelState.isDataChannelConnected || + channelState.isPeerConnected || + (channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket'); + + if (!isChannelUsable) { + console.warn(`数据块发送失败,传输通道不可用 ${chunkIndex}:`, { + state: channelState.state, + isDataChannelConnected: channelState.isDataChannelConnected, + isPeerConnected: channelState.isPeerConnected, + isWebSocketConnected: channelState.isWebSocketConnected, + currentConnectType: channelState.currentConnectType + }); resolve(false); return; } - // 如果连接暂时断开但数据通道可用,仍然可以尝试发送 - if (!channelState.isConnected && channelState.state === 'connecting') { - console.warn(`WebRTC 连接暂时断开,但数据通道正在连接,继续尝试发送文件块 ${chunkIndex}`); - } - const chunkKey = `${fileId}-${chunkIndex}`; // 设置确认回调 @@ -443,8 +450,27 @@ export function useFileTransferBusiness(connection: IWebConnection) { // 安全发送文件 const sendFileSecure = useCallback(async (file: File, fileId?: string) => { - if (connection.getConnectState().state !== 'open') { - updateState({ error: '连接未就绪' }); + // 改进连接状态检查 - 使用更全面的连接状态判断 + const connectState = connection.getConnectState(); + const isReadyToSend = + connectState.state === 'open' || // 数据通道已打开 + connectState.isDataChannelConnected || // 数据通道已连接 + connectState.isPeerConnected || // P2P连接已建立 + (connectState.isWebSocketConnected && connectState.currentConnectType === 'websocket'); // WebSocket降级模式 + + console.log('发送文件前连接状态检查:', { + state: connectState.state, + isDataChannelConnected: connectState.isDataChannelConnected, + isPeerConnected: connectState.isPeerConnected, + isWebSocketConnected: connectState.isWebSocketConnected, + currentConnectType: connectState.currentConnectType, + isReadyToSend + }); + + if (!isReadyToSend) { + const errorMsg = `连接未就绪 - 状态: ${connectState.state}, 数据通道: ${connectState.isDataChannelConnected}, P2P: ${connectState.isPeerConnected}, WebSocket: ${connectState.isWebSocketConnected}`; + console.error(errorMsg); + updateState({ error: errorMsg }); return; } @@ -488,16 +514,23 @@ export function useFileTransferBusiness(connection: IWebConnection) { let retryCount = 0; while (!success && retryCount <= MAX_RETRIES) { - // 检查数据通道状态,这是文件传输的实际通道 + // 改进传输过程中的连接状态检查 const channelState = connection.getConnectState(); - if (channelState.state === 'closed') { - console.warn(`数据通道已关闭,停止文件传输`); - throw new Error('数据通道已关闭'); - } + const isChannelUsable = + channelState.state === 'open' || + channelState.isDataChannelConnected || + channelState.isPeerConnected || + (channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket'); - // 如果连接暂时断开但数据通道可用,仍然可以尝试发送 - if (!connection.getConnectState().isConnected && channelState.state === 'connecting') { - console.warn(`WebRTC 连接暂时断开,但数据通道正在连接,继续尝试发送文件块 ${chunkIndex}`); + if (!isChannelUsable) { + console.warn(`数据传输通道不可用,停止文件传输:`, { + state: channelState.state, + isDataChannelConnected: channelState.isDataChannelConnected, + isPeerConnected: channelState.isPeerConnected, + isWebSocketConnected: channelState.isWebSocketConnected, + currentConnectType: channelState.currentConnectType + }); + throw new Error('数据传输通道不可用'); } const start = chunkIndex * chunkSize; @@ -596,26 +629,26 @@ export function useFileTransferBusiness(connection: IWebConnection) { // 发送文件列表 const sendFileList = useCallback((fileList: FileInfo[]) => { - // 检查连接状态 - 优先检查数据通道状态,因为 P2P 连接可能已经建立但状态未及时更新 + // 改进连接状态检查逻辑 const channelState = connection.getConnectState(); - const peerConnected = channelState.isPeerConnected; - const dataChannelConnected = channelState.isDataChannelConnected; - const channelReadyState = channelState.state; + const isReadyToSend = + channelState.state === 'open' || + channelState.isDataChannelConnected || + channelState.isPeerConnected || + (channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket') || + channelState.isConnected; console.log('发送文件列表检查:', { - channelState, - peerConnected, - dataChannelConnected, - channelReadyState, + state: channelState.state, + isDataChannelConnected: channelState.isDataChannelConnected, + isPeerConnected: channelState.isPeerConnected, + isWebSocketConnected: channelState.isWebSocketConnected, + currentConnectType: channelState.currentConnectType, + isConnected: channelState.isConnected, + isReadyToSend, fileListLength: fileList.length }); - // 使用更宽松的条件检查连接状态 - const isReadyToSend = channelReadyState === 'open' || - dataChannelConnected || - peerConnected || - channelState.isConnected; - if (isReadyToSend) { console.log('发送文件列表:', fileList.map(f => f.name)); @@ -629,42 +662,36 @@ export function useFileTransferBusiness(connection: IWebConnection) { // 不立即重试,让上层逻辑处理重试 } } else { - console.log('连接未就绪,等待连接后再发送文件列表:', { - channelReadyState, - dataChannelConnected, - peerConnected, - isConnected: channelState.isConnected - }); + console.log('连接未就绪,等待连接后再发送文件列表'); } }, [connection]); // 请求文件 const requestFile = useCallback((fileId: string, fileName: string) => { const channelState = connection.getConnectState(); - const isChannelOpen = channelState.state === 'open'; - const isDataChannelConnected = channelState.isDataChannelConnected; - const isPeerConnected = channelState.isPeerConnected; - const isConnected = channelState.isConnected; + + // 统一的连接状态检查逻辑 + const isReadyToRequest = + channelState.state === 'open' || + channelState.isDataChannelConnected || + channelState.isPeerConnected || + (channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket') || + channelState.isConnected; console.log('请求文件前检查连接状态:', { fileName, fileId, - isChannelOpen, - isDataChannelConnected, - isPeerConnected, - isConnected + state: channelState.state, + isDataChannelConnected: channelState.isDataChannelConnected, + isPeerConnected: channelState.isPeerConnected, + isWebSocketConnected: channelState.isWebSocketConnected, + currentConnectType: channelState.currentConnectType, + isConnected: channelState.isConnected, + isReadyToRequest }); - // 使用更宽松的条件检查连接状态 - const isReadyToRequest = isChannelOpen || isDataChannelConnected || isPeerConnected || isConnected; - if (!isReadyToRequest) { - console.error('数据通道未准备就绪,无法请求文件:', { - isChannelOpen, - isDataChannelConnected, - isPeerConnected, - isConnected - }); + console.error('数据通道未准备就绪,无法请求文件'); return; } diff --git a/chuan-next/src/lib/config.ts b/chuan-next/src/lib/config.ts index 81b94dc..c58561b 100644 --- a/chuan-next/src/lib/config.ts +++ b/chuan-next/src/lib/config.ts @@ -26,7 +26,7 @@ const getCurrentBaseUrl = () => { // 动态获取 WebSocket URL - 总是在客户端运行时计算 const getCurrentWsUrl = () => { - return "ws://192.168.1.120:8080" + // return "ws://192.168.1.120:8080" if (typeof window !== 'undefined') { // 检查是否是 Next.js 开发服务器(端口 3000 或 3001) const isNextDevServer = window.location.hostname === 'localhost' &&