feat(ckchat): 重构联系人列表逻辑并添加缓存功能
- 将联系人列表构建逻辑提取到独立api文件 - 添加getContractList缓存机制避免重复计算 - 优化kfSelected变更时的缓存清除逻辑 - 移除main.ts中冗余的联系人分组逻辑
This commit is contained in:
@@ -12,16 +12,11 @@ import {
|
|||||||
getControlTerminalList,
|
getControlTerminalList,
|
||||||
getContactList,
|
getContactList,
|
||||||
getGroupList,
|
getGroupList,
|
||||||
WechatGroup,
|
|
||||||
} from "./api";
|
} from "./api";
|
||||||
const { sendCommand } = useWebSocketStore.getState();
|
const { sendCommand } = useWebSocketStore.getState();
|
||||||
import { useUserStore } from "@/store/module/user";
|
import { useUserStore } from "@/store/module/user";
|
||||||
import { kfUserService, weChatGroupService, contractService } from "@/utils/db";
|
|
||||||
import {
|
import { KfUserListData } from "@/pages/pc/ckbox/data";
|
||||||
ContractData,
|
|
||||||
weChatGroup,
|
|
||||||
KfUserListData,
|
|
||||||
} from "@/pages/pc/ckbox/data";
|
|
||||||
const { login2 } = useUserStore.getState();
|
const { login2 } = useUserStore.getState();
|
||||||
//获取触客宝基础信息
|
//获取触客宝基础信息
|
||||||
export const chatInitAPIdata = async () => {
|
export const chatInitAPIdata = async () => {
|
||||||
@@ -48,10 +43,8 @@ export const chatInitAPIdata = async () => {
|
|||||||
|
|
||||||
await asyncWeChatGroup(groupList);
|
await asyncWeChatGroup(groupList);
|
||||||
|
|
||||||
//构建联系人列表标签
|
|
||||||
const newContractList = await createContractList();
|
|
||||||
// 会话列表分组
|
// 会话列表分组
|
||||||
await asyncNewContractList(newContractList);
|
await asyncNewContractList(0);
|
||||||
//获取消息会话列表并按lastUpdateTime排序
|
//获取消息会话列表并按lastUpdateTime排序
|
||||||
const filterUserSessions = contractList?.filter(
|
const filterUserSessions = contractList?.filter(
|
||||||
v => v?.config && v.config?.chat,
|
v => v?.config && v.config?.chat,
|
||||||
@@ -89,7 +82,6 @@ export const chatInitAPIdata = async () => {
|
|||||||
contractList,
|
contractList,
|
||||||
groupList,
|
groupList,
|
||||||
kfUserList,
|
kfUserList,
|
||||||
newContractList,
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取联系人列表失败:", error);
|
console.error("获取联系人列表失败:", error);
|
||||||
@@ -97,130 +89,12 @@ export const chatInitAPIdata = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//构建联系人列表标签
|
|
||||||
export const createContractList = async () => {
|
|
||||||
const LablesRes = await Promise.all(
|
|
||||||
[1, 2].map(item =>
|
|
||||||
WechatGroup({
|
|
||||||
groupType: item,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
const [friend, group] = LablesRes;
|
|
||||||
const countLables = [
|
|
||||||
...[
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
groupName: "默认群分组",
|
|
||||||
groupType: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
...group,
|
|
||||||
...friend,
|
|
||||||
...[
|
|
||||||
{
|
|
||||||
id: 0,
|
|
||||||
groupName: "未分组",
|
|
||||||
groupType: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
// 根据 groupType 决定查询不同的服务
|
|
||||||
const dataByLabels = [];
|
|
||||||
for (const label of countLables) {
|
|
||||||
let data;
|
|
||||||
if (label.groupType === 1) {
|
|
||||||
// groupType: 1, 查询 contractService
|
|
||||||
data = await contractService.findWhere("groupId", label.id);
|
|
||||||
// console.log(`标签 ${label.groupName} 对应的联系人数据:`, data);
|
|
||||||
} else if (label.groupType === 2) {
|
|
||||||
// groupType: 2, 查询 weChatGroupService
|
|
||||||
data = await weChatGroupService.findWhere("groupId", label.id);
|
|
||||||
} else {
|
|
||||||
console.warn(`未知的 groupType: ${label.groupType}`);
|
|
||||||
data = [];
|
|
||||||
}
|
|
||||||
dataByLabels.push({
|
|
||||||
...label,
|
|
||||||
contacts: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return dataByLabels;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据标签组织联系人
|
* 根据标签组织联系人
|
||||||
* @param contractList 联系人列表
|
* @param contractList 联系人列表
|
||||||
* @param countLables 标签列表
|
* @param countLables 标签列表
|
||||||
* @returns 按标签分组的联系人
|
* @returns 按标签分组的联系人
|
||||||
*/
|
*/
|
||||||
export const organizeContactsByLabels = (
|
|
||||||
countLables: any[],
|
|
||||||
contractList: ContractData[],
|
|
||||||
groupList: weChatGroup[],
|
|
||||||
) => {
|
|
||||||
// 创建结果对象,用于存储按标签分组的联系人
|
|
||||||
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 = (
|
export const getControlTerminalListByWechatAccountIds = (
|
||||||
|
|||||||
65
Cunkebao/src/store/module/ckchat/api.ts
Normal file
65
Cunkebao/src/store/module/ckchat/api.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
//构建联系人列表标签
|
||||||
|
import { weChatGroupService, contractService } from "@/utils/db";
|
||||||
|
import { request } from "@/api/request2";
|
||||||
|
export function WechatGroup(params) {
|
||||||
|
return request("/api/WechatGroup/list", params, "GET");
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createContractList = async (kfSelected: number) => {
|
||||||
|
const LablesRes = await Promise.all(
|
||||||
|
[1, 2].map(item =>
|
||||||
|
WechatGroup({
|
||||||
|
groupType: item,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const [friend, group] = LablesRes;
|
||||||
|
const countLables = [
|
||||||
|
...[
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
groupName: "默认群分组",
|
||||||
|
groupType: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...group,
|
||||||
|
...friend,
|
||||||
|
...[
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
groupName: "未分组",
|
||||||
|
groupType: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// 根据 groupType 决定查询不同的服务
|
||||||
|
const dataByLabels = [];
|
||||||
|
for (const label of countLables) {
|
||||||
|
let data;
|
||||||
|
if (label.groupType === 1) {
|
||||||
|
// groupType: 1, 查询 contractService
|
||||||
|
data = await contractService.findWhere("groupId", label.id);
|
||||||
|
// 过滤出 kfSelected 对应的联系人
|
||||||
|
if (kfSelected && kfSelected != 0) {
|
||||||
|
data = data.filter(contact => contact.wechatAccountId === kfSelected);
|
||||||
|
}
|
||||||
|
// console.log(`标签 ${label.groupName} 对应的联系人数据:`, data);
|
||||||
|
} else if (label.groupType === 2) {
|
||||||
|
// groupType: 2, 查询 weChatGroupService
|
||||||
|
data = await weChatGroupService.findWhere("groupId", label.id);
|
||||||
|
if (kfSelected && kfSelected != 0) {
|
||||||
|
data = data.filter(contact => contact.wechatAccountId === kfSelected);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn(`未知的 groupType: ${label.groupType}`);
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
dataByLabels.push({
|
||||||
|
...label,
|
||||||
|
contacts: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataByLabels;
|
||||||
|
};
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
contractService,
|
contractService,
|
||||||
messageListService,
|
messageListService,
|
||||||
} from "@/utils/db";
|
} from "@/utils/db";
|
||||||
|
import { createContractList } from "@/store/module/ckchat/api";
|
||||||
export const useCkChatStore = createPersistStore<CkChatState>(
|
export const useCkChatStore = createPersistStore<CkChatState>(
|
||||||
set => ({
|
set => ({
|
||||||
userInfo: null,
|
userInfo: null,
|
||||||
@@ -33,7 +34,7 @@ export const useCkChatStore = createPersistStore<CkChatState>(
|
|||||||
},
|
},
|
||||||
asyncKfSelected: (data: number) => {
|
asyncKfSelected: (data: number) => {
|
||||||
set({ kfSelected: data });
|
set({ kfSelected: data });
|
||||||
// 清除getChatSessions缓存
|
// 清除getChatSessions和getContractList缓存
|
||||||
const state = useCkChatStore.getState();
|
const state = useCkChatStore.getState();
|
||||||
if (
|
if (
|
||||||
state.getChatSessions &&
|
state.getChatSessions &&
|
||||||
@@ -42,9 +43,17 @@ export const useCkChatStore = createPersistStore<CkChatState>(
|
|||||||
// 触发缓存重新计算
|
// 触发缓存重新计算
|
||||||
state.getChatSessions();
|
state.getChatSessions();
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
state.getContractList &&
|
||||||
|
typeof state.getContractList === "function"
|
||||||
|
) {
|
||||||
|
// 触发缓存重新计算
|
||||||
|
state.getContractList();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 异步设置会话列表
|
// 异步设置会话列表
|
||||||
asyncNewContractList: (data: ContactGroupByLabel[]) => {
|
asyncNewContractList: async (kfSelected: number) => {
|
||||||
|
const data: ContactGroupByLabel[] = await createContractList(kfSelected);
|
||||||
set({ newContractList: data });
|
set({ newContractList: data });
|
||||||
},
|
},
|
||||||
getNewContractList: () => {
|
getNewContractList: () => {
|
||||||
@@ -66,8 +75,47 @@ export const useCkChatStore = createPersistStore<CkChatState>(
|
|||||||
},
|
},
|
||||||
// 异步设置联系人列表
|
// 异步设置联系人列表
|
||||||
asyncContractList: async (data: ContractData[]) => {
|
asyncContractList: async (data: ContractData[]) => {
|
||||||
|
set({ contractList: data });
|
||||||
await contractService.createManyWithServerId(data);
|
await contractService.createManyWithServerId(data);
|
||||||
|
// 清除getContractList缓存
|
||||||
|
const state = useCkChatStore.getState();
|
||||||
|
if (
|
||||||
|
state.getContractList &&
|
||||||
|
typeof state.getContractList === "function"
|
||||||
|
) {
|
||||||
|
// 触发缓存重新计算
|
||||||
|
state.getContractList();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
// 获取联系人列表 - 使用缓存避免无限循环
|
||||||
|
getContractList: (() => {
|
||||||
|
let cachedResult: any = null;
|
||||||
|
let lastKfSelected: number | null = null;
|
||||||
|
let lastContractListLength: number = 0;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const state = useCkChatStore.getState();
|
||||||
|
|
||||||
|
// 检查是否需要重新计算缓存
|
||||||
|
const shouldRecalculate =
|
||||||
|
cachedResult === null ||
|
||||||
|
lastKfSelected !== state.kfSelected ||
|
||||||
|
lastContractListLength !== state.contractList.length;
|
||||||
|
|
||||||
|
if (shouldRecalculate) {
|
||||||
|
const filteredContracts = state.contractList.filter(
|
||||||
|
item => item.wechatAccountId === state.kfSelected,
|
||||||
|
);
|
||||||
|
|
||||||
|
cachedResult =
|
||||||
|
state.kfSelected !== 0 ? filteredContracts : state.contractList;
|
||||||
|
lastKfSelected = state.kfSelected;
|
||||||
|
lastContractListLength = state.contractList.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedResult;
|
||||||
|
};
|
||||||
|
})(),
|
||||||
//异步设置联系人分组
|
//异步设置联系人分组
|
||||||
asyncWeChatGroup: async (data: weChatGroup[]) => {
|
asyncWeChatGroup: async (data: weChatGroup[]) => {
|
||||||
await weChatGroupService.createManyWithServerId(data);
|
await weChatGroupService.createManyWithServerId(data);
|
||||||
@@ -284,9 +332,8 @@ export const asyncContractList = (data: ContractData[]) =>
|
|||||||
useCkChatStore.getState().asyncContractList(data);
|
useCkChatStore.getState().asyncContractList(data);
|
||||||
export const asyncChatSessions = (data: ContractData[]) =>
|
export const asyncChatSessions = (data: ContractData[]) =>
|
||||||
useCkChatStore.getState().asyncChatSessions(data);
|
useCkChatStore.getState().asyncChatSessions(data);
|
||||||
export const asyncNewContractList = (
|
export const asyncNewContractList = (kfSelected: number) =>
|
||||||
data: { groupName: string; contacts: any[] }[],
|
useCkChatStore.getState().asyncNewContractList(kfSelected);
|
||||||
) => useCkChatStore.getState().asyncNewContractList(data);
|
|
||||||
export const asyncKfSelected = (data: number) =>
|
export const asyncKfSelected = (data: number) =>
|
||||||
useCkChatStore.getState().asyncKfSelected(data);
|
useCkChatStore.getState().asyncKfSelected(data);
|
||||||
export const asyncWeChatGroup = (data: weChatGroup[]) =>
|
export const asyncWeChatGroup = (data: weChatGroup[]) =>
|
||||||
@@ -295,3 +342,5 @@ export const getKfSelectedUser = () =>
|
|||||||
useCkChatStore.getState().getKfSelectedUser();
|
useCkChatStore.getState().getKfSelectedUser();
|
||||||
export const getKfUserInfo = (wechatAccountId: number) =>
|
export const getKfUserInfo = (wechatAccountId: number) =>
|
||||||
useCkChatStore.getState().getKfUserInfo(wechatAccountId);
|
useCkChatStore.getState().getKfUserInfo(wechatAccountId);
|
||||||
|
export const getContractList = () =>
|
||||||
|
useCkChatStore.getState().getContractList();
|
||||||
|
|||||||
Reference in New Issue
Block a user