新增 VITE_API_WS_URL 環境變數,更新主程式以引入嚴格模式包裝器,並在登錄頁面中整合觸客寶用戶信息獲取功能,調整請求模組以動態獲取 token2。

This commit is contained in:
超级老白兔
2025-08-18 11:30:56 +08:00
parent 7dd20b0a9b
commit 1b1bd7536d
11 changed files with 825 additions and 11 deletions

View File

@@ -0,0 +1,250 @@
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 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({
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;