Files
cunkebao_v3/Cunkebao/src/components/WebSocketExample.tsx
超级老白兔 20658c3ca5 refactor(websocket): 重构websocket模块并添加消息管理器
- 将websocket模块拆分为多个文件,提高代码可维护性
- 新增msgManage.ts处理不同类型的websocket消息
- 优化消息处理逻辑,减少重复代码
- 更新相关文件引用路径
2025-09-02 09:52:38 +08:00

252 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from "react";
import { Button, Card, List, Badge, Toast } from "antd-mobile";
import {
useWebSocketStore,
WebSocketStatus,
WebSocketMessage,
} from "@/store/module/websocket/websocket";
/**
* WebSocket使用示例组件
* 展示如何使用WebSocket store进行消息收发
*/
const WebSocketExample: React.FC = () => {
const [messageInput, setMessageInput] = useState("");
// 使用WebSocket store
const {
status,
messages,
unreadCount,
connect,
disconnect,
sendMessage,
sendCommand,
clearMessages,
markAsRead,
reconnect,
} = useWebSocketStore();
// 连接状态显示
const getStatusText = () => {
switch (status) {
case WebSocketStatus.DISCONNECTED:
return "未连接";
case WebSocketStatus.CONNECTING:
return "连接中...";
case WebSocketStatus.CONNECTED:
return "已连接";
case WebSocketStatus.RECONNECTING:
return "重连中...";
case WebSocketStatus.ERROR:
return "连接错误";
default:
return "未知状态";
}
};
// 获取状态颜色
const getStatusColor = () => {
switch (status) {
case WebSocketStatus.CONNECTED:
return "success";
case WebSocketStatus.CONNECTING:
case WebSocketStatus.RECONNECTING:
return "warning";
case WebSocketStatus.ERROR:
return "danger";
default:
return "default";
}
};
// 发送消息
const handleSendMessage = () => {
if (!messageInput.trim()) {
Toast.show({ content: "请输入消息内容", position: "top" });
return;
}
sendMessage({
type: "chat",
content: {
text: messageInput,
timestamp: Date.now(),
},
sender: "user",
receiver: "all",
});
setMessageInput("");
};
// 发送命令
const handleSendCommand = (cmdType: string) => {
sendCommand(cmdType, {
data: "示例数据",
timestamp: Date.now(),
});
};
// 格式化时间
const formatTime = (timestamp: number) => {
return new Date(timestamp).toLocaleTimeString();
};
return (
<div style={{ padding: "16px" }}>
<Card title="WebSocket 连接状态">
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<Badge color={getStatusColor()}>
<div style={{ width: "8px", height: "8px", borderRadius: "50%" }} />
</Badge>
<span>{getStatusText()}</span>
</div>
<div
style={{
marginTop: "16px",
display: "flex",
gap: "8px",
flexWrap: "wrap",
}}
>
<Button
size="small"
color="primary"
onClick={() =>
connect({
url: "wss://kf.quwanzhi.com:9993", // 显式指定WebSocket URL确保使用正确的服务器地址
client: "kefu-client",
autoReconnect: true,
})
}
disabled={
status === WebSocketStatus.CONNECTING ||
status === WebSocketStatus.CONNECTED
}
>
</Button>
<Button
size="small"
color="danger"
onClick={disconnect}
disabled={status === WebSocketStatus.DISCONNECTED}
>
</Button>
<Button
size="small"
color="warning"
onClick={reconnect}
disabled={status === WebSocketStatus.CONNECTED}
>
</Button>
</div>
</Card>
<Card
title={`消息列表 ${unreadCount > 0 ? `(${unreadCount} 条未读)` : ""}`}
extra={
<div style={{ display: "flex", gap: "8px" }}>
<Button size="small" onClick={markAsRead}>
</Button>
<Button size="small" onClick={clearMessages}>
</Button>
</div>
}
style={{ marginTop: "16px" }}
>
<List style={{ maxHeight: "300px", overflowY: "auto" }}>
{messages.length === 0 ? (
<List.Item></List.Item>
) : (
messages.map((message: WebSocketMessage) => (
<List.Item key={message.id}>
<div style={{ fontSize: "12px", color: "#666" }}>
{formatTime(message.timestamp)} - {message.type}
</div>
<div style={{ marginTop: "4px" }}>
{typeof message.content === "string"
? message.content
: JSON.stringify(message.content, null, 2)}
</div>
</List.Item>
))
)}
</List>
</Card>
<Card title="发送消息" style={{ marginTop: "16px" }}>
<div style={{ display: "flex", gap: "8px", marginBottom: "12px" }}>
<input
type="text"
value={messageInput}
onChange={e => setMessageInput(e.target.value)}
placeholder="输入消息内容"
style={{
flex: 1,
padding: "8px 12px",
border: "1px solid #d9d9d9",
borderRadius: "4px",
fontSize: "14px",
}}
onKeyPress={e => e.key === "Enter" && handleSendMessage()}
/>
<Button
color="primary"
onClick={handleSendMessage}
disabled={status !== WebSocketStatus.CONNECTED}
>
</Button>
</div>
<div style={{ display: "flex", gap: "8px", flexWrap: "wrap" }}>
<Button
size="small"
onClick={() => handleSendCommand("CmdHeartbeat")}
disabled={status !== WebSocketStatus.CONNECTED}
>
</Button>
<Button
size="small"
onClick={() => handleSendCommand("CmdGetStatus")}
disabled={status !== WebSocketStatus.CONNECTED}
>
</Button>
<Button
size="small"
onClick={() => handleSendCommand("CmdSignIn")}
disabled={status !== WebSocketStatus.CONNECTED}
>
</Button>
</div>
</Card>
<Card title="使用说明" style={{ marginTop: "16px" }}>
<div style={{ fontSize: "14px", lineHeight: "1.6", color: "#666" }}>
<p>1. "连接"WebSocket连接</p>
<p>2. </p>
<p>3. </p>
<p>4. </p>
<p>5. </p>
</div>
</Card>
</div>
);
};
export default WebSocketExample;