diff --git a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/index.tsx b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/index.tsx index 087029ff..c4473c64 100644 --- a/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/index.tsx +++ b/Cunkebao/src/pages/pc/ckbox/components/ChatWindow/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef } from "react"; +import React, { useEffect, useRef } from "react"; import { Layout, Button, Avatar, Space, Dropdown, Menu, Tooltip } from "antd"; import { PhoneOutlined, @@ -18,10 +18,7 @@ import { } from "@ant-design/icons"; import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; import styles from "./ChatWindow.module.scss"; -import { - useWebSocketStore, - WebSocketMessage, -} from "@/store/module/websocket/websocket"; +import { useWebSocketStore } from "@/store/module/websocket/websocket"; import { formatWechatTime } from "@/utils/common"; import Person from "./components/Person"; import MessageEnter from "./components/MessageEnter"; @@ -39,18 +36,13 @@ const ChatWindow: React.FC = ({ showProfile = true, onToggleProfile, }) => { - const [messages, setMessages] = useState([]); - const [loading, setLoading] = useState(false); - const [pendingVideoRequests, setPendingVideoRequests] = useState< - Record - >({}); const messagesEndRef = useRef(null); const currentMessages = useWeChatStore(state => state.currentMessages); useEffect(() => { // 只有在非视频加载操作时才自动滚动到底部 // 检查是否有视频正在加载中 - const hasLoadingVideo = messages.some(msg => { + const hasLoadingVideo = currentMessages.some(msg => { try { const content = typeof msg.content === "string" @@ -65,78 +57,13 @@ const ChatWindow: React.FC = ({ if (!hasLoadingVideo) { scrollToBottom(); } - }, [messages]); + }, [currentMessages]); - // 添加 WebSocket 消息订阅 - 监听视频下载响应消息 + // 初始化WebSocket监听 useEffect(() => { - // 只有当有待处理的视频请求时才订阅WebSocket消息 - if (Object.keys(pendingVideoRequests).length === 0) { - return; - } - - console.log("开始监听视频下载响应,当前待处理请求:", pendingVideoRequests); - - // 订阅 WebSocket 消息变化 - const unsubscribe = useWebSocketStore.subscribe(state => { - // 只处理新增的消息 - const messages = state.messages as WebSocketMessage[]; - - // 筛选出视频下载响应消息 - messages.forEach(message => { - if (message?.content?.cmdType === "CmdDownloadVideoResult") { - console.log("收到视频下载响应:", message.content); - - // 检查是否是我们正在等待的视频响应 - const messageId = Object.keys(pendingVideoRequests).find( - id => pendingVideoRequests[id] === message.content.friendMessageId, - ); - - if (messageId) { - console.log("找到对应的消息ID:", messageId); - - // 从待处理队列中移除 - setPendingVideoRequests(prev => { - const newRequests = { ...prev }; - delete newRequests[messageId]; - return newRequests; - }); - - // 更新消息内容,将视频URL添加到对应的消息中 - setMessages(prevMessages => { - return prevMessages.map(msg => { - if (msg.id === Number(messageId)) { - try { - const msgContent = - typeof msg.content === "string" - ? JSON.parse(msg.content) - : msg.content; - - // 更新消息内容,添加视频URL并移除加载状态 - return { - ...msg, - content: JSON.stringify({ - ...msgContent, - videoUrl: message.content.url, - isLoading: false, - }), - }; - } catch (e) { - console.error("解析消息内容失败:", e); - } - } - return msg; - }); - }); - } - } - }); - }); - - // 组件卸载时取消订阅 - return () => { - unsubscribe(); - }; - }, [pendingVideoRequests]); // 依赖于pendingVideoRequests,当队列变化时重新设置订阅 + const unsubscribe = useWeChatStore.getState().initWebSocketListener(); + return unsubscribe; + }, []); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); @@ -157,29 +84,13 @@ const ChatWindow: React.FC = ({ wechatAccountId: contract.wechatAccountId, }); - // 将消息ID和请求序列号添加到待处理队列 - setPendingVideoRequests(prev => ({ - ...prev, - [messageId]: messageId, - })); + // 将消息ID添加到待处理队列 + useWeChatStore + .getState() + .addPendingVideoRequest(messageId.toString(), messageId.toString()); // 更新消息状态为加载中 - setMessages(prevMessages => { - return prevMessages.map(msg => { - if (msg.id === messageId) { - // 保存原始内容,添加loading状态 - const originalContent = msg.content; - return { - ...msg, - content: JSON.stringify({ - ...JSON.parse(originalContent), - isLoading: true, - }), - }; - } - return msg; - }); - }); + useWeChatStore.getState().setMessageLoading(messageId.toString(), true); }; // 解析消息内容,判断消息类型并返回对应的渲染内容 @@ -613,14 +524,10 @@ const ChatWindow: React.FC = ({ // 用于分组消息并添加时间戳的辅助函数 const groupMessagesByTime = (messages: ChatRecord[]) => { - const groups: { time: string; messages: ChatRecord[] }[] = []; - messages.forEach(msg => { - // 使用 formatWechatTime 函数格式化时间戳 - const formattedTime = formatWechatTime(msg.wechatTime); - groups.push({ time: formattedTime, messages: [msg] }); - }); - - return groups; + return messages.map(msg => ({ + time: formatWechatTime(msg.wechatTime), + messages: [msg], + })); }; const renderMessage = (msg: ChatRecord) => { @@ -721,21 +628,13 @@ const ChatWindow: React.FC = ({ {/* 聊天内容 */}
- {loading ? ( -
-
加载中...
-
- ) : ( - <> - {groupMessagesByTime(messages).map((group, groupIndex) => ( - -
{group.time}
- {group.messages.map(renderMessage)} -
- ))} -
- - )} + {groupMessagesByTime(currentMessages).map((group, groupIndex) => ( + +
{group.time}
+ {group.messages.map(renderMessage)} +
+ ))} +
diff --git a/Cunkebao/src/store/module/weChat/weChat.data.ts b/Cunkebao/src/store/module/weChat/weChat.data.ts index 3bd851eb..955ce031 100644 --- a/Cunkebao/src/store/module/weChat/weChat.data.ts +++ b/Cunkebao/src/store/module/weChat/weChat.data.ts @@ -7,8 +7,22 @@ export interface WeChatState { // 当前聊天用户的消息列表(只存储当前聊天用户的消息) currentMessages: ChatRecord[]; - setCurrentContact: (contract: ContractData | weChatGroup) => void; // 消息加载状态 messagesLoading: boolean; + + // 待处理的视频请求队列 + pendingVideoRequests: Record; + + // Actions + setCurrentContact: (contract: ContractData | weChatGroup) => void; loadChatMessages: (contact: ContractData | weChatGroup) => Promise; + + // 视频请求相关方法 + addPendingVideoRequest: (messageId: string, requestId: string) => void; + removePendingVideoRequest: (messageId: string) => void; + updateMessageWithVideo: (messageId: string, videoUrl: string) => void; + setMessageLoading: (messageId: string, isLoading: boolean) => void; + + // WebSocket监听初始化 + initWebSocketListener: () => void; } diff --git a/Cunkebao/src/store/module/weChat/weChat.ts b/Cunkebao/src/store/module/weChat/weChat.ts index 66ee7818..633969b8 100644 --- a/Cunkebao/src/store/module/weChat/weChat.ts +++ b/Cunkebao/src/store/module/weChat/weChat.ts @@ -5,6 +5,10 @@ import { WeChatState } from "./weChat.data"; import { clearUnreadCount, updateConfig } from "@/pages/pc/ckbox/api"; import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; import { addChatSession } from "@/store/module/ckchat/ckchat"; +import { + useWebSocketStore, + WebSocketMessage, +} from "@/store/module/websocket/websocket"; export const useWeChatStore = create()( persist( (set, get) => ({ @@ -12,6 +16,7 @@ export const useWeChatStore = create()( currentContract: null, currentMessages: [], messagesLoading: false, + pendingVideoRequests: {}, // Actions setCurrentContact: (contract: ContractData | weChatGroup) => { @@ -58,7 +63,7 @@ export const useWeChatStore = create()( }, setMessageLoading: loading => { - set({ messagesLoading: loading }); + set({ messagesLoading: Boolean(loading) }); }, addMessage: message => { @@ -80,11 +85,121 @@ export const useWeChatStore = create()( getCurrentMessages: () => get().currentMessages, getMessagesLoading: () => get().messagesLoading, + // 视频请求相关方法 + addPendingVideoRequest: (messageId: string, requestId: string) => { + set(state => ({ + pendingVideoRequests: { + ...state.pendingVideoRequests, + [messageId]: requestId, + }, + })); + }, + + removePendingVideoRequest: (messageId: string) => { + set(state => { + const newRequests = { ...state.pendingVideoRequests }; + delete newRequests[messageId]; + return { pendingVideoRequests: newRequests }; + }); + }, + + updateMessageWithVideo: (messageId: string, videoUrl: string) => { + set(state => ({ + currentMessages: state.currentMessages.map(msg => { + if (msg.id === Number(messageId)) { + try { + const msgContent = + typeof msg.content === "string" + ? JSON.parse(msg.content) + : msg.content; + return { + ...msg, + content: JSON.stringify({ + ...msgContent, + videoUrl: videoUrl, + isLoading: false, + }), + }; + } catch (e) { + console.error("解析消息内容失败:", e); + } + } + return msg; + }), + })); + }, + + setMessageLoadingStatus: (messageId: string, isLoading: boolean) => { + set(state => ({ + currentMessages: state.currentMessages.map(msg => { + if (msg.id === Number(messageId)) { + try { + const originalContent = msg.content; + return { + ...msg, + content: JSON.stringify({ + ...JSON.parse(originalContent), + isLoading: isLoading, + }), + }; + } catch (e) { + console.error("解析消息内容失败:", e); + } + } + return msg; + }), + })); + }, + + // WebSocket监听初始化 + initWebSocketListener: () => { + const unsubscribe = useWebSocketStore.subscribe(state => { + const messages = state.messages as WebSocketMessage[]; + const currentState = get(); + + // 只有当有待处理的视频请求时才处理 + if (Object.keys(currentState.pendingVideoRequests).length === 0) { + return; + } + + messages.forEach(message => { + if (message?.content?.cmdType === "CmdDownloadVideoResult") { + console.log("收到视频下载响应:", message.content); + + // 检查是否是我们正在等待的视频响应 + const messageId = Object.keys( + currentState.pendingVideoRequests, + ).find( + id => + currentState.pendingVideoRequests[id] === + message.content.friendMessageId, + ); + + if (messageId) { + console.log("找到对应的消息ID:", messageId); + + // 从待处理队列中移除 + currentState.removePendingVideoRequest(messageId); + + // 更新消息内容,添加视频URL + currentState.updateMessageWithVideo( + messageId, + message.content.url, + ); + } + } + }); + }); + + return unsubscribe; + }, + clearAllData: () => { set({ currentContract: null, currentMessages: [], messagesLoading: false, + pendingVideoRequests: {}, }); }, }),