refactor(websocket): 将客服状态查询定时器逻辑移至websocket store

将原本在组件中的客服状态查询定时器逻辑重构到websocket store中,统一管理定时器的启动和停止。同时在连接成功时自动启动定时器,断开连接时自动停止,避免内存泄漏。
This commit is contained in:
超级老白兔
2025-09-03 09:52:58 +08:00
parent eb63dc1d8d
commit 0d6ac88dea
2 changed files with 57 additions and 15 deletions

View File

@@ -16,8 +16,6 @@ import {
weChatGroup,
ContractData,
} from "@/pages/pc/ckbox/data";
import { useWebSocketStore } from "@/store/module/websocket/websocket";
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
const CkboxPage: React.FC = () => {
const [messageApi, contextHolder] = message.useMessage();
@@ -25,22 +23,9 @@ const CkboxPage: React.FC = () => {
const [currentChat, setCurrentChat] = useState<ContractData | weChatGroup>(
null,
);
const status = useWebSocketStore(state => state.status);
// 不要在组件初始化时获取sendCommand而是在需要时动态获取
const [loading, setLoading] = useState(false);
const [showProfile, setShowProfile] = useState(true);
const kfUserList = useCkChatStore(state => state.kfUserList);
const { sendCommand } = useWebSocketStore.getState();
useEffect(() => {
if (status == "connected" && kfUserList.length > 0) {
//查询客服用户激活状态
setInterval(() => {
sendCommand("CmdRequestWechatAccountsAliveStatus", {
wechatAccountIds: kfUserList.map(v => v.id),
});
}, 10 * 1000);
}
}, [status]);
useEffect(() => {
// 方法一:使用 Promise 链式调用处理异步函数

View File

@@ -51,6 +51,7 @@ interface WebSocketState {
// 重连相关
reconnectAttempts: number;
reconnectTimer: NodeJS.Timeout | null;
aliveStatusTimer: NodeJS.Timeout | null; // 客服用户状态查询定时器
// 方法
connect: (config: Partial<WebSocketConfig>) => void;
@@ -68,6 +69,8 @@ interface WebSocketState {
_handleError: (event: Event) => void;
_startReconnectTimer: () => void;
_stopReconnectTimer: () => void;
_startAliveStatusTimer: () => void; // 启动客服状态查询定时器
_stopAliveStatusTimer: () => void; // 停止客服状态查询定时器
}
// 默认配置
@@ -92,6 +95,7 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
unreadCount: 0,
reconnectAttempts: 0,
reconnectTimer: null,
aliveStatusTimer: null,
// 连接WebSocket
connect: (config: Partial<WebSocketConfig>) => {
@@ -183,6 +187,7 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
}
currentState._stopReconnectTimer();
currentState._stopAliveStatusTimer();
set({
status: WebSocketStatus.DISCONNECTED,
@@ -291,6 +296,9 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
}
Toast.show({ content: "WebSocket连接成功", position: "top" });
// 启动客服状态查询定时器
currentState._startAliveStatusTimer();
},
// 内部方法:处理消息接收
@@ -319,6 +327,9 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
});
}
// 停止客服状态查询定时器
get()._stopAliveStatusTimer();
// 断开连接
get().disconnect();
return;
@@ -414,6 +425,51 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
set({ reconnectTimer: null });
}
},
// 内部方法:启动客服状态查询定时器
_startAliveStatusTimer: () => {
const currentState = get();
// 先停止现有定时器
currentState._stopAliveStatusTimer();
// 获取客服用户列表
const { kfUserList } = useCkChatStore.getState();
// 如果没有客服用户,不启动定时器
if (!kfUserList || kfUserList.length === 0) {
return;
}
// 启动定时器每5秒查询一次
const timer = setInterval(() => {
const state = get();
// 检查连接状态
if (state.status === WebSocketStatus.CONNECTED) {
const { kfUserList: currentKfUserList } = useCkChatStore.getState();
if (currentKfUserList && currentKfUserList.length > 0) {
state.sendCommand("CmdRequestWechatAccountsAliveStatus", {
wechatAccountIds: currentKfUserList.map(v => v.id),
});
}
} else {
// 如果连接断开,停止定时器
state._stopAliveStatusTimer();
}
}, 5000);
set({ aliveStatusTimer: timer });
},
// 内部方法:停止客服状态查询定时器
_stopAliveStatusTimer: () => {
const currentState = get();
if (currentState.aliveStatusTimer) {
clearInterval(currentState.aliveStatusTimer);
set({ aliveStatusTimer: null });
}
},
}),
{
name: "websocket-store",
@@ -424,6 +480,7 @@ export const useWebSocketStore = createPersistStore<WebSocketState>(
messages: state.messages.slice(-100), // 只保留最近100条消息
unreadCount: state.unreadCount,
reconnectAttempts: state.reconnectAttempts,
// 注意:定时器不需要持久化,重新连接时会重新创建
}),
onRehydrateStorage: () => state => {
// 页面刷新后,如果之前是连接状态,尝试重新连接