From a7124c800eb4b209d1b2b926a67820a909e5ecf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Tue, 16 Sep 2025 17:40:02 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E8=A7=A6?= =?UTF-8?q?=E5=AE=A2=E5=AE=9D=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81=E5=8F=8A?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: 为朋友圈功能添加点赞和评论交互区域样式 style: 优化朋友圈组件代码结构,增加类型定义 --- Cunkebao/src/pages/login/Login.tsx | 9 +- Cunkebao/src/pages/mobile/mine/main/index.tsx | 10 - Cunkebao/src/store/module/ckchat/api.ts | 43 -- .../src/store/module/ckchat/ckchat.data.ts | 72 --- Cunkebao/src/store/module/ckchat/ckchat.ts | 527 ---------------- .../src/store/module/weChat/weChat.data.ts | 33 - Cunkebao/src/store/module/weChat/weChat.ts | 287 --------- .../src/store/module/websocket/msg.data.ts | 7 - .../src/store/module/websocket/msgManage.ts | 117 ---- .../store/module/websocket/sendMessages.ts | 0 .../src/store/module/websocket/websocket.ts | 586 ------------------ .../FriendsCicle/index.module.scss | 57 ++ .../SidebarMenu/FriendsCicle/index.tsx | 279 ++++++--- 13 files changed, 263 insertions(+), 1764 deletions(-) delete mode 100644 Cunkebao/src/store/module/ckchat/api.ts delete mode 100644 Cunkebao/src/store/module/ckchat/ckchat.data.ts delete mode 100644 Cunkebao/src/store/module/ckchat/ckchat.ts delete mode 100644 Cunkebao/src/store/module/weChat/weChat.data.ts delete mode 100644 Cunkebao/src/store/module/weChat/weChat.ts delete mode 100644 Cunkebao/src/store/module/websocket/msg.data.ts delete mode 100644 Cunkebao/src/store/module/websocket/msgManage.ts delete mode 100644 Cunkebao/src/store/module/websocket/sendMessages.ts delete mode 100644 Cunkebao/src/store/module/websocket/websocket.ts diff --git a/Cunkebao/src/pages/login/Login.tsx b/Cunkebao/src/pages/login/Login.tsx index 972710b2..d1db021e 100644 --- a/Cunkebao/src/pages/login/Login.tsx +++ b/Cunkebao/src/pages/login/Login.tsx @@ -1,5 +1,4 @@ import React, { useState, useEffect } from "react"; -import { useCkChatStore } from "@/store/module/ckchat/ckchat"; import { Form, Input, Button, Toast, Checkbox } from "antd-mobile"; import { EyeInvisibleOutline, @@ -7,7 +6,6 @@ import { UserOutline, } from "antd-mobile-icons"; import { useUserStore } from "@/store/module/user"; -import { useWebSocketStore } from "@/store/module/websocket/websocket"; import { loginWithPassword, loginWithCode, sendVerificationCode } from "./api"; import style from "./login.module.scss"; @@ -19,7 +17,6 @@ const Login: React.FC = () => { const [countdown, setCountdown] = useState(0); const [showPassword, setShowPassword] = useState(false); const [agreeToTerms, setAgreeToTerms] = useState(false); - const { setUserInfo } = useCkChatStore.getState(); const { login, login2 } = useUserStore(); // 倒计时效果 @@ -75,13 +72,9 @@ const Login: React.FC = () => { : loginWithCode(loginParams); response.then(res => { - const { member, kefuData, deviceTotal } = res; + const { member, deviceTotal } = res; // 清空WebSocket连接状态 - useWebSocketStore.getState().clearConnectionState(); login(res.token, member, deviceTotal); - const { self, token } = kefuData; - login2(token.access_token); - setUserInfo(self); }); }; diff --git a/Cunkebao/src/pages/mobile/mine/main/index.tsx b/Cunkebao/src/pages/mobile/mine/main/index.tsx index 66450792..d2e56cea 100644 --- a/Cunkebao/src/pages/mobile/mine/main/index.tsx +++ b/Cunkebao/src/pages/mobile/mine/main/index.tsx @@ -84,16 +84,6 @@ const Mine: React.FC = () => { bgColor: "#fff7e6", iconColor: "#fa8c16", }, - { - id: "ckb", - title: "触客宝", - description: "触客宝", - icon: , - count: 0, - path: "/ckbox/weChat", - bgColor: "#fff7e6", - iconColor: "#fa8c16", - }, ]; // 加载统计数据 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); - } - }, - }, -); diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss index 876ccf6e..ddb2a15f 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.module.scss @@ -218,6 +218,63 @@ } } } + + // 点赞和评论交互区域 + .interactionArea { + margin-top: 8px; + padding: 8px 12px; + background-color: #f7f7f7; + border-radius: 4px; + font-size: 13px; + + .likeArea { + display: flex; + align-items: center; + margin-bottom: 4px; + + .likeIcon { + color: #ff6b6b; + margin-right: 6px; + font-size: 12px; + } + + .likeList { + color: #576b95; + + span { + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + } + } + + .commentArea { + .commentItem { + margin-bottom: 2px; + line-height: 1.4; + + .commentUser { + color: #576b95; + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + + .commentSeparator { + color: #666; + } + + .commentContent { + color: #333; + } + } + } + } } } diff --git a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx index da7693ad..d8938386 100644 --- a/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx +++ b/Touchkebao/src/pages/pc/ckbox/weChat/components/SidebarMenu/FriendsCicle/index.tsx @@ -10,16 +10,47 @@ import { import { InfiniteScroll } from "antd-mobile"; import styles from "./index.module.scss"; +// 评论数据类型 +interface CommentItem { + commentArg: number; + commentId1: number; + commentId2: number; + commentTime: number; + content: string; + nickName: string; + wechatId: string; +} + +// 点赞数据类型 +interface LikeItem { + createTime: number; + nickName: string; + wechatId: string; +} + +// 朋友圈实体数据类型 +interface MomentEntity { + content: string; + createTime: number; + lat: number; + lng: number; + location: string; + objectType: number; + picSize: number; + resUrls: string[]; + snsId: string; + urls: string[]; + userName: string; +} + // 朋友圈数据类型定义 interface FriendsCircleItem { - id: string; - avatar: string; - username: string; - content: string; - images?: string[]; - time: string; - likes?: number; - comments?: number; + commentList: CommentItem[]; + createTime: number; + likeList: LikeItem[]; + momentEntity: MomentEntity; + snsId: string; + type: number; } // API响应类型 @@ -39,60 +70,83 @@ interface PaginationParams { // 模拟朋友圈数据 const mockFriendsCircleData: FriendsCircleItem[] = [ { - id: "1", - avatar: "", - username: "我的朋友圈", - content: "", - time: "", + commentList: [ + { + commentArg: 2, + commentId1: 0, + commentId2: 35, + commentTime: 1758011325, + content: "测试评论", + nickName: "老坑爹- 解放双手,释放时间", + wechatId: "wxid_480es52qsj2812", + }, + ], + createTime: 1757258659, + likeList: [ + { + createTime: 1757315556, + nickName: "老坑爹- 解放双手,释放时间", + wechatId: "wxid_480es52qsj2812", + }, + ], + momentEntity: { + content: "没看到血月[旺柴]", + createTime: 1757258659, + lat: 0, + lng: 0, + location: "", + objectType: 1, + picSize: 0, + resUrls: [ + "https://ac-weremote-s2.oss-cn-shenzhen.aliyuncs.com/weremote/chat-logs/5E2C38F5A275450D935F3ECEC076124E/aa6d4c2f7b1fe24d04d34f4f409883e6/sns/wxid_480es52qsj2812/-3705790026851937712/-3705790026851937712-14740954047910318662.jpg", + ], + snsId: "-3705790026851937712", + urls: ["/sns/3/3/snst_14740954047910318662"], + userName: "wxid_dlhi90odctcl22", + }, + snsId: "-3705790026851937712", + type: 1, }, { - id: "2", - avatar: "", - username: "朋友圈广场", - content: "", - time: "", + commentList: [], + createTime: 1757258600, + likeList: [], + momentEntity: { + content: + "🎉🎊🎈欢迎小伙伴加入单群聊客宝地盘思慕斯蛋糕的小伙伴们的支持与信任!!!", + createTime: 1757258600, + lat: 0, + lng: 0, + location: "", + objectType: 1, + picSize: 0, + resUrls: ["/public/assets/face/1.png"], + snsId: "-3705790026851937713", + urls: ["/sns/3/3/snst_14740954047910318663"], + userName: "wxid_dlhi90odctcl23", + }, + snsId: "-3705790026851937713", + type: 1, }, { - id: "3", - avatar: "/public/assets/face/1.png", - username: "老坑爹-解放双手,释放时间", - content: - "🎉🎊🎈欢迎小伙伴加入单群聊客宝地盘思慕斯蛋糕的小伙伴们的支持与信任!!!", - images: ["/public/assets/face/1.png"], - time: "2025年9月16日 13:48", - likes: 0, - comments: 0, - }, - { - id: "4", - avatar: "/public/assets/face/1.png", - username: "老坑爹-解放双手,释放时间", - content: "一整年卡1好的产品有用户的好评是买卖说的再多不如用户的有说服力", - images: ["/public/assets/face/1.png"], - time: "2025年9月16日 11:33", - likes: 0, - comments: 0, - }, - { - id: "5", - avatar: "/public/assets/face/1.png", - username: "老坑爹-解放双手,释放时间", - content: - "两个小时637朵卡今天的努力也是给我自己最好的礼物🎁坚持就是胜利第二年开干。", - images: ["/public/assets/face/1.png"], - time: "2025年9月16日 11:03", - likes: 0, - comments: 0, - }, - { - id: "6", - avatar: "/public/assets/face/1.png", - username: "老坑爹-解放双手,释放时间", - content: "老坑爹如果不幸苦,没有品质保障,客户会无限复购?", - images: ["/public/assets/face/1.png"], - time: "2025年9月16日 10:33", - likes: 0, - comments: 0, + commentList: [], + createTime: 1757258500, + likeList: [], + momentEntity: { + content: "一整年卡1好的产品有用户的好评是买卖说的再多不如用户的有说服力", + createTime: 1757258500, + lat: 0, + lng: 0, + location: "", + objectType: 1, + picSize: 0, + resUrls: ["/public/assets/face/1.png"], + snsId: "-3705790026851937714", + urls: ["/sns/3/3/snst_14740954047910318664"], + userName: "wxid_dlhi90odctcl24", + }, + snsId: "-3705790026851937714", + type: 1, }, ]; @@ -118,9 +172,9 @@ const FriendsCircle: React.FC = () => { const { pageNum, pageSize, type } = params; const startIndex = (pageNum - 1) * pageSize; - // 使用原有的模拟数据 - const allData = mockFriendsCircleData.slice(2); // 排除前两个特殊项 - const typeData = type === "my" ? allData.slice(0, 2) : allData.slice(2); + // 使用模拟数据 + const allData = mockFriendsCircleData; + const typeData = type === "my" ? allData.slice(0, 1) : allData; const paginatedData = typeData.slice(startIndex, startIndex + pageSize); return { @@ -222,26 +276,57 @@ const FriendsCircle: React.FC = () => { console.log("评论:", id); }; + // 格式化时间戳 + const formatTime = (timestamp: number) => { + const date = new Date(timestamp * 1000); + return date.toLocaleString("zh-CN", { + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + }); + }; + + // 获取用户昵称 + const getUserNickName = (item: FriendsCircleItem) => { + // 优先从点赞列表或评论列表中获取昵称 + if (item.likeList.length > 0) { + return item.likeList[0].nickName; + } + if (item.commentList.length > 0) { + return item.commentList[0].nickName; + } + return item.momentEntity.userName; + }; + const renderNormalItem = (item: FriendsCircleItem, isNotMy?: boolean) => { + const nickName = getUserNickName(item); + const content = item.momentEntity.content; + const images = item.momentEntity.resUrls; + const time = formatTime(item.createTime); + const likesCount = item.likeList.length; + const commentsCount = item.commentList.length; + return (
{isNotMy && (
- +
)}
-
{item.username}
+
{nickName}
-
{item.content}
- {item.images && item.images.length > 0 && ( +
{content}
+ {images && images.length > 0 && (
- {item.images.map((image, index) => ( + {images.map((image, index) => ( {
)} -
查看图片
+ {images && images.length > 0 && ( +
查看图片
+ )}
-
{item.time}
+
{time}
+ + {/* 点赞和评论区域 */} + {(item.likeList.length > 0 || item.commentList.length > 0) && ( +
+ {/* 点赞列表 */} + {item.likeList.length > 0 && ( +
+ + + {item.likeList.map((like, index) => ( + + {like.nickName} + {index < item.likeList.length - 1 && "、"} + + ))} + +
+ )} + + {/* 评论列表 */} + {item.commentList.length > 0 && ( +
+ {item.commentList.map(comment => ( +
+ + {comment.nickName} + + : + + {comment.content} + +
+ ))} +
+ )} +
+ )}
); @@ -284,7 +415,7 @@ const FriendsCircle: React.FC = () => { {myCircleData.length > 0 ? ( <> {myCircleData.map(item => ( -
+
{renderNormalItem(item, false)}
))} @@ -317,7 +448,7 @@ const FriendsCircle: React.FC = () => { {squareData.length > 0 ? ( <> {squareData.map(item => ( -
+
{renderNormalItem(item, true)}
))} From 81e0f2307566f562fcffd1fb73ff009d1828d456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Tue, 16 Sep 2025 17:46:08 +0800 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E4=BA=A7=E7=89=A9=E5=92=8C.gitignore=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加dist/*到.gitignore以避免提交构建产物 - 更新Vite构建生成的资源文件哈希值 --- Cunkebao/.gitignore | 3 ++- Cunkebao/dist/.vite/manifest.json | 36 +++++++++++++++---------------- Cunkebao/dist/index.html | 12 +++++------ 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Cunkebao/.gitignore b/Cunkebao/.gitignore index dcf55aed..a2bf4a07 100644 --- a/Cunkebao/.gitignore +++ b/Cunkebao/.gitignore @@ -3,4 +3,5 @@ dist/ build/ yarn.lock .env -.DS_Store \ No newline at end of file +.DS_Store +dist/* diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json index 23344959..994665e2 100644 --- a/Cunkebao/dist/.vite/manifest.json +++ b/Cunkebao/dist/.vite/manifest.json @@ -1,50 +1,50 @@ { - "_charts-DsEZaGAW.js": { - "file": "assets/charts-DsEZaGAW.js", + "_charts-B449e2xS.js": { + "file": "assets/charts-B449e2xS.js", "name": "charts", "imports": [ - "_ui-YC29IQHT.js", - "_vendor-Bq99rrm8.js" + "_ui-DDu9FCjt.js", + "_vendor-0WYR1k4q.js" ] }, "_ui-D0C0OGrH.css": { "file": "assets/ui-D0C0OGrH.css", "src": "_ui-D0C0OGrH.css" }, - "_ui-YC29IQHT.js": { - "file": "assets/ui-YC29IQHT.js", + "_ui-DDu9FCjt.js": { + "file": "assets/ui-DDu9FCjt.js", "name": "ui", "imports": [ - "_vendor-Bq99rrm8.js" + "_vendor-0WYR1k4q.js" ], "css": [ "assets/ui-D0C0OGrH.css" ] }, - "_utils-Ft3ushmX.js": { - "file": "assets/utils-Ft3ushmX.js", + "_utils-DC06x9DY.js": { + "file": "assets/utils-DC06x9DY.js", "name": "utils", "imports": [ - "_vendor-Bq99rrm8.js" + "_vendor-0WYR1k4q.js" ] }, - "_vendor-Bq99rrm8.js": { - "file": "assets/vendor-Bq99rrm8.js", + "_vendor-0WYR1k4q.js": { + "file": "assets/vendor-0WYR1k4q.js", "name": "vendor" }, "index.html": { - "file": "assets/index-d8oC2PBC.js", + "file": "assets/index-DzNmnMYg.js", "name": "index", "src": "index.html", "isEntry": true, "imports": [ - "_vendor-Bq99rrm8.js", - "_ui-YC29IQHT.js", - "_utils-Ft3ushmX.js", - "_charts-DsEZaGAW.js" + "_vendor-0WYR1k4q.js", + "_ui-DDu9FCjt.js", + "_utils-DC06x9DY.js", + "_charts-B449e2xS.js" ], "css": [ - "assets/index-D8Ews0CA.css" + "assets/index-QrS4Cvyc.css" ] } } \ No newline at end of file diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html index 693dadfc..0eea1718 100644 --- a/Cunkebao/dist/index.html +++ b/Cunkebao/dist/index.html @@ -11,13 +11,13 @@ - - - - - + + + + + - +