diff --git a/Cunkebao/src/store/module/ckchat/api.ts b/Cunkebao/src/store/module/ckchat/api.ts deleted file mode 100644 index 5c91f734..00000000 --- a/Cunkebao/src/store/module/ckchat/api.ts +++ /dev/null @@ -1,43 +0,0 @@ -//构建联系人列表标签 -import { weChatGroupService, contractService } from "@/utils/db"; -import { request } from "@/api/request2"; -import { ContactGroupByLabel } from "@/pages/pc/ckbox/data"; - -export function WechatGroup(params) { - return request("/api/WechatGroup/list", params, "GET"); -} - -export const createContractList = async ( - kfSelected: number, - countLables: ContactGroupByLabel[], -) => { - // 根据 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; -}; diff --git a/Cunkebao/src/store/module/ckchat/ckchat.data.ts b/Cunkebao/src/store/module/ckchat/ckchat.data.ts deleted file mode 100644 index 3d74c36c..00000000 --- a/Cunkebao/src/store/module/ckchat/ckchat.data.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - ContractData, - KfUserListData, - CkAccount, - ContactGroupByLabel, - weChatGroup, -} from "@/pages/pc/ckbox/data"; - -// 权限片段接口 -export interface PrivilegeFrag { - // 根据实际数据结构补充 - [key: string]: any; -} - -// 租户信息接口 -export interface CkTenant { - id: number; - name: string; - guid: string; - thirdParty: string | null; - tenantType: number; - deployName: string; -} - -// 触客宝用户信息接口 -export interface CkUserInfo { - account: CkAccount; - privilegeFrags: PrivilegeFrag[]; - tenant: CkTenant; -} - -// 状态接口 -export interface CkChatState { - userInfo: CkUserInfo | null; - isLoggedIn: boolean; - searchKeyword: string; - contractList: ContractData[]; - chatSessions: any[]; - kfUserList: KfUserListData[]; - kfSelected: number; - getKfSelectedUser: () => KfUserListData | undefined; - countLables: ContactGroupByLabel[]; - newContractList: ContactGroupByLabel[]; - getContractList: () => ContractData[]; - getSomeContractList: (kfSelected: number) => ContractData[]; - getNewContractList: () => ContactGroupByLabel[]; - setSearchKeyword: (keyword: string) => void; - clearSearchKeyword: () => void; - asyncKfSelected: (data: number) => void; - asyncWeChatGroup: (data: weChatGroup[]) => void; - asyncCountLables: (data: ContactGroupByLabel[]) => void; - getkfUserList: () => KfUserListData[]; - asyncKfUserList: (data: KfUserListData[]) => void; - getKfUserInfo: (wechatAccountId: number) => KfUserListData | undefined; - asyncContractList: (data: ContractData[]) => void; - getChatSessions: () => any[]; - asyncChatSessions: (data: any[]) => void; - updateChatSession: (session: ContractData | weChatGroup) => void; - deleteCtrlUser: (userId: number) => void; - updateCtrlUser: (user: KfUserListData) => void; - clearkfUserList: () => void; - addChatSession: (session: any) => void; - deleteChatSession: (sessionId: number) => void; - setUserInfo: (userInfo: CkUserInfo) => void; - clearUserInfo: () => void; - updateAccount: (account: Partial) => void; - updateTenant: (tenant: Partial) => void; - getAccountId: () => number | null; - getTenantId: () => number | null; - getAccountName: () => string | null; - getTenantName: () => string | null; -} diff --git a/Cunkebao/src/store/module/ckchat/ckchat.ts b/Cunkebao/src/store/module/ckchat/ckchat.ts deleted file mode 100644 index 1b44fcbe..00000000 --- a/Cunkebao/src/store/module/ckchat/ckchat.ts +++ /dev/null @@ -1,527 +0,0 @@ -import { createPersistStore } from "@/store/createPersistStore"; -import { CkChatState, CkUserInfo, CkTenant } from "./ckchat.data"; -import { - ContractData, - weChatGroup, - CkAccount, - KfUserListData, - ContactGroupByLabel, -} from "@/pages/pc/ckbox/data"; -import { weChatGroupService, contractService } from "@/utils/db"; -import { createContractList } from "@/store/module/ckchat/api"; -import { useWeChatStore } from "@/store/module/weChat/weChat"; -// 从weChat store获取clearCurrentContact方法 -const getClearCurrentContact = () => - useWeChatStore.getState().clearCurrentContact; -export const useCkChatStore = createPersistStore( - set => ({ - userInfo: null, - isLoggedIn: false, - contractList: [], //联系人列表 - chatSessions: [], //聊天会话 - kfUserList: [], //客服列表 - countLables: [], //标签列表 - newContractList: [], //联系人分组 - kfSelected: 0, //选中的客服 - searchKeyword: "", //搜索关键词 - //客服列表 - asyncKfUserList: async data => { - set({ kfUserList: data }); - // await kfUserService.createManyWithServerId(data); - }, - // 获取客服列表 - getkfUserList: async () => { - const state = useCkChatStore.getState(); - return state.kfUserList; - // return await kfUserService.findAll(); - }, - // 异步设置标签列表 - asyncCountLables: async (data: ContactGroupByLabel[]) => { - set({ countLables: data }); - // 清除getNewContractList缓存 - const state = useCkChatStore.getState(); - if ( - state.getNewContractList && - typeof state.getNewContractList === "function" - ) { - // 触发缓存重新计算 - await state.getNewContractList(); - } - }, - // 设置搜索关键词 - setSearchKeyword: (keyword: string) => { - set({ searchKeyword: keyword }); - }, - // 清除搜索关键词 - clearSearchKeyword: () => { - set({ searchKeyword: "" }); - }, - asyncKfSelected: async (data: number) => { - set({ kfSelected: data }); - // 清除getChatSessions、getContractList和getNewContractList缓存 - const state = useCkChatStore.getState(); - if ( - state.getChatSessions && - typeof state.getChatSessions === "function" - ) { - // 触发缓存重新计算 - state.getChatSessions(); - } - if ( - state.getContractList && - typeof state.getContractList === "function" - ) { - // 触发缓存重新计算 - state.getContractList(); - } - if ( - state.getNewContractList && - typeof state.getNewContractList === "function" - ) { - // 触发缓存重新计算 - await state.getNewContractList(); - } - }, - - // 获取联系人分组列表 - 使用缓存避免无限循环 - getNewContractList: (() => { - let cachedResult: any = null; - let lastKfSelected: number | null = null; - let lastCountLablesLength: number = 0; - let lastSearchKeyword: string = ""; - - return async () => { - const state = useCkChatStore.getState(); - - // 检查是否需要重新计算缓存 - const shouldRecalculate = - cachedResult === null || - lastKfSelected !== state.kfSelected || - lastCountLablesLength !== (state.countLables?.length || 0) || - lastSearchKeyword !== state.searchKeyword; - - if (shouldRecalculate) { - // 使用createContractList构建联系人分组数据 - let contractList = await createContractList( - state.kfSelected, - state.countLables, - ); - - // 根据搜索关键词筛选联系人分组 - if (state.searchKeyword.trim()) { - const keyword = state.searchKeyword.toLowerCase(); - contractList = contractList - .map(group => ({ - ...group, - contracts: - group.contracts?.filter(item => { - const nickname = (item.nickname || "").toLowerCase(); - const conRemark = (item.conRemark || "").toLowerCase(); - return ( - nickname.includes(keyword) || conRemark.includes(keyword) - ); - }) || [], - })) - .filter(group => group.contracts.length > 0); - } - - cachedResult = contractList; - lastKfSelected = state.kfSelected; - lastCountLablesLength = state.countLables?.length || 0; - lastSearchKeyword = state.searchKeyword; - } - - return cachedResult; - }; - })(), - // 搜索好友和群组的新方法 - 从本地数据库查询并返回扁平化的搜索结果 - searchContactsAndGroups: (() => { - let cachedResult: (ContractData | weChatGroup)[] = []; - let lastKfSelected: number | null = null; - let lastSearchKeyword: string = ""; - - return async () => { - const state = useCkChatStore.getState(); - - // 检查是否需要重新计算缓存 - const shouldRecalculate = - lastKfSelected !== state.kfSelected || - lastSearchKeyword !== state.searchKeyword; - - if (shouldRecalculate) { - if (state.searchKeyword.trim()) { - const keyword = state.searchKeyword.toLowerCase(); - - // 从本地数据库查询联系人数据 - let allContacts: any[] = await contractService.findAll(); - - // 从本地数据库查询群组数据 - let allGroups: any[] = await weChatGroupService.findAll(); - - // 根据选中的客服筛选联系人 - if (state.kfSelected !== 0) { - allContacts = allContacts.filter( - item => item.wechatAccountId === state.kfSelected, - ); - } - - // 根据选中的客服筛选群组 - if (state.kfSelected !== 0) { - allGroups = allGroups.filter( - item => item.wechatAccountId === state.kfSelected, - ); - } - - // 搜索匹配的联系人 - const matchedContacts = allContacts.filter(item => { - const nickname = (item.nickname || "").toLowerCase(); - const conRemark = (item.conRemark || "").toLowerCase(); - return nickname.includes(keyword) || conRemark.includes(keyword); - }); - - // 搜索匹配的群组 - const matchedGroups = allGroups.filter(item => { - const nickname = (item.nickname || "").toLowerCase(); - const conRemark = (item.conRemark || "").toLowerCase(); - return nickname.includes(keyword) || conRemark.includes(keyword); - }); - - // 合并搜索结果 - cachedResult = [...matchedContacts, ...matchedGroups]; - } else { - cachedResult = []; - } - - lastKfSelected = state.kfSelected; - lastSearchKeyword = state.searchKeyword; - } - - return cachedResult; - }; - })(), - // 异步设置联系人分组列表 - asyncNewContractList: async (data: any[]) => { - set({ newContractList: data }); - // 清除getNewContractList缓存 - const state = useCkChatStore.getState(); - if ( - state.getNewContractList && - typeof state.getNewContractList === "function" - ) { - // 触发缓存重新计算 - await state.getNewContractList(); - } - }, - // 异步设置会话列表 - asyncChatSessions: data => { - set({ chatSessions: data }); - // 清除getChatSessions缓存 - const state = useCkChatStore.getState(); - if ( - state.getChatSessions && - typeof state.getChatSessions === "function" - ) { - // 触发缓存重新计算 - state.getChatSessions(); - } - }, - // 异步设置联系人列表 - asyncContractList: async (data: ContractData[]) => { - set({ contractList: data }); - await contractService.createManyWithServerId(data); - // 清除getContractList缓存 - const state = useCkChatStore.getState(); - if ( - state.getContractList && - typeof state.getContractList === "function" - ) { - // 触发缓存重新计算 - state.getContractList(); - } - }, - //获取特定联系人 - getSomeContractList: (kfSelected: number) => { - const state = useCkChatStore.getState(); - return state.contractList.filter( - item => item.wechatAccountId === kfSelected, - ); - }, - // 获取联系人列表 - 使用缓存避免无限循环 - getContractList: (() => { - let cachedResult: any = null; - let lastKfSelected: number | null = null; - let lastContractListLength: number = 0; - let lastSearchKeyword: string = ""; - - return () => { - const state = useCkChatStore.getState(); - - // 检查是否需要重新计算缓存 - const shouldRecalculate = - cachedResult === null || - lastKfSelected !== state.kfSelected || - lastContractListLength !== state.contractList.length || - lastSearchKeyword !== state.searchKeyword; - - if (shouldRecalculate) { - let filteredContracts = state.contractList; - - // 根据客服筛选 - if (state.kfSelected !== 0) { - filteredContracts = filteredContracts.filter( - item => item.wechatAccountId === state.kfSelected, - ); - } - - // 根据搜索关键词筛选 - if (state.searchKeyword.trim()) { - const keyword = state.searchKeyword.toLowerCase(); - filteredContracts = filteredContracts.filter(item => { - const nickname = (item.nickname || "").toLowerCase(); - const conRemark = (item.conRemark || "").toLowerCase(); - return nickname.includes(keyword) || conRemark.includes(keyword); - }); - } - - cachedResult = filteredContracts; - lastKfSelected = state.kfSelected; - lastContractListLength = state.contractList.length; - lastSearchKeyword = state.searchKeyword; - } - - return cachedResult; - }; - })(), - //异步设置联系人分组 - asyncWeChatGroup: async (data: weChatGroup[]) => { - await weChatGroupService.createManyWithServerId(data); - }, - //获取选中的客服信息 - getKfSelectedUser: () => { - const state = useCkChatStore.getState(); - return state.kfUserList.find(item => item.id === state.kfSelected); - }, - getKfUserInfo: (wechatAccountId: number) => { - const state = useCkChatStore.getState(); - return state.kfUserList.find(item => item.id === wechatAccountId); - }, - - // 删除控制终端用户 - deleteCtrlUser: (userId: number) => { - set(state => ({ - kfUserList: state.kfUserList.filter(item => item.id !== userId), - })); - }, - // 更新控制终端用户 - updateCtrlUser: (user: KfUserListData) => { - set(state => ({ - kfUserList: state.kfUserList.map(item => - item.id === user.id ? user : item, - ), - })); - }, - // 清空控制终端用户列表 - clearkfUserList: () => { - set({ kfUserList: [] }); - }, - // 获取聊天会话 - 使用缓存避免无限循环 - getChatSessions: (() => { - let cachedResult: any = null; - let lastKfSelected: number | null = null; - let lastChatSessionsLength: number = 0; - let lastSearchKeyword: string = ""; - - return () => { - const state = useCkChatStore.getState(); - - // 检查是否需要重新计算缓存 - const shouldRecalculate = - cachedResult === null || - lastKfSelected !== state.kfSelected || - lastChatSessionsLength !== state.chatSessions.length || - lastSearchKeyword !== state.searchKeyword; - - if (shouldRecalculate) { - let filteredSessions = state.chatSessions; - - // 根据客服筛选 - if (state.kfSelected !== 0) { - filteredSessions = filteredSessions.filter( - item => item.wechatAccountId === state.kfSelected, - ); - } - - // 根据搜索关键词筛选 - if (state.searchKeyword.trim()) { - const keyword = state.searchKeyword.toLowerCase(); - filteredSessions = filteredSessions.filter(item => { - const nickname = (item.nickname || "").toLowerCase(); - const conRemark = (item.conRemark || "").toLowerCase(); - return nickname.includes(keyword) || conRemark.includes(keyword); - }); - } - - cachedResult = filteredSessions; - lastKfSelected = state.kfSelected; - lastChatSessionsLength = state.chatSessions.length; - lastSearchKeyword = state.searchKeyword; - } - - return cachedResult; - }; - })(), - // 添加聊天会话 - addChatSession: (session: ContractData | weChatGroup) => { - set(state => { - // 检查是否已存在相同id的会话 - const exists = state.chatSessions.some(item => item.id === session.id); - // 如果已存在则不添加,否则添加到列表中 - return { - chatSessions: exists - ? state.chatSessions - : [...state.chatSessions, session as ContractData | weChatGroup], - }; - }); - }, - // 更新聊天会话 - updateChatSession: (session: ContractData | weChatGroup) => { - set(state => ({ - chatSessions: state.chatSessions.map(item => - item.id === session.id ? { ...item, ...session } : item, - ), - })); - }, - // 删除聊天会话 - deleteChatSession: (sessionId: number) => { - set(state => ({ - chatSessions: state.chatSessions.filter(item => item.id !== sessionId), - })); - //当前选中的客户清空 - getClearCurrentContact(); - }, - // 设置用户信息 - setUserInfo: (userInfo: CkUserInfo) => { - set({ userInfo, isLoggedIn: true }); - }, - - // 清除用户信息 - clearUserInfo: () => { - set({ userInfo: null, isLoggedIn: false }); - }, - - // 更新账户信息 - updateAccount: (account: Partial) => { - set(state => ({ - userInfo: state.userInfo - ? { - ...state.userInfo, - account: { ...state.userInfo.account, ...account }, - } - : null, - })); - }, - - // 更新租户信息 - updateTenant: (tenant: Partial) => { - set(state => ({ - userInfo: state.userInfo - ? { - ...state.userInfo, - tenant: { ...state.userInfo.tenant, ...tenant }, - } - : null, - })); - }, - - // 获取账户ID - getAccountId: () => { - const state = useCkChatStore.getState(); - return Number(state.userInfo?.account?.id) || null; - }, - - // 获取租户ID - getTenantId: () => { - const state = useCkChatStore.getState(); - return state.userInfo?.tenant?.id || null; - }, - - // 获取账户名称 - getAccountName: () => { - const state = useCkChatStore.getState(); - return ( - state.userInfo?.account?.realName || - state.userInfo?.account?.userName || - null - ); - }, - - // 获取租户名称 - getTenantName: () => { - const state = useCkChatStore.getState(); - return state.userInfo?.tenant?.name || null; - }, - }), - { - name: "ckchat-store", - partialize: state => ({ - userInfo: state.userInfo, - isLoggedIn: state.isLoggedIn, - kfUserList: state.kfUserList, - }), - onRehydrateStorage: () => state => { - // console.log("CkChat store hydrated:", state); - }, - }, -); - -// 导出便捷的获取方法 -export const getCkAccountId = () => useCkChatStore.getState().getAccountId(); -export const getCkTenantId = () => useCkChatStore.getState().getTenantId(); -export const getCkAccountName = () => - useCkChatStore.getState().getAccountName(); -export const getCkTenantName = () => useCkChatStore.getState().getTenantName(); -export const getChatSessions = () => - useCkChatStore.getState().getChatSessions(); -export const addChatSession = (session: ContractData | weChatGroup) => - useCkChatStore.getState().addChatSession(session); -export const updateChatSession = (session: ContractData | weChatGroup) => - useCkChatStore.getState().updateChatSession(session); -export const deleteChatSession = (sessionId: string) => - useCkChatStore.getState().deleteChatSession(sessionId); -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: 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); -export const asyncKfSelected = (data: number) => - useCkChatStore.getState().asyncKfSelected(data); -export const asyncWeChatGroup = (data: weChatGroup[]) => - useCkChatStore.getState().asyncWeChatGroup(data); -export const getKfSelectedUser = () => - useCkChatStore.getState().getKfSelectedUser(); -export const getKfUserInfo = (wechatAccountId: number) => - useCkChatStore.getState().getKfUserInfo(wechatAccountId); -export const getContractList = () => - useCkChatStore.getState().getContractList(); -export const getNewContractList = () => - useCkChatStore.getState().getNewContractList(); -export const asyncCountLables = (data: ContactGroupByLabel[]) => - useCkChatStore.getState().asyncCountLables(data); -export const asyncNewContractList = (data: any[]) => - useCkChatStore.getState().asyncNewContractList(data); -export const getCountLables = () => useCkChatStore.getState().countLables; -export const setSearchKeyword = (keyword: string) => - useCkChatStore.getState().setSearchKeyword(keyword); -export const clearSearchKeyword = () => - useCkChatStore.getState().clearSearchKeyword(); -export const searchContactsAndGroups = () => - useCkChatStore.getState().searchContactsAndGroups(); -useCkChatStore.getState().getKfSelectedUser(); diff --git a/Cunkebao/src/store/module/weChat/weChat.data.ts b/Cunkebao/src/store/module/weChat/weChat.data.ts deleted file mode 100644 index 7cdd4b73..00000000 --- a/Cunkebao/src/store/module/weChat/weChat.data.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; -// 微信聊天相关的类型定义 -export interface WeChatState { - // 当前选中的联系人/群组 - currentContract: ContractData | weChatGroup | null; - - // 当前聊天用户的消息列表(只存储当前聊天用户的消息) - currentMessages: ChatRecord[]; - // 清空当前联系人 - clearCurrentContact: () => void; - // 消息加载状态 - messagesLoading: boolean; - isLoadingData: boolean; - currentGroupMembers: any[]; - - // Actions - setCurrentContact: ( - contract: ContractData | weChatGroup, - isExist?: boolean, - ) => void; - loadChatMessages: (Init: boolean, To?: number) => Promise; - SearchMessage: (params: { - From: number; - To: number; - keyword: string; - Count?: number; - }) => Promise; - // 视频消息处理方法 - setVideoLoading: (messageId: number, isLoading: boolean) => void; - setVideoUrl: (messageId: number, videoUrl: string) => void; - addMessage: (message: ChatRecord) => void; - receivedMsg: (message: ChatRecord) => void; -} diff --git a/Cunkebao/src/store/module/weChat/weChat.ts b/Cunkebao/src/store/module/weChat/weChat.ts deleted file mode 100644 index f4f3cb0c..00000000 --- a/Cunkebao/src/store/module/weChat/weChat.ts +++ /dev/null @@ -1,287 +0,0 @@ -import { create } from "zustand"; -import { persist } from "zustand/middleware"; -import { - getChatMessages, - getChatroomMessages, - getGroupMembers, -} from "@/pages/pc/ckbox/api"; -import { WeChatState } from "./weChat.data"; -import { clearUnreadCount, updateConfig } from "@/pages/pc/ckbox/api"; -import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data"; -import { weChatGroupService, contractService } from "@/utils/db"; -import { - addChatSession, - updateChatSession, - useCkChatStore, -} from "@/store/module/ckchat/ckchat"; - -export const useWeChatStore = create()( - persist( - (set, get) => ({ - // 初始状态 - currentContract: null, - currentMessages: [], - messagesLoading: false, - isLoadingData: false, - currentGroupMembers: [], - //清空当前联系人 - clearCurrentContact: () => { - set({ currentContract: null, currentMessages: [] }); - }, - // Actions - setCurrentContact: ( - contract: ContractData | weChatGroup, - isExist?: boolean, - ) => { - const state = useWeChatStore.getState(); - // 切换联系人时清空当前消息,等待重新加载 - set({ currentMessages: [] }); - clearUnreadCount([contract.id]).then(() => { - if (isExist) { - updateChatSession({ ...contract, unreadCount: 0 }); - } else { - addChatSession(contract); - } - set({ currentContract: contract }); - updateConfig({ - id: contract.id, - config: { chat: true }, - }); - state.loadChatMessages(true, 4704624000000); - }); - }, - loadChatMessages: async (Init: boolean, To?: number) => { - const state = useWeChatStore.getState(); - const contact = state.currentContract; - set({ messagesLoading: true }); - set({ isLoadingData: Init }); - try { - const params: any = { - wechatAccountId: contact.wechatAccountId, - From: 1, - To: To || +new Date(), - Count: 5, - olderData: true, - }; - - if ("chatroomId" in contact && contact.chatroomId) { - params.wechatChatroomId = contact.id; - const messages = await getChatroomMessages(params); - const currentGroupMembers = await getGroupMembers({ - id: contact.id, - }); - if (Init) { - set({ currentMessages: messages || [], currentGroupMembers }); - } else { - set({ - currentMessages: [ - ...(messages || []), - ...state.currentMessages, - ], - }); - } - } else { - params.wechatFriendId = contact.id; - const messages = await getChatMessages(params); - if (Init) { - set({ currentMessages: messages || [] }); - } else { - set({ - currentMessages: [ - ...(messages || []), - ...state.currentMessages, - ], - }); - } - } - set({ messagesLoading: false }); - } catch (error) { - console.error("获取聊天消息失败:", error); - } finally { - set({ messagesLoading: false }); - } - }, - SearchMessage: async ({ - From = 1, - To = 4704624000000, - keyword = "", - Count = 20, - }: { - From: number; - To: number; - keyword: string; - Count?: number; - }) => { - const state = useWeChatStore.getState(); - const contact = state.currentContract; - set({ messagesLoading: true }); - - try { - const params: any = { - wechatAccountId: contact.wechatAccountId, - From, - To, - keyword, - Count, - olderData: true, - }; - - if ("chatroomId" in contact && contact.chatroomId) { - params.wechatChatroomId = contact.id; - const messages = await getChatroomMessages(params); - const currentGroupMembers = await getGroupMembers({ - id: contact.id, - }); - set({ currentMessages: messages || [], currentGroupMembers }); - } else { - params.wechatFriendId = contact.id; - const messages = await getChatMessages(params); - set({ currentMessages: messages || [] }); - } - set({ messagesLoading: false }); - } catch (error) { - console.error("获取聊天消息失败:", error); - } finally { - set({ messagesLoading: false }); - } - }, - - setMessageLoading: loading => { - set({ messagesLoading: Boolean(loading) }); - }, - - addMessage: message => { - set(state => ({ - currentMessages: [...state.currentMessages, message], - })); - }, - - receivedMsg: async message => { - const currentContract = useWeChatStore.getState().currentContract; - //判断群还是好友 - const getMessageId = - message?.wechatChatroomId || message.wechatFriendId; - const isWechatGroup = message?.wechatChatroomId; - //当前选中聊天的群或好友 - if (currentContract && currentContract.id == getMessageId) { - set(state => ({ - currentMessages: [...state.currentMessages, message], - })); - } else { - //更新消息列表unread数值,根据接收的++1 这样 - const chatSessions = useCkChatStore.getState().chatSessions; - const session = chatSessions.find(item => item.id == getMessageId); - if (session) { - session.unreadCount = Number(session.unreadCount) + 1; - updateChatSession(session); - } else { - if (isWechatGroup) { - const [group] = await weChatGroupService.findByIds(getMessageId); - if (group) { - addChatSession({ - ...group, - unreadCount: 1, - }); - } - } else { - const [user] = await contractService.findByIds(getMessageId); - addChatSession({ - ...user, - unreadCount: 1, - }); - } - } - } - }, - - updateMessage: (messageId, updates) => { - set(state => ({ - currentMessages: state.currentMessages.map(msg => - msg.id === messageId ? { ...msg, ...updates } : msg, - ), - })); - }, - - // 便捷选择器 - getCurrentContact: () => get().currentContract, - getCurrentMessages: () => get().currentMessages, - getMessagesLoading: () => get().messagesLoading, - - // 视频消息处理方法 - setVideoLoading: (messageId: number, isLoading: boolean) => { - set(state => ({ - currentMessages: state.currentMessages.map(msg => { - if (msg.id === messageId) { - try { - const content = JSON.parse(msg.content); - // 更新加载状态 - const updatedContent = { ...content, isLoading }; - return { - ...msg, - content: JSON.stringify(updatedContent), - }; - } catch (e) { - console.error("更新视频加载状态失败:", e); - return msg; - } - } - return msg; - }), - })); - }, - - setVideoUrl: (messageId: number, videoUrl: string) => { - set(state => ({ - currentMessages: state.currentMessages.map(msg => { - if (msg.id === messageId) { - try { - const content = JSON.parse(msg.content); - // 检查视频是否已经下载完毕,避免重复更新 - if (content.videoUrl && content.videoUrl === videoUrl) { - console.log("视频已下载,跳过重复更新:", messageId); - return msg; - } - - // 设置视频URL并清除加载状态 - const updatedContent = { - ...content, - videoUrl, - isLoading: false, - }; - return { - ...msg, - content: JSON.stringify(updatedContent), - }; - } catch (e) { - console.error("更新视频URL失败:", e); - return msg; - } - } - return msg; - }), - })); - }, - clearAllData: () => { - set({ - currentContract: null, - currentMessages: [], - messagesLoading: false, - }); - }, - }), - { - name: "wechat-storage", - partialize: state => ({ - // currentContract 不做持久化,登录和页面刷新时直接清空 - }), - }, - ), -); - -// 导出便捷的选择器函数 -export const useCurrentContact = () => - useWeChatStore(state => state.currentContract); -export const useCurrentMessages = () => - useWeChatStore(state => state.currentMessages); -export const useMessagesLoading = () => - useWeChatStore(state => state.messagesLoading); diff --git a/Cunkebao/src/store/module/websocket/msg.data.ts b/Cunkebao/src/store/module/websocket/msg.data.ts deleted file mode 100644 index ec1a29c7..00000000 --- a/Cunkebao/src/store/module/websocket/msg.data.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ChatRecord } from "@/pages/pc/ckbox/data"; -export interface Messages { - friendMessage?: ChatRecord | null; - chatroomMessage?: ChatRecord | null; - seq: number; - cmdType: string; -} diff --git a/Cunkebao/src/store/module/websocket/msgManage.ts b/Cunkebao/src/store/module/websocket/msgManage.ts deleted file mode 100644 index 92ec518c..00000000 --- a/Cunkebao/src/store/module/websocket/msgManage.ts +++ /dev/null @@ -1,117 +0,0 @@ -//消息管理器 -import { deepCopy } from "@/utils/common"; -import { WebSocketMessage } from "./websocket"; -import { getkfUserList, asyncKfUserList } from "@/store/module/ckchat/ckchat"; -import { Messages } from "./msg.data"; - -import { useWeChatStore } from "@/store/module/weChat/weChat"; -// 消息处理器类型定义 -type MessageHandler = (message: WebSocketMessage) => void; -const setVideoUrl = useWeChatStore.getState().setVideoUrl; -const addMessage = useWeChatStore.getState().addMessage; -const receivedMsg = useWeChatStore.getState().receivedMsg; - -// 消息处理器映射 -const messageHandlers: Record = { - // 微信账号存活状态响应 - CmdRequestWechatAccountsAliveStatusResp: message => { - // console.log("微信账号存活状态响应", message); - // 获取客服列表 - const kfUserList = deepCopy(getkfUserList()); - const wechatAccountsAliveStatus = message.wechatAccountsAliveStatus || {}; - // 遍历客服列表,更新存活状态 - kfUserList.forEach(kfUser => { - kfUser.isOnline = wechatAccountsAliveStatus[kfUser.id]; - }); - asyncKfUserList(kfUserList); - }, - // 发送消息响应 - CmdSendMessageResp: message => { - console.log("发送消息响应", message); - addMessage(message.friendMessage || message.chatroomMessage); - // 在这里添加具体的处理逻辑 - }, - CmdSendMessageResult: message => { - console.log("发送消息结果", message); - // 在这里添加具体的处理逻辑 - }, - // 接收消息响应 - CmdReceiveMessageResp: message => { - console.log("接收消息响应", message); - addMessage(message.friendMessage || message.chatroomMessage); - // 在这里添加具体的处理逻辑 - }, - //收到消息 - CmdNewMessage: (message: Messages) => { - // 在这里添加具体的处理逻辑 - receivedMsg(message.friendMessage || message.chatroomMessage); - }, - CmdFriendInfoChanged: message => { - // console.log("好友信息变更", message); - // 在这里添加具体的处理逻辑 - }, - - // 登录响应 - CmdSignInResp: message => { - console.log("登录响应", message); - // 在这里添加具体的处理逻辑 - }, - - // 通知消息 - CmdNotify: message => { - console.log("通知消息", message); - // 在这里添加具体的处理逻辑 - if (message.notify == "Kicked out") { - // 被踢出时直接跳转到登录页面 - window.location.href = "/login"; - } - }, - - CmdDownloadVideoResult: message => { - // 在这里添加具体的处理逻辑 - setVideoUrl(message.friendMessageId, message.url); - }, - - // 可以继续添加更多处理器... -}; - -// 默认处理器 -const defaultHandler: MessageHandler = message => { - console.log("未知消息类型", message.cmdType, message); -}; - -// 注册新的消息处理器 -export const registerMessageHandler = ( - cmdType: string, - handler: MessageHandler, -) => { - messageHandlers[cmdType] = handler; -}; - -// 移除消息处理器 -export const unregisterMessageHandler = (cmdType: string) => { - delete messageHandlers[cmdType]; -}; - -// 获取所有已注册的消息类型 -export const getRegisteredMessageTypes = (): string[] => { - return Object.keys(messageHandlers); -}; - -// 消息管理核心函数 -export const msgManageCore = (message: WebSocketMessage) => { - const cmdType = message.cmdType; - if (!cmdType) { - console.warn("消息缺少cmdType字段", message); - return; - } - - // 获取对应的处理器,如果没有则使用默认处理器 - const handler = messageHandlers[cmdType] || defaultHandler; - - try { - handler(message); - } catch (error) { - console.error(`处理消息类型 ${cmdType} 时发生错误:`, error); - } -}; diff --git a/Cunkebao/src/store/module/websocket/sendMessages.ts b/Cunkebao/src/store/module/websocket/sendMessages.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/Cunkebao/src/store/module/websocket/websocket.ts b/Cunkebao/src/store/module/websocket/websocket.ts deleted file mode 100644 index 46f9ed18..00000000 --- a/Cunkebao/src/store/module/websocket/websocket.ts +++ /dev/null @@ -1,586 +0,0 @@ -import { createPersistStore } from "@/store/createPersistStore"; -import { Toast } from "antd-mobile"; -import { useUserStore } from "../user"; -import { useCkChatStore } from "@/store/module/ckchat/ckchat"; -const { getAccountId } = useCkChatStore.getState(); -import { msgManageCore } from "./msgManage"; -// WebSocket消息类型 -export interface WebSocketMessage { - cmdType?: string; - seq?: number; - wechatAccountIds?: string[]; - content?: any; - [key: string]: any; -} - -// WebSocket连接状态 -export enum WebSocketStatus { - DISCONNECTED = "disconnected", - CONNECTING = "connecting", - CONNECTED = "connected", - RECONNECTING = "reconnecting", - ERROR = "error", -} - -// WebSocket配置 -interface WebSocketConfig { - url: string; - client: string; - accountId: number; - accessToken: string; - autoReconnect: boolean; - cmdType: string; - seq: number; - reconnectInterval: number; - maxReconnectAttempts: number; - [key: string]: any; -} - -interface WebSocketState { - // 连接状态 - status: WebSocketStatus; - ws: WebSocket | null; - - // 配置信息 - config: WebSocketConfig | null; - - // 消息相关 - messages: WebSocketMessage[]; - unreadCount: number; - - // 重连相关 - reconnectAttempts: number; - reconnectTimer: NodeJS.Timeout | null; - aliveStatusTimer: NodeJS.Timeout | null; // 客服用户状态查询定时器 - - // 方法 - connect: (config: Partial) => void; - disconnect: () => void; - sendMessage: (message: Omit) => void; - sendCommand: (cmdType: string, data?: any) => void; - clearMessages: () => void; - markAsRead: () => void; - reconnect: () => void; - clearConnectionState: () => void; // 清空连接状态 - - // 内部方法 - _handleOpen: () => void; - _handleMessage: (event: MessageEvent) => void; - _handleClose: (event: CloseEvent) => void; - _handleError: (event: Event) => void; - _startReconnectTimer: () => void; - _stopReconnectTimer: () => void; - _startAliveStatusTimer: () => void; // 启动客服状态查询定时器 - _stopAliveStatusTimer: () => void; // 停止客服状态查询定时器 -} - -// 默认配置 -const DEFAULT_CONFIG: WebSocketConfig = { - url: "wss://kf.quwanzhi.com:9993", - client: "kefu-client", - accountId: 0, - accessToken: "", - autoReconnect: true, - cmdType: "", // 添加默认的命令类型 - seq: +new Date(), // 添加默认的序列号 - reconnectInterval: 3000, - maxReconnectAttempts: 5, -}; - -export const useWebSocketStore = createPersistStore( - (set, get) => ({ - status: WebSocketStatus.DISCONNECTED, - ws: null, - config: null, - messages: [], - unreadCount: 0, - reconnectAttempts: 0, - reconnectTimer: null, - aliveStatusTimer: null, - - // 连接WebSocket - connect: (config: Partial) => { - const currentState = get(); - - // 检查当前连接状态,避免重复连接 - if ( - currentState.status === WebSocketStatus.CONNECTED || - currentState.status === WebSocketStatus.CONNECTING - ) { - // console.log("WebSocket已连接或正在连接,跳过重复连接", { - // currentStatus: currentState.status, - // hasWebSocket: !!currentState.ws, - // }); - return; - } - - // 如果已经有WebSocket实例,先断开 - if (currentState.ws) { - // console.log("断开现有WebSocket连接"); - currentState.disconnect(); - } - - // 合并配置 - const fullConfig: WebSocketConfig = { - ...DEFAULT_CONFIG, - ...config, - }; - - // 获取用户信息 - const { token2 } = useUserStore.getState(); - - if (!token2) { - Toast.show({ content: "未找到有效的访问令牌", position: "top" }); - return; - } - - // 构建WebSocket URL - const params = new URLSearchParams({ - client: fullConfig.client.toString(), - accountId: getAccountId().toString(), - accessToken: token2, - t: Date.now().toString(), - }); - - const wsUrl = fullConfig.url + "?" + params; - - // 检查URL是否为localhost,如果是则不连接 - if (wsUrl.includes("localhost") || wsUrl.includes("127.0.0.1")) { - // console.error("WebSocket连接被拦截:不允许连接到本地地址", wsUrl); - Toast.show({ - content: "WebSocket连接被拦截:不允许连接到本地地址", - position: "top", - }); - set({ status: WebSocketStatus.ERROR }); - return; - } - - set({ - status: WebSocketStatus.CONNECTING, - config: fullConfig, - }); - - try { - const ws = new WebSocket(wsUrl); - - // 绑定事件处理器 - ws.onopen = () => get()._handleOpen(); - ws.onmessage = event => get()._handleMessage(event); - ws.onclose = event => get()._handleClose(event); - ws.onerror = event => get()._handleError(event); - - set({ ws }); - - // console.log("WebSocket连接创建成功", wsUrl); - } catch (error) { - // console.error("WebSocket连接失败:", error); - set({ status: WebSocketStatus.ERROR }); - Toast.show({ content: "WebSocket连接失败", position: "top" }); - } - }, - - // 断开连接 - disconnect: () => { - const currentState = get(); - - if (currentState.ws) { - currentState.ws.close(); - } - - currentState._stopReconnectTimer(); - currentState._stopAliveStatusTimer(); - - set({ - status: WebSocketStatus.DISCONNECTED, - ws: null, - reconnectAttempts: 0, - }); - - // console.log("WebSocket连接已断开"); - }, - - // 发送消息 - sendMessage: message => { - const currentState = get(); - - if ( - currentState.status !== WebSocketStatus.CONNECTED || - !currentState.ws - ) { - Toast.show({ content: "WebSocket未连接", position: "top" }); - return; - } - - const fullMessage: WebSocketMessage = { - ...message, - }; - - try { - currentState.ws.send(JSON.stringify(fullMessage)); - // console.log("消息发送成功:", fullMessage); - } catch (error) { - // console.error("消息发送失败:", error); - Toast.show({ content: "消息发送失败", position: "top" }); - } - }, - - // 发送命令 - sendCommand: (cmdType: string, data?: any) => { - const currentState = get(); - - if ( - currentState.status !== WebSocketStatus.CONNECTED || - !currentState.ws - ) { - Toast.show({ - content: "WebSocket未连接,正在重新连接...", - position: "top", - }); - - // 重置连接状态并发起重新连接 - set({ status: WebSocketStatus.DISCONNECTED }); - if (currentState.config) { - currentState.connect(currentState.config); - } - return; - } - - const command = { - cmdType, - ...data, - seq: +new Date(), - }; - - try { - currentState.ws.send(JSON.stringify(command)); - // console.log("命令发送成功:", command); - } catch (error) { - // console.error("命令发送失败:", error); - Toast.show({ content: "命令发送失败", position: "top" }); - - // 发送失败时也尝试重新连接 - set({ status: WebSocketStatus.DISCONNECTED }); - if (currentState.config) { - currentState.connect(currentState.config); - } - } - }, - - // 清除消息 - clearMessages: () => { - set({ messages: [], unreadCount: 0 }); - }, - - // 标记为已读 - markAsRead: () => { - set({ unreadCount: 0 }); - }, - - // 重连 - reconnect: () => { - const currentState = get(); - - if (currentState.config) { - // 检查是否允许重连 - if (!currentState.config.autoReconnect) { - // console.log("自动重连已禁用,不再尝试重连"); - return; - } - currentState.connect(currentState.config); - } - }, - - // 清空连接状态(用于退出登录时) - clearConnectionState: () => { - const currentState = get(); - - // 断开现有连接 - if (currentState.ws) { - currentState.ws.close(); - } - - // 停止所有定时器 - currentState._stopReconnectTimer(); - currentState._stopAliveStatusTimer(); - - // 重置所有状态 - set({ - status: WebSocketStatus.DISCONNECTED, - ws: null, - config: null, - messages: [], - unreadCount: 0, - reconnectAttempts: 0, - reconnectTimer: null, - aliveStatusTimer: null, - }); - - // console.log("WebSocket连接状态已清空"); - }, - - // 内部方法:处理连接打开 - _handleOpen: () => { - const currentState = get(); - - set({ - status: WebSocketStatus.CONNECTED, - reconnectAttempts: 0, - }); - - // console.log("WebSocket连接成功"); - const { token2 } = useUserStore.getState(); - // 发送登录命令 - if (currentState.config) { - currentState.sendCommand("CmdSignIn", { - accessToken: token2, - accountId: Number(getAccountId()), - client: currentState.config?.client || "kefu-client", - seq: +new Date(), - }); - } - - Toast.show({ content: "WebSocket连接成功", position: "top" }); - - // 启动客服状态查询定时器 - currentState._startAliveStatusTimer(); - }, - - // 内部方法:处理消息接收 - _handleMessage: (event: MessageEvent) => { - try { - const data = JSON.parse(event.data); - // console.log("收到WebSocket消息:", data); - - // 处理特定的通知消息 - if (data.cmdType === "CmdNotify") { - // 处理Auth failed通知 - if (data.notify === "Auth failed" || data.notify === "Kicked out") { - // console.error(`WebSocket ${data.notify},断开连接`); - Toast.show({ - content: `WebSocket ${data.notify},断开连接`, - position: "top", - }); - - // 禁用自动重连 - if (get().config) { - set({ - config: { - ...get().config!, - autoReconnect: false, - }, - }); - } - - // 停止客服状态查询定时器 - get()._stopAliveStatusTimer(); - - // 断开连接 - get().disconnect(); - return; - } - } - - const currentState = get(); - const newMessage: WebSocketMessage = { - id: Date.now().toString(), - type: data.type || "message", - content: data, - timestamp: Date.now(), - sender: data.sender, - receiver: data.receiver, - }; - - set({ - messages: [...currentState.messages, newMessage], - unreadCount: currentState.unreadCount + 1, - }); - //消息处理器 - msgManageCore(data); - - // 可以在这里添加消息处理逻辑 - // 比如播放提示音、显示通知等 - } catch (error) { - // console.error("解析WebSocket消息失败:", error); - } - }, - - // 内部方法:处理连接关闭 - _handleClose: (event: CloseEvent) => { - const currentState = get(); - - // console.log("WebSocket连接关闭:", event.code, event.reason); - - set({ - status: WebSocketStatus.DISCONNECTED, - ws: null, - }); - - // 自动重连逻辑 - if ( - currentState.config?.autoReconnect && - currentState.reconnectAttempts < - (currentState.config?.maxReconnectAttempts || 5) - ) { - // console.log("尝试自动重连..."); - currentState._startReconnectTimer(); - } else if (!currentState.config?.autoReconnect) { - // console.log("自动重连已禁用,不再尝试重连"); - // 重置重连计数 - set({ reconnectAttempts: 0 }); - } - }, - - // 内部方法:处理连接错误 - _handleError: (event: Event) => { - // console.error("WebSocket连接错误:", event); - - set({ status: WebSocketStatus.ERROR }); - - Toast.show({ content: "WebSocket连接错误", position: "top" }); - }, - - // 内部方法:启动重连定时器 - _startReconnectTimer: () => { - const currentState = get(); - - currentState._stopReconnectTimer(); - - set({ - status: WebSocketStatus.RECONNECTING, - reconnectAttempts: currentState.reconnectAttempts + 1, - }); - - const timer = setTimeout(() => { - // console.log( - // `尝试重连 (${currentState.reconnectAttempts + 1}/${currentState.config?.maxReconnectAttempts})`, - // ); - currentState.reconnect(); - }, currentState.config?.reconnectInterval || 3000); - - set({ reconnectTimer: timer }); - }, - - // 内部方法:停止重连定时器 - _stopReconnectTimer: () => { - const currentState = get(); - - if (currentState.reconnectTimer) { - clearTimeout(currentState.reconnectTimer); - set({ reconnectTimer: null }); - } - }, - - // 内部方法:启动客服状态查询定时器 - _startAliveStatusTimer: () => { - const currentState = get(); - - // 先停止现有定时器 - currentState._stopAliveStatusTimer(); - - // 获取客服用户列表 - const { kfUserList } = useCkChatStore.getState(); - - // 如果没有客服用户,不启动定时器 - if (!kfUserList || kfUserList.length === 0) { - return; - } - - // 启动定时器,每5秒查询一次 - const timer = setInterval(() => { - const state = get(); - // 检查连接状态 - if (state.status === WebSocketStatus.CONNECTED) { - const { kfUserList: currentKfUserList } = useCkChatStore.getState(); - if (currentKfUserList && currentKfUserList.length > 0) { - state.sendCommand("CmdRequestWechatAccountsAliveStatus", { - wechatAccountIds: currentKfUserList.map(v => v.id), - }); - } - } else { - // 如果连接断开,停止定时器 - state._stopAliveStatusTimer(); - } - }, 5 * 1000); - - set({ aliveStatusTimer: timer }); - }, - - // 内部方法:停止客服状态查询定时器 - _stopAliveStatusTimer: () => { - const currentState = get(); - - if (currentState.aliveStatusTimer) { - clearInterval(currentState.aliveStatusTimer); - set({ aliveStatusTimer: null }); - } - }, - }), - { - name: "websocket-store", - partialize: state => ({ - // 只持久化必要的状态,不持久化WebSocket实例 - status: state.status, - config: state.config, - messages: state.messages.slice(-100), // 只保留最近100条消息 - unreadCount: state.unreadCount, - reconnectAttempts: state.reconnectAttempts, - // 注意:定时器不需要持久化,重新连接时会重新创建 - }), - onRehydrateStorage: () => state => { - // 页面刷新后,如果之前是连接状态,尝试重新连接 - if (state && state.status === WebSocketStatus.CONNECTED && state.config) { - // console.log("页面刷新后恢复WebSocket连接", { - // persistedConfig: state.config, - // currentDefaultConfig: DEFAULT_CONFIG, - // }); - - // 使用最新的默认配置,而不是持久化的配置 - const freshConfig = { - ...DEFAULT_CONFIG, - client: state.config.client, - accountId: state.config.accountId, - accessToken: state.config.accessToken, - autoReconnect: state.config.autoReconnect, - }; - - // console.log("使用刷新后的配置重连:", freshConfig); - - // 延迟一下再重连,确保页面完全加载 - // 同时检查当前状态,避免重复连接 - setTimeout(() => { - // 重新获取最新的状态,而不是使用闭包中的state - const currentState = useWebSocketStore.getState(); - // console.log("页面刷新后检查状态", { - // status: currentState.status, - // hasWs: !!currentState.ws, - // }); - - // 强制重置状态为disconnected,因为页面刷新后WebSocket实例已失效 - if ( - currentState.status === WebSocketStatus.CONNECTED && - !currentState.ws - ) { - // console.log("检测到状态不一致,重置为disconnected"); - useWebSocketStore.setState({ - status: WebSocketStatus.DISCONNECTED, - }); - } - - // 重新获取状态进行连接 - const latestState = useWebSocketStore.getState(); - if ( - latestState.status === WebSocketStatus.DISCONNECTED || - latestState.status === WebSocketStatus.ERROR - ) { - // console.log("页面刷新后开始重连"); - latestState.connect(freshConfig); - } else { - // console.log("WebSocket已连接或正在连接,跳过页面刷新重连", { - // status: latestState.status, - // }); - } - }, 1000); - } - }, - }, -);