feat(ckchat): 添加客服在线状态显示和选择功能

- 在KfUserListData接口中添加isOnline字段表示客服在线状态
- 在CkChatState中添加kfSelected字段存储当前选中的客服ID
- 重构VerticalUserList组件,使用zustand管理选中状态
- 添加在线状态指示器样式,区分在线和离线状态
- 优化persistUtils工具,添加分片存储功能处理大数据
This commit is contained in:
超级老白兔
2025-08-29 10:36:37 +08:00
parent bcc2022826
commit 7a4831e200
3 changed files with 39 additions and 31 deletions

View File

@@ -5,33 +5,33 @@
background-color: #2e2e2e;
color: #fff;
width: 60px;
.userListHeader {
padding: 10px 0;
text-align: center;
border-bottom: 1px solid #3a3a3a;
cursor: pointer;
.allFriends {
font-size: 12px;
color: #ccc;
}
}
.userList {
flex: 1;
overflow-y: auto;
padding: 10px 0;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background-color: #555;
border-radius: 2px;
}
}
.userItem {
display: flex;
flex-direction: column;
@@ -40,16 +40,16 @@
padding: 10px 0;
position: relative;
cursor: pointer;
&:hover {
background-color: #3a3a3a;
}
&.active {
background-color: #3a3a3a;
&::before {
content: '';
content: "";
position: absolute;
left: 0;
top: 50%;
@@ -60,15 +60,15 @@
}
}
}
.userAvatar {
border: 2px solid transparent;
.active & {
border-color: #1890ff;
}
}
.messageBadge {
:global(.ant-badge-count) {
background-color: #ff4d4f;
@@ -81,7 +81,7 @@
border-radius: 8px;
}
}
.onlineIndicator {
position: absolute;
bottom: 10px;
@@ -89,7 +89,14 @@
width: 8px;
height: 8px;
border-radius: 50%;
background-color: #52c41a;
border: 1px solid #2e2e2e;
&.online {
background-color: #52c41a; // 绿色表示在线
}
&.offline {
background-color: #8c8c8c; // 灰色表示离线
}
}
}
}

View File

@@ -1,17 +1,10 @@
import React, { useState } from "react";
import { Avatar, Badge, Tooltip } from "antd";
import styles from "./VerticalUserList.module.scss";
import { useCkChatStore } from "@/store/module/ckchat";
interface VerticalUserListProps {
activeKfUserId: number;
onUserSelect: (userId: string) => void;
}
const VerticalUserList: React.FC<VerticalUserListProps> = ({
activeKfUserId,
onUserSelect,
}) => {
const [activeUserId, setActiveUserId] = useState<number>(activeKfUserId);
import { useCkChatStore, asyncKfSelected } from "@/store/module/ckchat";
import { TeamOutlined } from "@ant-design/icons";
const VerticalUserList: React.FC = () => {
// 格式化消息数量显示
const formatMessageCount = (count: number) => {
if (count > 99) return "99+";
@@ -19,21 +12,25 @@ const VerticalUserList: React.FC<VerticalUserListProps> = ({
};
const handleUserSelect = (userId: number) => {
setActiveUserId(userId);
onUserSelect(userId.toString());
asyncKfSelected(userId);
};
const kfUserList = useCkChatStore(state => state.kfUserList);
const kfSelected = useCkChatStore(state => state.kfSelected);
return (
<div className={styles.verticalUserList}>
<div className={styles.userListHeader}>
<div
className={styles.userListHeader}
onClick={() => handleUserSelect(0)}
>
<TeamOutlined style={{ fontSize: "26px" }} />
<div className={styles.allFriends}></div>
</div>
<div className={styles.userList}>
{kfUserList.map(user => (
<Tooltip key={user.id} title={user.name} placement="right">
<div
className={`${styles.userItem} ${activeUserId === user.id ? styles.active : ""}`}
className={`${styles.userItem} ${kfSelected === user.id ? styles.active : ""}`}
onClick={() => handleUserSelect(user.id)}
>
<Badge
@@ -54,7 +51,9 @@ const VerticalUserList: React.FC<VerticalUserListProps> = ({
{!user.avatar && user.name.charAt(0)}
</Avatar>
</Badge>
{user.isOnline && <div className={styles.onlineIndicator} />}
<div
className={`${styles.onlineIndicator} ${user.isOnline ? styles.online : styles.offline}`}
/>
</div>
</Tooltip>
))}

View File

@@ -23,6 +23,7 @@ export interface KfUserListData {
wechatVersion: string;
labels: string[];
lastUpdateTime: string;
isOnline?: boolean;
[key: string]: any;
}
@@ -71,6 +72,7 @@ export interface CkChatState {
contractList: ContractData[];
chatSessions: any[];
kfUserList: KfUserListData[];
kfSelected: number;
newContractList: { groupName: string; contacts: any[] }[];
getkfUserList: () => KfUserListData[];
asyncKfUserList: (data: KfUserListData[]) => void;