refactor(ckbox): 重构客服列表和联系人管理逻辑
- 将ctrlUserList重命名为kfUserList并优化相关接口 - 新增异步更新客服列表、联系人列表和会话列表的方法 - 重构联系人分组逻辑,支持按标签分组 - 优化会话列表排序规则,按最后更新时间降序排列 - 移除无用代码并简化组件逻辑
This commit is contained in:
@@ -23,7 +23,7 @@ export interface FormData {
|
||||
name: string;
|
||||
startTime: string; // 允许推送的开始时间
|
||||
endTime: string; // 允许推送的结束时间
|
||||
maxPerDay: number;
|
||||
dailyPushCount: number;
|
||||
pushOrder: number; // 1: 按最早, 2: 按最新
|
||||
isLoop: number; // 0: 否, 1: 是
|
||||
pushType: number; // 0: 定时推送, 1: 立即推送
|
||||
|
||||
@@ -14,6 +14,10 @@ import {
|
||||
//读取聊天信息
|
||||
//kf.quwanzhi.com:9991/api/WechatFriend/clearUnreadCount
|
||||
|
||||
export function WechatGroup(params) {
|
||||
return request("/api/WechatGroup/list", params, "GET");
|
||||
}
|
||||
|
||||
//获取聊天记录-1 清除未读
|
||||
export function clearUnreadCount(params) {
|
||||
return request("/api/WechatFriend/clearUnreadCount", params, "PUT");
|
||||
@@ -30,7 +34,7 @@ export function getMessages(params: {
|
||||
return request("/api/FriendMessage/SearchMessage", params, "GET");
|
||||
}
|
||||
//获取群列表
|
||||
export function getChatRoomList(params: { prevId: number; count: number }) {
|
||||
export function getGroupList(params: { prevId: number; count: number }) {
|
||||
return request(
|
||||
"/api/wechatChatroom/listExcludeMembersByPage?",
|
||||
params,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { UserOutlined, TeamOutlined } from "@ant-design/icons";
|
||||
import dayjs from "dayjs";
|
||||
import { ContractData, GroupData } from "@/pages/pc/ckbox/data";
|
||||
import styles from "./MessageList.module.scss";
|
||||
|
||||
import { formatWechatTime } from "@/utils/common";
|
||||
interface MessageListProps {
|
||||
chatSessions: ContractData[];
|
||||
currentChat: ContractData;
|
||||
@@ -16,22 +16,6 @@ const MessageList: React.FC<MessageListProps> = ({
|
||||
currentChat,
|
||||
onChatSelect,
|
||||
}) => {
|
||||
const formatTime = (timestamp: string) => {
|
||||
const now = dayjs();
|
||||
const messageTime = dayjs(timestamp);
|
||||
const diffDays = now.diff(messageTime, "day");
|
||||
|
||||
if (diffDays === 0) {
|
||||
return messageTime.format("HH:mm");
|
||||
} else if (diffDays === 1) {
|
||||
return "昨天";
|
||||
} else if (diffDays < 7) {
|
||||
return messageTime.format("ddd");
|
||||
} else {
|
||||
return messageTime.format("MM-DD");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.messageList}>
|
||||
<List
|
||||
@@ -47,7 +31,7 @@ const MessageList: React.FC<MessageListProps> = ({
|
||||
<Badge count={session.unreadCount} size="small">
|
||||
<Avatar
|
||||
size={48}
|
||||
src={session.avatar}
|
||||
src={session.avatar || session.chatroomAvatar}
|
||||
icon={
|
||||
session?.type === "group" ? (
|
||||
<TeamOutlined />
|
||||
@@ -61,7 +45,7 @@ const MessageList: React.FC<MessageListProps> = ({
|
||||
<div className={styles.messageHeader}>
|
||||
<div className={styles.messageName}>{session.nickname}</div>
|
||||
<div className={styles.messageTime}>
|
||||
{formatTime(session?.lastTime || "")}
|
||||
{formatWechatTime(session?.lastUpdateTime)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.messageContent}>
|
||||
|
||||
@@ -31,7 +31,7 @@ const SidebarMenu: React.FC<SidebarMenuProps> = ({
|
||||
const chatSessions = getChatSessions();
|
||||
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const [activeTab, setActiveTab] = useState("contracts");
|
||||
const [activeTab, setActiveTab] = useState("chats");
|
||||
|
||||
const handleSearch = (value: string) => {
|
||||
setSearchText(value);
|
||||
|
||||
@@ -1,29 +1,17 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Avatar, Badge, Tooltip } from "antd";
|
||||
import styles from "./VerticalUserList.module.scss";
|
||||
import { CkChatCtrlUserData } from "@/store/module/ckchat.data";
|
||||
interface UserItem {
|
||||
id: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
messageCount?: number;
|
||||
isOnline?: boolean;
|
||||
}
|
||||
|
||||
import { useCkChatStore } from "@/store/module/ckchat";
|
||||
interface VerticalUserListProps {
|
||||
activeKfUserId: number;
|
||||
onUserSelect: (userId: string) => void;
|
||||
}
|
||||
import { getCtrlUserList, useCkChatStore } from "@/store/module/ckchat";
|
||||
const VerticalUserList: React.FC<VerticalUserListProps> = ({
|
||||
activeKfUserId,
|
||||
onUserSelect,
|
||||
}) => {
|
||||
// 直接从store获取ctrlUserList,这样当store中的数据更新时,组件会自动重新渲染
|
||||
const ctrlUserList = useCkChatStore(state => state.ctrlUserList);
|
||||
const [activeUserId, setActiveUserId] = useState<number>();
|
||||
const [activeUserId, setActiveUserId] = useState<number>(activeKfUserId);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("控制终端用户列表更新:", ctrlUserList);
|
||||
}, [ctrlUserList]);
|
||||
// 格式化消息数量显示
|
||||
const formatMessageCount = (count: number) => {
|
||||
if (count > 99) return "99+";
|
||||
@@ -34,6 +22,7 @@ const VerticalUserList: React.FC<VerticalUserListProps> = ({
|
||||
setActiveUserId(userId);
|
||||
onUserSelect(userId.toString());
|
||||
};
|
||||
const kfUserList = useCkChatStore(state => state.kfUserList);
|
||||
|
||||
return (
|
||||
<div className={styles.verticalUserList}>
|
||||
@@ -41,7 +30,7 @@ const VerticalUserList: React.FC<VerticalUserListProps> = ({
|
||||
<div className={styles.allFriends}>全部好友</div>
|
||||
</div>
|
||||
<div className={styles.userList}>
|
||||
{ctrlUserList.map(user => (
|
||||
{kfUserList.map(user => (
|
||||
<Tooltip key={user.id} title={user.name} placement="right">
|
||||
<div
|
||||
className={`${styles.userItem} ${activeUserId === user.id ? styles.active : ""}`}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Layout, Button, Space, message, Tooltip } from "antd";
|
||||
import { Layout, Button, Space, message, Tooltip, Spin } from "antd";
|
||||
import { InfoCircleOutlined, MessageOutlined } from "@ant-design/icons";
|
||||
import dayjs from "dayjs";
|
||||
import { ContractData } from "./data";
|
||||
@@ -10,63 +10,12 @@ import styles from "./index.module.scss";
|
||||
import { addChatSession } from "@/store/module/ckchat";
|
||||
const { Header, Content, Sider } = Layout;
|
||||
import { chatInitAPIdata } from "./main";
|
||||
// 垂直侧边栏用户数据
|
||||
const verticalUsers = [
|
||||
{
|
||||
id: "all",
|
||||
name: "全部好友",
|
||||
avatar: "",
|
||||
messageCount: 99,
|
||||
},
|
||||
{
|
||||
id: "game",
|
||||
name: "游戏好友",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
messageCount: 99,
|
||||
},
|
||||
{
|
||||
id: "card",
|
||||
name: "卡片好友",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
messageCount: 99,
|
||||
},
|
||||
{
|
||||
id: "dh",
|
||||
name: "DH好友",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
},
|
||||
{
|
||||
id: "yp",
|
||||
name: "用户多",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
},
|
||||
{
|
||||
id: "dq",
|
||||
name: "当前",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
},
|
||||
{
|
||||
id: "rq",
|
||||
name: "人气榜",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
},
|
||||
{
|
||||
id: "ai",
|
||||
name: "AI助手",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
},
|
||||
{
|
||||
id: "hf",
|
||||
name: "回复号码",
|
||||
avatar: "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png",
|
||||
},
|
||||
];
|
||||
|
||||
const CkboxPage: React.FC = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const [contracts, setContacts] = useState<any[]>([]);
|
||||
const [currentChat, setCurrentChat] = useState<ContractData | null>(null);
|
||||
const [activeVerticalUserId, setActiveVerticalUserId] = useState("all");
|
||||
const [activeVerticalUserId, setActiveVerticalUserId] = useState(0);
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showProfile, setShowProfile] = useState(true);
|
||||
@@ -75,8 +24,8 @@ const CkboxPage: React.FC = () => {
|
||||
// 方法一:使用 Promise 链式调用处理异步函数
|
||||
setLoading(true);
|
||||
chatInitAPIdata()
|
||||
.then((response: { contractList: any[]; chatRoomList: any[] }) => {
|
||||
const { contractList, chatRoomList } = response;
|
||||
.then(response => {
|
||||
const { contractList, chatRoomList, kfUserList } = response;
|
||||
//找出已经在聊天的
|
||||
const isChatList = contractList.filter(
|
||||
v => (v?.config && v.config?.chat) || false,
|
||||
@@ -133,10 +82,10 @@ const CkboxPage: React.FC = () => {
|
||||
<Header className={styles.header}>触客宝</Header>
|
||||
<Layout>
|
||||
{/* 垂直侧边栏 */}
|
||||
|
||||
<Sider width={60} className={styles.verticalSider}>
|
||||
<VerticalUserList
|
||||
users={verticalUsers}
|
||||
activeUserId={activeVerticalUserId}
|
||||
activeKfUserId={activeVerticalUserId}
|
||||
onUserSelect={handleVerticalUserSelect}
|
||||
/>
|
||||
</Sider>
|
||||
@@ -148,7 +97,6 @@ const CkboxPage: React.FC = () => {
|
||||
currentChat={currentChat}
|
||||
onContactClick={handleContactClick}
|
||||
onChatSelect={setCurrentChat}
|
||||
loading={loading}
|
||||
/>
|
||||
</Sider>
|
||||
|
||||
|
||||
@@ -1,62 +1,182 @@
|
||||
import { addCtrlUser, useCkChatStore } from "@/store/module/ckchat";
|
||||
import {
|
||||
useCkChatStore,
|
||||
asyncKfUserList,
|
||||
asyncContractList,
|
||||
asyncChatSessions,
|
||||
} from "@/store/module/ckchat";
|
||||
import { useWebSocketStore } from "@/store/module/websocket";
|
||||
|
||||
import {
|
||||
loginWithToken,
|
||||
getControlTerminalList,
|
||||
getContactList,
|
||||
getChatRoomList,
|
||||
getGroupList,
|
||||
WechatGroup,
|
||||
} from "./api";
|
||||
const { sendCommand } = useWebSocketStore.getState();
|
||||
import { useUserStore } from "@/store/module/user";
|
||||
import { CkChatCtrlUserData } from "@/store/module/ckchat.data";
|
||||
import { KfUserListData } from "@/store/module/ckchat.data";
|
||||
const { login2 } = useUserStore.getState();
|
||||
const { connect } = useWebSocketStore.getState();
|
||||
const { setUserInfo, getAccountId } = useCkChatStore.getState();
|
||||
//获取触客宝基础信息
|
||||
export const chatInitAPIdata = async () => {
|
||||
try {
|
||||
// //发起链接
|
||||
// if (Token && accountId) {
|
||||
// connect({
|
||||
// url: "wss://kf.quwanzhi.com:9993", // 显式指定WebSocket URL,确保使用正确的服务器地址
|
||||
// accessToken: String(Token),
|
||||
// accountId: accountId,
|
||||
// client: "kefu-client",
|
||||
// cmdType: "CmdSignIn",
|
||||
// seq: +new Date(),
|
||||
// });
|
||||
// console.log("WebSocket连接已初始化");
|
||||
// } else {
|
||||
// console.error("WebSocket连接初始化失败:缺少Token或accountId");
|
||||
// }
|
||||
//获取联系人列表
|
||||
const contractList = await getAllContactList();
|
||||
|
||||
//构建联系人列表标签
|
||||
const newContractList = await createContractList(contractList);
|
||||
|
||||
//获取联系人列表
|
||||
asyncContractList(contractList);
|
||||
|
||||
// 提取不重复的wechatAccountId组
|
||||
const uniqueWechatAccountIds: number[] =
|
||||
getUniqueWechatAccountIds(contractList);
|
||||
|
||||
//获取控制终端列表
|
||||
const controlTerminalList: CkChatCtrlUserData[] =
|
||||
const kfUserList: KfUserListData[] =
|
||||
await getControlTerminalListByWechatAccountIds(uniqueWechatAccountIds);
|
||||
|
||||
//添加控制终端用户
|
||||
controlTerminalList.forEach(item => {
|
||||
addCtrlUser(item);
|
||||
});
|
||||
//获取用户列表
|
||||
asyncKfUserList(kfUserList);
|
||||
|
||||
//获取群列表
|
||||
const chatRoomList = await getAllChatRoomList();
|
||||
const groupList = await getAllGroupList();
|
||||
|
||||
//获取消息会话列表并按lastUpdateTime排序
|
||||
const filterUserSessions = contractList?.filter(
|
||||
v => v?.config && v.config?.chat,
|
||||
);
|
||||
const filterGroupSessions = groupList?.filter(
|
||||
v => v?.config && v.config?.chat,
|
||||
);
|
||||
//排序功能
|
||||
const sortedSessions = [...filterUserSessions, ...filterGroupSessions].sort(
|
||||
(a, b) => {
|
||||
// 如果lastUpdateTime不存在,则将其排在最后
|
||||
if (!a.lastUpdateTime) return 1;
|
||||
if (!b.lastUpdateTime) return -1;
|
||||
|
||||
// 首先按时间降序排列(最新的在前面)
|
||||
const timeCompare =
|
||||
new Date(b.lastUpdateTime).getTime() -
|
||||
new Date(a.lastUpdateTime).getTime();
|
||||
|
||||
// 如果时间相同,则按未读消息数量降序排列
|
||||
if (timeCompare === 0) {
|
||||
// 如果unreadCount不存在,则将其排在后面
|
||||
const aUnread = a.unreadCount || 0;
|
||||
const bUnread = b.unreadCount || 0;
|
||||
return bUnread - aUnread; // 未读消息多的排在前面
|
||||
}
|
||||
|
||||
return timeCompare;
|
||||
},
|
||||
);
|
||||
//会话数据同步
|
||||
asyncChatSessions(sortedSessions);
|
||||
|
||||
return {
|
||||
contractList,
|
||||
chatRoomList,
|
||||
groupList,
|
||||
kfUserList,
|
||||
newContractList,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("获取联系人列表失败:", error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
//构建联系人列表标签
|
||||
export const createContractList = async (contractList: any[]) => {
|
||||
const LablesRes = await Promise.all(
|
||||
[1, 2].map(item =>
|
||||
WechatGroup({
|
||||
groupType: item,
|
||||
}),
|
||||
),
|
||||
);
|
||||
const [friend, group] = LablesRes;
|
||||
|
||||
const countLables = [...friend, ...group];
|
||||
|
||||
// 根据countLables中的groupName整理contractList数据
|
||||
// 返回按标签分组的联系人数组,包括未分组标签(在数组最后)
|
||||
return organizeContactsByLabels(contractList, countLables);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据标签组织联系人
|
||||
* @param contractList 联系人列表
|
||||
* @param countLables 标签列表
|
||||
* @returns 按标签分组的联系人
|
||||
*/
|
||||
export const organizeContactsByLabels = (
|
||||
contractList: any[],
|
||||
countLables: any[],
|
||||
) => {
|
||||
// 创建结果对象,用于存储按标签分组的联系人
|
||||
const result: { [key: string]: any[] } = {};
|
||||
|
||||
// 初始化结果对象,为每个标签创建一个空数组
|
||||
countLables.forEach(label => {
|
||||
if (label && label.groupName) {
|
||||
result[label.groupName] = [];
|
||||
}
|
||||
});
|
||||
|
||||
// 创建未分组标签,用于存放没有匹配到任何标签的联系人
|
||||
const ungroupedLabel = "未分组";
|
||||
result[ungroupedLabel] = [];
|
||||
|
||||
// 遍历联系人列表
|
||||
contractList.forEach(contact => {
|
||||
// 确保联系人有labels字段且是数组
|
||||
if (contact && Array.isArray(contact.labels)) {
|
||||
// 标记联系人是否已被分配到某个组
|
||||
let isAssigned = false;
|
||||
|
||||
// 遍历标签列表
|
||||
countLables.forEach(label => {
|
||||
if (label && label.groupName) {
|
||||
// 检查联系人的labels是否包含当前标签的groupName
|
||||
if (contact.labels.includes(label.groupName)) {
|
||||
// 将联系人添加到对应标签的数组中
|
||||
result[label.groupName].push(contact);
|
||||
isAssigned = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 如果联系人没有被分配到任何组,则添加到未分组
|
||||
if (!isAssigned) {
|
||||
result[ungroupedLabel].push(contact);
|
||||
}
|
||||
} else {
|
||||
// 如果联系人没有labels字段或不是数组,也添加到未分组
|
||||
result[ungroupedLabel].push(contact);
|
||||
}
|
||||
});
|
||||
|
||||
// 将结果转换为数组格式,确保未分组在最后
|
||||
const resultArray = Object.entries(result).map(([groupName, contacts]) => ({
|
||||
groupName,
|
||||
contacts,
|
||||
}));
|
||||
|
||||
// 将未分组移到数组末尾
|
||||
const ungroupedIndex = resultArray.findIndex(
|
||||
item => item.groupName === ungroupedLabel,
|
||||
);
|
||||
if (ungroupedIndex !== -1) {
|
||||
const ungrouped = resultArray.splice(ungroupedIndex, 1)[0];
|
||||
resultArray.push(ungrouped);
|
||||
}
|
||||
|
||||
return resultArray;
|
||||
};
|
||||
|
||||
//获取控制终端列表
|
||||
export const getControlTerminalListByWechatAccountIds = (
|
||||
WechatAccountIds: number[],
|
||||
@@ -126,7 +246,7 @@ export const getUniqueWechatAccountIds = contacts => {
|
||||
return Array.from(uniqueAccountIdsSet);
|
||||
};
|
||||
// 递归获取所有群列表
|
||||
export const getAllChatRoomList = async () => {
|
||||
export const getAllGroupList = async () => {
|
||||
try {
|
||||
let allContacts = [];
|
||||
let prevId = 0;
|
||||
@@ -134,7 +254,7 @@ export const getAllChatRoomList = async () => {
|
||||
let hasMore = true;
|
||||
|
||||
while (hasMore) {
|
||||
const contractList = await getChatRoomList({
|
||||
const contractList = await getGroupList({
|
||||
prevId,
|
||||
count,
|
||||
});
|
||||
|
||||
@@ -1,61 +1,27 @@
|
||||
import { ContractData } from "../../pages/pc/ckbox/data";
|
||||
|
||||
//终端用户数据接口
|
||||
export interface CkChatCtrlUserData {
|
||||
/** 用户唯一标识ID */
|
||||
export interface KfUserListData {
|
||||
id: number;
|
||||
/** 租户ID(多租户系统中用于区分租户) */
|
||||
tenantId: number;
|
||||
/** 微信ID(用户微信账号唯一标识) */
|
||||
wechatId: string;
|
||||
/** 用户昵称 */
|
||||
nickname: string;
|
||||
/** 用户别名/备注名(自定义标识) */
|
||||
alias: string;
|
||||
/** 头像图片URL(阿里云OSS存储地址) */
|
||||
avatar: string;
|
||||
/**
|
||||
* 性别标识(0:未知/未设置,1:男,2:女,符合微信性别字段定义)
|
||||
* 原始数据中为0,此处标注可能的枚举值以便后续扩展
|
||||
*/
|
||||
gender: 0 | 1 | 2;
|
||||
/** 地区信息(原始数据为空字符串,未填写) */
|
||||
gender: number;
|
||||
region: string;
|
||||
/** 个性签名(原始数据为空字符串,未填写) */
|
||||
signature: string;
|
||||
/** 绑定的QQ号(0表示未绑定) */
|
||||
bindQQ: string;
|
||||
/** 绑定的邮箱(原始数据为空字符串,未绑定) */
|
||||
bindEmail: string;
|
||||
/** 绑定的手机号(原始数据为空字符串,未绑定) */
|
||||
bindMobile: string;
|
||||
/**
|
||||
* 用户创建时间(注册时间)
|
||||
* 格式:ISO 8601标准时间字符串(YYYY-MM-DDTHH:mm:ss.fffffff)
|
||||
*/
|
||||
createTime: string;
|
||||
/** 当前登录设备ID(关联用户使用的设备唯一标识) */
|
||||
currentDeviceId: number;
|
||||
/** 是否删除(逻辑删除标识,false:未删除,true:已删除) */
|
||||
isDeleted: boolean;
|
||||
/**
|
||||
* 删除时间(逻辑删除时记录,未删除时为默认初始时间"0001-01-01T00:00:00")
|
||||
* 格式:ISO 8601标准时间字符串
|
||||
*/
|
||||
deleteTime: string;
|
||||
/** 用户所属群组ID(用于群组分类管理) */
|
||||
groupId: number;
|
||||
/** 系统内对用户的备注信息(补充标识) */
|
||||
memo: string;
|
||||
/** 用户当前使用的微信版本号 */
|
||||
wechatVersion: string;
|
||||
/**
|
||||
* 用户标签列表(用于分类、筛选,涵盖:业务类型、互动记录、身份标识等维度)
|
||||
* 例如:"团队"(身份)、"未成交"(业务状态)、"抖音"(渠道)等
|
||||
*/
|
||||
labels: string[];
|
||||
/**
|
||||
* 最后更新时间(用户信息最近修改时间)
|
||||
* 格式:ISO 8601标准时间字符串
|
||||
*/
|
||||
lastUpdateTime: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
@@ -102,6 +68,20 @@ export interface CkUserInfo {
|
||||
export interface CkChatState {
|
||||
userInfo: CkUserInfo | null;
|
||||
isLoggedIn: boolean;
|
||||
contractList: ContractData[];
|
||||
chatSessions: any[];
|
||||
kfUserList: KfUserListData[];
|
||||
getkfUserList: () => KfUserListData[];
|
||||
asyncKfUserList: (data: KfUserListData[]) => void;
|
||||
asyncContractList: (data: ContractData[]) => void;
|
||||
asyncChatSessions: (data: any[]) => void;
|
||||
deleteCtrlUser: (userId: number) => void;
|
||||
updateCtrlUser: (user: KfUserListData) => void;
|
||||
clearkfUserList: () => void;
|
||||
getChatSessions: () => any[];
|
||||
addChatSession: (session: any) => void;
|
||||
updateChatSession: (session: any) => void;
|
||||
deleteChatSession: (sessionId: string) => void;
|
||||
setUserInfo: (userInfo: CkUserInfo) => void;
|
||||
clearUserInfo: () => void;
|
||||
updateAccount: (account: Partial<CkAccount>) => void;
|
||||
|
||||
@@ -5,40 +5,50 @@ import {
|
||||
CkUserInfo,
|
||||
CkAccount,
|
||||
CkTenant,
|
||||
CkChatCtrlUserData,
|
||||
KfUserListData,
|
||||
} from "./ckchat.data";
|
||||
import { ContractData, GroupData } from "@/pages/pc/ckbox/data";
|
||||
export const useCkChatStore = createPersistStore<CkChatState>(
|
||||
set => ({
|
||||
userInfo: null,
|
||||
isLoggedIn: false,
|
||||
chatSessions: [],
|
||||
ctrlUserList: [],
|
||||
// 控制终端用户列表
|
||||
getCtrlUserList: () => {
|
||||
const state = useCkChatStore.getState();
|
||||
return state.ctrlUserList;
|
||||
contractList: [], //联系人列表
|
||||
chatSessions: [], //聊天会话
|
||||
kfUserList: [], //客服列表
|
||||
// 异步设置会话列表
|
||||
asyncChatSessions: data => {
|
||||
set({ chatSessions: data });
|
||||
},
|
||||
// 添加控制终端用户
|
||||
addCtrlUser: (user: CkChatCtrlUserData) => {
|
||||
set(state => ({
|
||||
ctrlUserList: [...state.ctrlUserList, user],
|
||||
}));
|
||||
// 异步设置联系人列表
|
||||
asyncContractList: data => {
|
||||
set({ contractList: data });
|
||||
},
|
||||
// 控制终端用户列表
|
||||
getkfUserList: () => {
|
||||
const state = useCkChatStore.getState();
|
||||
return state.kfUserList;
|
||||
},
|
||||
asyncKfUserList: data => {
|
||||
set({ kfUserList: data });
|
||||
},
|
||||
// 删除控制终端用户
|
||||
deleteCtrlUser: (userId: number) => {
|
||||
set(state => ({
|
||||
ctrlUserList: state.ctrlUserList.filter(item => item.id !== userId),
|
||||
kfUserList: state.kfUserList.filter(item => item.id !== userId),
|
||||
}));
|
||||
},
|
||||
// 更新控制终端用户
|
||||
updateCtrlUser: (user: CkChatCtrlUserData) => {
|
||||
updateCtrlUser: (user: KfUserListData) => {
|
||||
set(state => ({
|
||||
ctrlUserList: state.ctrlUserList.map(item =>
|
||||
kfUserList: state.kfUserList.map(item =>
|
||||
item.id === user.id ? user : item,
|
||||
),
|
||||
}));
|
||||
},
|
||||
// 清空控制终端用户列表
|
||||
clearkfUserList: () => {
|
||||
set({ kfUserList: [] });
|
||||
},
|
||||
// 获取聊天会话
|
||||
getChatSessions: () => {
|
||||
const state = useCkChatStore.getState();
|
||||
@@ -159,10 +169,16 @@ export const updateChatSession = (session: ContractData | GroupData) =>
|
||||
useCkChatStore.getState().updateChatSession(session);
|
||||
export const deleteChatSession = (sessionId: string) =>
|
||||
useCkChatStore.getState().deleteChatSession(sessionId);
|
||||
export const getCtrlUserList = () => useCkChatStore.getState().ctrlUserList;
|
||||
export const addCtrlUser = (user: CkChatCtrlUserData) =>
|
||||
export const getkfUserList = () => useCkChatStore.getState().kfUserList;
|
||||
export const addCtrlUser = (user: KfUserListData) =>
|
||||
useCkChatStore.getState().addCtrlUser(user);
|
||||
export const deleteCtrlUser = (userId: number) =>
|
||||
useCkChatStore.getState().deleteCtrlUser(userId);
|
||||
export const updateCtrlUser = (user: CkChatCtrlUserData) =>
|
||||
export const updateCtrlUser = (user: KfUserListData) =>
|
||||
useCkChatStore.getState().updateCtrlUser(user);
|
||||
export const asyncKfUserList = (data: KfUserListData[]) =>
|
||||
useCkChatStore.getState().asyncKfUserList(data);
|
||||
export const asyncContractList = (data: ContractData[]) =>
|
||||
useCkChatStore.getState().asyncContractList(data);
|
||||
export const asyncChatSessions = (data: ContractData[]) =>
|
||||
useCkChatStore.getState().asyncChatSessions(data);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Modal } from "antd-mobile";
|
||||
import { getSetting } from "@/store/module/settings";
|
||||
export function formatWechatTime(timestamp) {
|
||||
if (!timestamp) {
|
||||
return "";
|
||||
}
|
||||
// 处理时间戳(兼容秒级/毫秒级)
|
||||
const date = new Date(
|
||||
timestamp.toString().length === 10 ? timestamp * 1000 : timestamp,
|
||||
|
||||
Reference in New Issue
Block a user