import { create } from 'zustand'; import { RealTimeAPI } from '@/channel/realTimeAPI'; import { olog, isEmpty, groupBy, sortArrayByOrder, logWebsocket, pick, sortKeys, omit, sortObjectsByKeysMap, clean7DaysWebsocketLog } from '@/utils/commons'; import { receivedMsgTypeMapped, handleNotification } from '@/channel/bubbleMsgUtils'; import { fetchConversationsList, fetchTemplates, fetchConversationsSearch, UNREAD_MARK, fetchTags } from '@/actions/ConversationActions'; import { devtools } from 'zustand/middleware'; import { WS_URL, DATETIME_FORMAT } from '@/config'; import dayjs from 'dayjs'; const replaceObjectsByKey = (arr1, arr2, key) => { const map2 = new Map(arr2.map(ele => [ele[key], ele])); return arr1.map(item => map2.has(item[key]) ? map2.get(item[key]) : item); } const sortConversationList = (list) => { const mergedListMapped = groupBy(list, 'top_state'); const topValOrder = Object.keys(mergedListMapped).filter(ss => ss !== '1').sort((a, b) => b - a); const pagelist = topValOrder.reduce((r, topVal) => r.concat(mergedListMapped[String(topVal)]), []); return { topList: mergedListMapped['1'] || [], pageList: pagelist, } }; // const WS_URL = 'ws://202.103.68.144:8888/whatever/'; // const WS_URL = 'ws://120.79.9.217:10022/whatever/'; const conversationRow = { sn: '', opi_sn: '', coli_sn: '', coli_id: '', last_received_time: '', last_send_time: '', unread_msg_count: '', whatsapp_name: '', customer_name: '', whatsapp_phone_number: '', top_state: 0, session_type: 0, }; const initialConversationState = { // websocket: null, // websocketOpened: null, // websocketRetrying: null, // websocketRetrytimes: null, errors: [], // 错误信息 initialState: false, // templates: [], closedConversationsList: [], // 已关闭的对话列表 conversationsList: [], // 对话列表 topList: [], pageList: [], currentConversation: {}, // 当前对话 activeConversations: {}, // 激活的对话的消息列表: { [conversationId]: [] } referenceMsg: {}, complexMsg: {}, totalNotify: 0, msgListLoading: false, detailPopupOpen: false, wai: {}, }; const globalNotifySlice = (set) => ({ globalNotify: [], setGlobalNotify: (notify) => set(() => ({ globalNotify: notify })), addGlobalNotify: (notify) => set((state) => ({ globalNotify: [notify, ...state.globalNotify] })), removeGlobalNotify: (id) => set((state) => ({ globalNotify: state.globalNotify.filter(item => item.id !== id) })), clearGlobalNotify: () => set(() => ({ globalNotify: [] })), }) const waiSlice = (set) => ({ wai: {}, setWai: (wai) => set({ wai }), }); // 顾问的自定义标签 const tagsSlice = (set) => ({ tags: [], setTags: (tags) => set({ tags }), addTag: (tag) => set((state) => ({ tags: [...state.tags, tag] })), removeTag: (tag) => set((state) => ({ tags: state.tags.filter((t) => t.key !== tag.key) })), updateTag: (tag) => set((state) => ({ tags: state.tags.map((t) => (t.key === tag.key ? tag : t)) })), resetTags: () => set({ tags: [] }), }); // 会话筛选 const filterObj = { pagesize: '', search: '', otype: '', tags: [], loadNextPage: true, lastpagetime: '', lastactivetime: '', // dayjs().subtract(30, "days").format('YYYY-MM-DD 00:00'), // 30 days }; const filterSlice = (set) => ({ filter: structuredClone(filterObj), setFilter: (filter) => set(state => ({ filter: { ...state.filter, ...filter } })), setFilterSearch: (search) => set((state) => ({ filter: { ...state.filter, search } })), setFilterOtype: (otype) => set((state) => ({ filter: {...state.filter, otype } })), setFilterTags: (tags) => set((state) => ({ filter: {...state.filter, tags } })), setFilterLoadNextPage: (loadNextPage) => set((state) => ({ filter: {...state.filter, loadNextPage } })), resetFilter: () => set({ filter: structuredClone(filterObj) }), }) // WABA 模板 const templatesSlice = (set) => ({ templates: [], setTemplates: (templates) => set({ templates }), }); const websocketSlice = (set, get) => ({ websocket: null, websocketOpened: null, websocketRetrying: null, websocketRetrytimes: null, setWebsocket: (websocket) => set({ websocket }), setWebsocketOpened: (opened) => set({ websocketOpened: opened }), setWebsocketRetrying: (retrying) => set({ websocketRetrying: retrying }), setWebsocketRetrytimes: (retrytimes) => set({ websocketRetrytimes: retrytimes, websocketRetrying: retrytimes > 0 }), connectWebsocket: (userId) => { const { setWebsocket, setWebsocketOpened, setWebsocketRetrytimes, addError, handleMessage, activeConversations } = get(); const realtimeAPI = new RealTimeAPI( { url: `${WS_URL}?opisn=${userId || ''}&_spam=${Date.now().toString()}`, protocol: 'WhatsApp', }, () => { setWebsocketOpened(true); setWebsocketRetrytimes(0); }, () => { setWebsocketOpened(false); const newMsgList = Object.keys(activeConversations).reduce((acc, key) => { const newMsgList = activeConversations[key].slice(-10); acc[key] = newMsgList; return acc; }, {}); set({ activeConversations: newMsgList, currentConversation: {} }); }, (n) => setWebsocketRetrytimes(n) ); realtimeAPI.onError(() => addError('Error')); realtimeAPI.onMessage(handleMessage); realtimeAPI.onCompletion(() => addError('Connection broken')); olog('Connecting to websocket...'); setWebsocket(realtimeAPI); }, disconnectWebsocket: () => { const { websocket } = get(); if (websocket) websocket.disconnect(); return set({ websocket: null }); }, reconnectWebsocket: (userId) => { const { disconnectWebsocket, connectWebsocket } = get(); disconnectWebsocket(); setTimeout(() => { connectWebsocket(userId); }, 500); }, handleMessage: (data) => { // olog('websocket Message IN ⬇', JSON.stringify(data, null, 2)); logWebsocket(data, 'I'); // olog('websocket Messages ----', data); // console.log(data); const { updateMessageItem, sentOrReceivedNewMessage, addGlobalNotify, setWai, addToConversationList } = get(); const { errcode, errmsg, result } = data; if (!result) { return false; } let resultType = result?.action || result?.type; if (errcode !== 0) { // addError('Error Connecting to Server'); resultType = 'error'; } const msgObj = receivedMsgTypeMapped[resultType].getMsg(result); const msgRender = receivedMsgTypeMapped[resultType].contentToRender(msgObj); const msgUpdate = receivedMsgTypeMapped[resultType].contentToUpdate(msgObj); // console.log('msgRender msgUpdate', msgRender, msgUpdate); if ([ 'whatsapp.message.updated', 'message', 'error', 'email.updated', 'wai.message.updated', ].includes(resultType) && !isEmpty(msgUpdate)) { updateMessageItem(msgUpdate); } if (!isEmpty(msgRender)) { sentOrReceivedNewMessage(msgRender.conversationid, msgRender); handleNotification(msgRender.senderName, { body: msgRender?.text || `[ ${msgRender.type} ]`, ...(msgRender.type === 'photo' ? { image: msgRender.data.uri } : {}), }); } // 其他通知, 不是消息 if ([ 'email.action.received', ].includes(resultType)) { const msgNotify = receivedMsgTypeMapped[resultType].contentToNotify(msgObj); addGlobalNotify(msgNotify); } // WhatsApp creds update if ([ 'wai.creds.update' ].includes(resultType)) { const _data = receivedMsgTypeMapped[resultType].getMsg(result); setWai(_data) if (['offline', 'close'].includes(_data.status)) { const msgNotify = receivedMsgTypeMapped[resultType].contentToNotify(msgObj); addGlobalNotify(msgNotify); } // setTimeout(() => { // setWai({}); // 60s 后清空 // }, 60_000); } // 会话表 更新 if (['session.new', 'session.updated'].includes(resultType)) { const sessionList = receivedMsgTypeMapped[resultType].getMsg(result); addToConversationList(sessionList, 'top'); } // console.log('handleMessage*******************'); }, }); const referenceMsgSlice = (set) => ({ referenceMsg: {}, setReferenceMsg: (referenceMsg) => set({ referenceMsg }), }); const complexMsgSlice = (set) => ({ complexMsg: {}, setComplexMsg: (complexMsg) => set({ complexMsg }), }); const conversationSlice = (set, get) => ({ conversationsListLoading: false, conversationsList: [], currentConversation: {}, closedConversationsList: [], topList: [], pageList: [], setConversationsListLoading: (conversationsListLoading) => set({ conversationsListLoading }), /** * 首次加载 * 搜索结果 */ setConversationsList: (conversationsList) => { const { activeConversations, currentConversation } = get(); // 让当前会话显示在页面上 let _tmpCurrentMsgs = []; if (currentConversation.sn) { _tmpCurrentMsgs = activeConversations[currentConversation.sn]; } const conversationsMapped = conversationsList.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {}); if (currentConversation.sn) { const hasCurrent = Object.keys(conversationsMapped).findIndex(sn => Number(sn) === Number(currentConversation.sn)) !== -1; conversationsMapped[currentConversation.sn] = _tmpCurrentMsgs; const _len = hasCurrent ? 0 : conversationsList.unshift(currentConversation); } const { topList, pageList } = sortConversationList(conversationsList); return set({ topList, // conversationsList: conversationsTopStateMapped[0], pageList, conversationsList, activeConversations: { ...conversationsMapped, ...activeConversations } }) }, setClosedConversationList: (closedConversationsList) => { const { activeConversations, } = get(); const listMapped = closedConversationsList.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {}); return set({ closedConversationsList, activeConversations: { ...activeConversations, ...listMapped } }); }, addToConversationList: (newList, position='top') => { const { activeConversations, conversationsList, currentConversation } = get(); // const conversationsIds = Object.keys(activeConversations); const conversationsIds = conversationsList.map((chatItem) => `${chatItem.sn}`); const newConversations = newList.filter((conversation) => !conversationsIds.includes(`${conversation.sn}`)); const newConversationsMapped = newConversations.reduce((r, v) => ({ ...r, [`${v.sn}`]: [] }), {}); const newListIds = newList.map((chatItem) => `${chatItem.sn}`); const withoutNew = conversationsList.filter((item) => !newListIds.includes(`${item.sn}`)); const updateList = replaceObjectsByKey(conversationsList, newList, 'sn'); const mergedList = position==='top' ? [...newList, ...withoutNew] : [...updateList, ...newConversations]; const mergedListMsgs = { ...newConversationsMapped, ...activeConversations, }; const needUpdateCurrent = -1 !== newList.findIndex(row => Number(row.sn) === Number(currentConversation.sn)); const updateCurrent = needUpdateCurrent ? { currentConversation: newList.find(row => Number(row.sn) === Number(currentConversation.sn)) } : {}; // 让当前会话显示在页面上 if (currentConversation.sn) { const hasCurrent = -1 !== Object.keys(mergedListMsgs).findIndex(sn => Number(sn) === Number(currentConversation.sn)); hasCurrent ? 0 : mergedList.unshift(currentConversation); } const refreshTotalNotify = mergedList.reduce((r, c) => r+(c.unread_msg_count === UNREAD_MARK ? 0 : c.unread_msg_count), 0); const { topList, pageList } = sortConversationList(mergedList) return set((state) => ({ ...updateCurrent, topList, pageList, conversationsList: mergedList, activeConversations: mergedListMsgs, totalNotify: refreshTotalNotify, // totalNotify: state.totalNotify + newConversations.map((ele) => ele.unread_msg_count).reduce((acc, cur) => acc + (cur || 0), 0), })); }, delConversationitem: (conversation) => { const { conversationsList, activeConversations } = get(); const targetId = conversation.sn; const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); conversationsList.splice(targetIndex, 1); const { topList, pageList } = sortConversationList(conversationsList) return set({ topList, pageList, conversationsList: [...conversationsList], activeConversations: { ...activeConversations, [`${targetId}`]: [] }, currentConversation: {}, }); }, setCurrentConversation: (conversation) => { // 清空未读 const { conversationsList } = get(); const targetId = conversation.sn; const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); const targetItemFromList = conversationsList.find((ele) => String(ele.sn) === String(targetId)); targetIndex !== -1 ? conversationsList.splice(targetIndex, 1, { ...conversationsList[targetIndex], unread_msg_count: 0, }) : null; const mergedListMapped = groupBy(conversationsList, 'top_state'); return set((state) => ({ totalNotify: state.totalNotify - (conversation.unread_msg_count || 0), currentConversation: Object.assign({}, conversation, targetItemFromList), referenceMsg: {}, // topList: mergedListMapped['1'] || [], // pageList: mergedListMapped['0'] || [], // conversationsList: [...conversationsList], })); }, updateCurrentConversation: (conversation) => { const { updateConversationItem, currentConversation } = get(); updateConversationItem({...currentConversation, ...conversation}) return set((state) => ({ currentConversation: { ...state.currentConversation, ...conversation } })) }, updateConversationItem: (conversation) => { const { conversationsList } = get(); const targetId = conversation.sn; const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); targetIndex !== -1 ? conversationsList.splice(targetIndex, 1, { ...conversationsList[targetIndex], ...conversation, }) : null; const { topList, pageList } = sortConversationList(conversationsList) return set({ topList, pageList, conversationsList: [...conversationsList] }); }, }); const messageSlice = (set, get) => ({ totalNotify: 0, msgListLoading: false, activeConversations: {}, refreshTotalNotify: () => set((state) => ({ totalNotify: state.conversationsList.reduce((r, c) => r+(c.unread_msg_count === UNREAD_MARK ? 0 : c.unread_msg_count), 0) })), setMsgLoading: (msgListLoading) => set({ msgListLoading }), receivedMessageList: (conversationid, msgList) => set((state) => ({ // msgListLoading: false, activeConversations: { ...state.activeConversations, [String(conversationid)]: msgList }, })), updateMessageItem: (message) => { // msgUpdate // console.log('UPDATE_SENT_MESSAGE_ITEM-----------------------------------------------------------------', message); // 更新会话中的消息 const { activeConversations, conversationsList, currentConversation, setFilter } = get(); const targetId = message.conversationid; const targetMsgs = (activeConversations[String(targetId)] || []).map((ele) => { // 更新状态 // * 已读的不再更新状态, 有时候投递结果在已读之后返回 // if (ele.id === ele.actionId && ele.actionId === message.actionId) { if (ele.actionId === message.actionId && !isEmpty(ele.actionId) && !isEmpty(message.actionId)) { // console.log('actionID', message.actionId, ele.actionId) // WABA: 同步返回, 根据actionId 更新消息的id; const toUpdateFields = pick(message, ['msgOrigin', 'id', 'status', 'dateString', 'replyButton', 'coli_id', 'coli_sn']); return { ...ele, ...toUpdateFields, status: ele.status === 'read' ? ele.status : message.status, }; } else if (String(ele.id) === String(message.id)) { // console.log('id', message.id, ele.id) // WABA: 异步的后续状态更新, id已更新为wamid // console.log('coming msg', message.type, message); // console.log('old msg ele', ele.type, ele); const renderStatus = message?.data?.status ? { status: { ...ele.data.status, loading: 0, download: true } } : {}; const keepReply = ele.reply ? { reply: ele.reply } : {}; const keepTemplate = ele.template ? { template: ele.template, template_origin: ele.template_origin, text: ele.text } : {}; return { ...ele, ...message, id: message.id, status: ele.status === 'read' ? ele.status : message.status, dateString: message.dateString, data: { ...ele.data, ...renderStatus }, ...keepReply, ...keepTemplate }; } return ele; }); // 显示会话中其他客户端发送的消息 const targetMsgsIds = targetMsgs.map((ele) => ele.id); if (!targetMsgsIds.includes(message.id)) { targetMsgs.push(message); } // const targetIndex = conversationsList.findIndex((ele) => String(ele.sn) === String(targetId)); // let newConversations = []; // if (targetIndex !== -1) { // 'delivered' // // 更新列表的时间 // conversationsList.splice(targetIndex, 1, { // ...conversationsList[targetIndex], // last_received_time: message.status === 'received' ? dayjs(message.deliverTime).add(8, 'hours').format(DATETIME_FORMAT) : conversationsList[targetIndex].last_received_time, // conversation_expiretime: message?.conversation?.expireTime || conversationsList[targetIndex].conversation_expiretime || '', // 保留使用UTC时间 // last_message: { ...message, source: message.msg_source }, // }) // } else if (targetIndex === -1) { // // 当前客户端不存在的会话 // // todo: 设置为当前(在WhatsApp返回号码不一致时) // const newContact = message.msg_direction === 'outbound' ? message.to : message.from; // newConversations = [{ // ...conversationRow, // ...message, // sn: targetId, // opi_sn: currentConversation.opi_sn, // todo: coli sn // last_received_time: message.date, // unread_msg_count: 0, // whatsapp_name: newContact, //message?.senderName || message?.sender || '', // customer_name: newContact, // message?.senderName || message?.sender || '', // conversation_expiretime: message?.conversation?.expireTime || '', // 保留使用UTC时间 // whatsapp_phone_number: message.type === 'email' ? null : newContact, // show_default: message?.conversation?.name || newContact || '', // session_type: message?.conversation?.type === 'group' ? 1 : 0, // last_message: { ...message, source: message.msg_source }, // channels: { // "email": message.type === 'email' ? newContact : null, // "phone_number": message.type === 'email' ? null : newContact, // "whatsapp_phone_number": message.type === 'email' ? null : newContact, // }, // }]; // } // const mergedList = [...newConversations, ...conversationsList] setFilter({ loadNextPage: true }); // const { topList, pageList } = sortConversationList(mergedList); return set({ // topList, // pageList, // conversationsList: mergedList, activeConversations: { ...activeConversations, [String(targetId)]: targetMsgs }, }); }, sentOrReceivedNewMessage: (targetId, message) => { // msgRender: // console.log('sentOrReceivedNewMessage', targetId, message) const { activeConversations, conversationsList, currentConversation, totalNotify, setFilter } = get(); const targetMsgs = activeConversations[String(targetId)] || []; // const targetIndex = conversationsList.findIndex((ele) => Number(ele.sn) === Number(targetId)); // const lastReceivedTime = (message.type !== 'system' && message.sender !== 'me') ? dayjs(message.date).add(8, 'hours').format(DATETIME_FORMAT) : null; // const newContact = message.msg_direction === 'outbound' ? message.to : message.from; // const newConversation = // targetIndex !== -1 // ? { // ...conversationsList[targetIndex], // last_received_time: lastReceivedTime || conversationsList[targetIndex].last_received_time, // unread_msg_count: // Number(targetId) !== Number(currentConversation.sn) && message.sender !== 'me' // ? conversationsList[targetIndex].unread_msg_count + 1 // : conversationsList[targetIndex].unread_msg_count, // last_message: { ...message, source: message.msg_source }, // } // : { // ...conversationRow, // ...message, // sn: Number(targetId), // opi_sn: message.opi_sn || currentConversation.opi_sn, // todo: coli sn // last_received_time: dayjs(message.date).add(8, 'hours').format(DATETIME_FORMAT), // unread_msg_count: message.sender === 'me' ? 0 : 1, // whatsapp_name: message?.senderName || message?.sender || '', // customer_name: message?.senderName || message?.sender || '', // whatsapp_phone_number: message.type === 'email' ? null : newContact, // show_default: message?.conversation?.name || message?.senderName || message?.sender || newContact || '', // session_type: message?.conversation?.type === 'group' ? 1 : 0, // last_message: { ...message, source: message.msg_source }, // channels: { // "email": message.type === 'email' ? newContact : null, // "phone_number": message.type === 'email' ? null : newContact, // "whatsapp_phone_number": message.type === 'email' ? null : newContact, // }, // }; // if (targetIndex === -1) { // conversationsList.unshift(newConversation); // } else { // // if (String(targetId)!== '0') { // conversationsList.splice(targetIndex, 1); // conversationsList.unshift(newConversation); // } // console.log('find in list, i:', targetIndex); // console.log('find in list, chat updated and Top: \n', JSON.stringify(newConversation, null, 2)); // console.log('list updated : \n', JSON.stringify(conversationsList, null, 2)); setFilter({ loadNextPage: true }); const isCurrent = Number(targetId) === Number(currentConversation.sn); const updatedCurrent = isCurrent ? { ...currentConversation, last_received_time: dayjs(message.date).add(8, 'hours').format(DATETIME_FORMAT), conversation_expiretime: dayjs(message.date).add(24, 'hours').format(DATETIME_FORMAT), last_message: { ...message, source: message.msg_source }, } : {...currentConversation, last_message: message,}; // const { topList, pageList } = sortConversationList(conversationsList); return set({ // currentConversation: updatedCurrent, // topList, // pageList, // conversationsList: [...conversationsList], // totalNotify: totalNotify + (message.sender === 'me' ? 0 : 1), activeConversations: { ...activeConversations, [String(targetId)]: [...targetMsgs, message] }, }); }, }); /** * Email */ const emailSlice = (set, get) => ({ emailMsg: { id: -1, conversationid: '', actionId: '', order_opi: '', coli_sn: '', msgOrigin: {} }, setEmailMsg: (emailMsg) => { const { editorOpen } = get(); return editorOpen ? false : set({ emailMsg }); // 已经打开的不更新 }, detailPopupOpen: false, setDetailOpen: (v) => set({ detailPopupOpen: v }), openDetail: () => set(() => ({ detailPopupOpen: true })), closeDetail: () => set(() => ({ detailPopupOpen: false })), editorOpen: false, setEditorOpen: (v) => set({ editorOpen: v }), openEditor: () => set(() => ({ editorOpen: true })), closeEditor: () => set(() => ({ editorOpen: false })), // EmailEditorPopup 组件的 props // @property {string} fromEmail - 发件人邮箱 // @property {string} fromUser - 发件人用户 // @property {string} fromOrder - 发件订单 // @property {string} toEmail - 收件人邮箱 // @property {string} conversationid - 会话ID // @property {string} quoteid - 引用邮件ID // @property {object} draft - 草稿 // @property {string} action - reply / forward / new / edit // @property {string} oid - coli_sn // @property {object} mailData - 邮件内容 // @property {string} receiverName - 收件人称呼 emailEdiorProps: new Map(), setEditorProps: (v) => { const { emailEdiorProps } = get(); const uniqueKey = v.quoteid || Date.now().toString(32); const currentEditValue = {...v, key: `${v.action}-${uniqueKey}`}; const news = new Map(emailEdiorProps).set(currentEditValue.key, currentEditValue); for (const [key, value] of news.entries()) { console.log(value); } return set((state) => ({ emailEdiorProps: news, currentEditKey: currentEditValue.key, currentEditValue })) // return set((state) => ({ emailEdiorProps: { ...state.emailEdiorProps, ...v } })) }, closeEditor1: (key) => { const { emailEdiorProps } = get(); const newProps = new Map(emailEdiorProps); newProps.delete(key); return set(() => ({ emailEdiorProps: newProps })) }, clearEditor: () => { return set(() => ({ emailEdiorProps: new Map() })) }, currentEditKey: '', setCurrentEditKey: (key) => { const { emailEdiorProps, setCurrentEditValue } = get(); const value = emailEdiorProps.get(key); setCurrentEditValue(value); return set(() => ({ currentEditKey: key })) }, currentEditValue: {}, setCurrentEditValue: (v) => { return set(() => ({ currentEditValue: v })) } }) export const useConversationStore = create( devtools((set, get) => ({ ...initialConversationState, ...websocketSlice(set, get), ...conversationSlice(set, get), ...templatesSlice(set, get), ...messageSlice(set, get), ...referenceMsgSlice(set, get), ...complexMsgSlice(set, get), ...tagsSlice(set, get), ...filterSlice(set, get), ...globalNotifySlice(set, get), ...emailSlice(set, get), ...waiSlice(set, get), // state actions addError: (error) => set((state) => ({ errors: [...state.errors, error] })), setInitial: (v) => set({ initialState: v }), // side effects fetchInitialData: async ({userId, whatsAppBusiness, ...loginUser}) => { const { addToConversationList, setTemplates, setInitial, setTags } = get(); const conversationsList = await fetchConversationsList({ opisn: userId }); addToConversationList(conversationsList); const templates = await fetchTemplates({ waba: whatsAppBusiness }); setTemplates(templates); const myTags = await fetchTags({ opisn: userId}); setTags(myTags); setInitial(true); // 登录后, 执行一下清除日志缓存 clean7DaysWebsocketLog(); }, reset: () => set(initialConversationState), }), { name: 'cStore' }) ); export default useConversationStore;