From 5caf461a4c96bbc5f51bafebe4aed1f6cd90e4d3 Mon Sep 17 00:00:00 2001 From: "[yxf]" <[1524240689@qq.com]> Date: Fri, 3 Apr 2026 18:53:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=9C=8D=E8=BD=AC=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-uniapp/pages/chat/chat-box.vue | 209 +++++------- im-uniapp/store/chatStore.js | 530 +++++++++++------------------- 2 files changed, 285 insertions(+), 454 deletions(-) diff --git a/im-uniapp/pages/chat/chat-box.vue b/im-uniapp/pages/chat/chat-box.vue index da3a7bc..12b8807 100644 --- a/im-uniapp/pages/chat/chat-box.vue +++ b/im-uniapp/pages/chat/chat-box.vue @@ -133,6 +133,10 @@ export default { isReceipt: false, // 是否回执消息 scrollMsgIdx: 0, // 滚动条定位为到哪条消息 chatTabBox: 'none', + currentTargetId: null, // 加这一行 + currentChatType: 'PRIVATE', + // activeChatIdx: 0, + _activeChatIdx: 0, // 添加这个私有变量 showRecord: false, chatMainHeight: 800, // 聊天窗口高度 keyboardHeight: 290, // 键盘高度 @@ -181,6 +185,8 @@ export default { this.fillTargetId(msgInfo, this.chat.targetId); // 防止发送期间用户切换会话导致串扰 const chat = this.chat; + // const chat = this.chatStore.chats[this.activeChatIdx]; + if (!chat) return; // 消息回显 let tmpMessage = this.buildTmpMessage(msgInfo); this.chatStore.insertMessage(tmpMessage, chat); @@ -330,6 +336,8 @@ export default { this.fillTargetId(msgInfo, this.chat.targetId); // 防止发送期间用户切换会话导致串扰 const chat = this.chat; + // const chat = this.chatStore.chats[this.activeChatIdx]; + if (!chat) return; // 回显消息 let tmpMessage = this.buildTmpMessage(msgInfo); this.chatStore.insertMessage(tmpMessage, chat); @@ -555,6 +563,8 @@ export default { } // 防止发送期间用户切换会话导致串扰 const chat = this.chat; + // const chat = this.chatStore.chats[this.activeChatIdx]; + if (!chat) return; // 删除旧消息 this.chatStore.deleteMessage(msgInfo, chat); // 重新发送 @@ -1002,22 +1012,26 @@ export default { }, computed: { chat() { - // 根据当前激活的索引从 store 获取最新的 chat - if (!this.chatStore.chats || this.chatStore.chats.length === 0) { - return null; - } - const idx = this.activeChatIdx; - return this.chatStore.chats[idx] || this.chatStore.chats[0]; - }, + if (!this.currentTargetId) return null; + return this.chatStore.chats.find(c => + c.targetId === this.currentTargetId && + c.type === this.currentChatType + ) || null; + }, - activeChatIdx: { - get() { - return this._activeChatIdx || 0; - }, - set(val) { - this._activeChatIdx = val; - } - }, + activeChatIdx: { + get() { return this._activeChatIdx || 0; }, + set(val) { this._activeChatIdx = val; } + }, + + // activeChatIdx: { + // get() { + // return this._activeChatIdx || 0; + // }, + // set(val) { + // this._activeChatIdx = val; + // } + // }, mine() { return this.userStore.userInfo; @@ -1036,9 +1050,13 @@ export default { } return title; }, - messageAction() { - return `/message/${this.chat.type.toLowerCase()}/send`; - }, + // messageAction() { + // return `/message/${this.chat.type.toLowerCase()}/send`; + // }, + messageAction() { + if (!this.chat) return ''; + return `/message/${this.chat.type.toLowerCase()}/send`; + }, messageSize() { if (!this.chat || !this.chat.messages) { return 0; @@ -1119,120 +1137,63 @@ export default { } }, async onLoad(options) { - const chatIdx = options.chatIdx !== undefined ? parseInt(options.chatIdx) : 0; - - // 显示加载提示 - uni.showLoading({ - title: '加载中...', - mask: true - }); - try { - // 等待配置初始化 - let retryCount = 0; - const maxRetry = 30; // 3秒 - - // 等待 chats 数据加载 - while ((!this.chatStore.chats || this.chatStore.chats.length === 0) && retryCount < maxRetry) { - await new Promise(resolve => setTimeout(resolve, 100)); - retryCount++; - } - - // 如果还是没有数据,主动加载 - if (!this.chatStore.chats || this.chatStore.chats.length === 0) { - if (this.chatStore.loadChat) { - await this.chatStore.loadChat(); - } - // 再次等待 - await new Promise(resolve => setTimeout(resolve, 500)); - } - - // 再次检查 - if (!this.chatStore.chats || this.chatStore.chats.length === 0) { - // 尝试从本地缓存读取 - const cached = uni.getStorageSync('chat_chats'); - if (cached && cached.length > 0) { - this.chatStore.chats = cached; - } else { - throw new Error('暂无聊天数据'); - } - } - - // 获取聊天数据 - this.chat = this.chatStore.chats[chatIdx] || this.chatStore.chats[0]; - - if (!this.chat || !this.chat.targetId) { - // throw new Error('会话不存在'); - } - - uni.hideLoading(); - - // 其余代码保持不变... - // 初始状态只显示20条消息 - let size = this.messageSize; - this.showMinIdx = size > 20 ? size - 20 : 0; - - // 消息已读 - this.readedMessage() - - // 加载好友或群聊信息 - if (this.isGroup) { - this.loadGroup(this.chat.targetId); + uni.showLoading({ title: '加载中...', mask: true }); + + let targetId = null; + let type = 'PRIVATE'; + + // 从列表进入 + if (options.targetId) { + targetId = Number(options.targetId); + type = options.type || 'PRIVATE'; } else { - this.loadFriend(this.chat.targetId); - this.loadReaded(this.chat.targetId) + // 直接打开页面 + if (this.friendStore.friends.length === 0) await this.friendStore.loadFriend(); + const first = this.friendStore.friends[0]; + if (!first) return uni.showToast({ title: '暂无好友', icon: 'none' }); + targetId = first.id; + } + + await this.chatStore.loadChat(); + await new Promise(r => setTimeout(r, 300)); + + // 查找会话 + let chat = this.chatStore.chats.find(c => c.type === type && c.targetId === targetId); + if (!chat) { + const friend = this.friendStore.findFriend(targetId) || this.friendStore.friends[0]; + chat = { + targetId, type, + showName: friend?.nickName || '客服', + headImage: friend?.headImage || '', + isDnd: false, lastContent: '', + lastSendTime: Date.now(), unreadCount: 0, messages: [] + }; + this.chatStore.chats.unshift(chat); } - - // 激活当前会话 - this.chatStore.activeChat(chatIdx); - - // 复位回执消息 - this.isReceipt = false; - this.isInBottom = true; - this.newMessageSize = 0; - this.maxTmpId = 0; - - // 监听键盘高度 + + // ✅ 永久锁定 ID,绝不乱跳 + this.currentTargetId = targetId; + this.currentChatType = type; + + await this.$nextTick(); + + // 初始化 + this.readedMessage(); + this.loadFriend(targetId); + this.loadReaded(targetId); + this.listenKeyBoard(); - - // 计算聊天窗口高度 this.windowHeight = uni.getSystemInfoSync().windowHeight; this.screenHeight = uni.getSystemInfoSync().screenHeight; this.reCalChatMainHeight(); - - this.$nextTick(() => { - this.windowHeight = uni.getSystemInfoSync().windowHeight; - this.reCalChatMainHeight(); - this.scrollToBottom(); - // #ifdef H5 - this.initHeight = window.innerHeight; - const chatBox = document.getElementById('chatBox') - if (chatBox) { - chatBox.addEventListener('touchmove', e => { - e.preventDefault() - }, { passive: false }); - } - // #endif - }); - - } catch (error) { + + this.$nextTick(() => this.scrollToBottom()); + + } catch (err) { + console.error('错误:', err); + } finally { uni.hideLoading(); - console.error('进入聊天页面失败:', error); - uni.showToast({ - title: error.message || '加载失败,请稍后重试', - icon: 'none' - }); - - setTimeout(() => { - uni.navigateBack({ - delta: 1, - fail: () => { - uni.switchTab({ - url: "/pages/chat/chat" - }); - } - }); - }, 1500); } }, onUnload() { diff --git a/im-uniapp/store/chatStore.js b/im-uniapp/store/chatStore.js index ac47518..408213a 100644 --- a/im-uniapp/store/chatStore.js +++ b/im-uniapp/store/chatStore.js @@ -6,23 +6,19 @@ import useUserStore from './userStore'; let cacheChats = []; export default defineStore('chatStore', { - state: () => { - return { - chats: [], - privateMsgMaxId: 0, - groupMsgMaxId: 0, - loading: false - } - }, + state: () => ({ + chats: [], + privateMsgMaxId: 0, + groupMsgMaxId: 0, + loading: false + }), actions: { initChats(chatsData) { cacheChats = []; this.chats = []; for (let chat of chatsData.chats) { chat.stored = false; - // 暂存至缓冲区 cacheChats.push(JSON.parse(JSON.stringify(chat))); - // 加载期间显示只前15个会话做做样子,一切都为了加快初始化时间 if (this.chats.length < 15) { this.chats.push(chat); } @@ -31,18 +27,15 @@ export default defineStore('chatStore', { this.groupMsgMaxId = chatsData.groupMsgMaxId || 0; }, openChat(chatInfo) { - let chats = this.curChats; + let chats = this.chats; let chat = null; for (let idx in chats) { - if (chats[idx].type == chatInfo.type && - chats[idx].targetId === chatInfo.targetId) { + if (chats[idx].type == chatInfo.type && chats[idx].targetId === chatInfo.targetId) { chat = chats[idx]; - // 放置头部 - this.moveTop(idx) + this.moveTop(idx); break; } } - // 创建会话 if (chat == null) { chat = { targetId: chatInfo.targetId, @@ -65,323 +58,265 @@ export default defineStore('chatStore', { } }, activeChat(idx) { - let chats = this.curChats; if (idx >= 0) { - chats[idx].unreadCount = 0; + this.chats[idx] = { ...this.chats[idx], unreadCount: 0 }; } }, resetUnreadCount(chatInfo) { - let chats = this.curChats; - for (let idx in chats) { - if (chats[idx].type == chatInfo.type && - chats[idx].targetId == chatInfo.targetId) { - chats[idx].unreadCount = 0; - chats[idx].atMe = false; - chats[idx].atAll = false; - chats[idx].stored = false; - this.saveToStorage(); + this.chats = this.chats.map(chat => { + if (chat.type == chatInfo.type && chat.targetId == chatInfo.targetId) { + return { ...chat, unreadCount: 0, atMe: false, atAll: false, stored: false }; } - } - + return chat; + }); + this.saveToStorage(); }, readedMessage(pos) { let chat = this.findChatByFriend(pos.friendId); if (!chat) return; - for (let idx = chat.readedMessageIdx; idx < chat.messages.length; idx++) { - let m = chat.messages[idx]; + let messages = [...chat.messages]; + let changed = false; + for (let idx = chat.readedMessageIdx; idx < messages.length; idx++) { + let m = messages[idx]; if (m.id && m.selfSend && m.status < MESSAGE_STATUS.RECALL) { - // pos.maxId为空表示整个会话已读 if (!pos.maxId || m.id <= pos.maxId) { - m.status = MESSAGE_STATUS.READED + messages[idx] = { ...m, status: MESSAGE_STATUS.READED }; chat.readedMessageIdx = idx; - chat.stored = false; + changed = true; } } } - if (!chat.stored) { + if (changed) { + chat.messages = messages; + chat.stored = false; this.saveToStorage(); } }, cleanMessage(idx) { - let chat = this.curChats[idx]; + let chat = { ...this.chats[idx] }; chat.lastContent = ''; chat.hotMinIdx = 0; chat.unreadCount = 0; chat.atMe = false; chat.atAll = false; - chat.stored = false + chat.stored = false; chat.messages = []; + this.chats[idx] = chat; this.saveToStorage(true); }, removeChat(idx) { - let chats = this.curChats; - chats[idx].delete = true; - chats[idx].stored = false; + this.chats[idx] = { ...this.chats[idx], delete: true, stored: false }; this.saveToStorage(); }, removePrivateChat(userId) { - let chats = this.curChats; - for (let idx in chats) { - if (chats[idx].type == 'PRIVATE' && - chats[idx].targetId == userId) { - this.removeChat(idx); + this.chats = this.chats.map(chat => { + if (chat.type == 'PRIVATE' && chat.targetId == userId) { + return { ...chat, delete: true, stored: false }; } - } + return chat; + }); + this.saveToStorage(); }, removeGroupChat(groupId) { - let chats = this.curChats; - for (let idx in chats) { - if (chats[idx].type == 'GROUP' && - chats[idx].targetId == groupId) { - this.removeChat(idx); + this.chats = this.chats.map(chat => { + if (chat.type == 'GROUP' && chat.targetId == groupId) { + return { ...chat, delete: true, stored: false }; } - } + return chat; + }); + this.saveToStorage(); }, moveTop(idx) { - if (this.loading) { - return; - } - let chats = this.curChats; + if (this.loading) return; if (idx > 0) { - let chat = chats[idx]; - chats.splice(idx, 1); + let chats = [...this.chats]; + let chat = chats.splice(idx, 1)[0]; + chat = { ...chat, lastSendTime: new Date().getTime(), stored: false }; chats.unshift(chat); - chat.lastSendTime = new Date().getTime(); - chat.stored = false; + this.chats = chats; this.saveToStorage(); } }, insertMessage(msgInfo, chatInfo) { - // 获取对方id或群id let type = chatInfo.type; - // 记录消息的最大id if (msgInfo.id && type == "PRIVATE" && msgInfo.id > this.privateMsgMaxId) { this.privateMsgMaxId = msgInfo.id; } if (msgInfo.id && type == "GROUP" && msgInfo.id > this.groupMsgMaxId) { this.groupMsgMaxId = msgInfo.id; } - // 如果是已存在消息,则覆盖旧的消息数据 + let chat = this.findChat(chatInfo); + if (!chat) return; + let message = this.findMessage(chat, msgInfo); if (message) { - console.log("message:", message) - Object.assign(message, msgInfo); + chat.messages = chat.messages.map(m => + (m.id === msgInfo.id || m.tmpId === msgInfo.tmpId) ? { ...m, ...msgInfo } : m + ); chat.stored = false; this.saveToStorage(); return; } - // 会话列表内容 - if (msgInfo.type == MESSAGE_TYPE.IMAGE) { - chat.lastContent = "[图片]"; - } else if (msgInfo.type == MESSAGE_TYPE.FILE) { - chat.lastContent = "[文件]"; - } else if (msgInfo.type == MESSAGE_TYPE.AUDIO) { - chat.lastContent = "[语音]"; - } else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VOICE) { - chat.lastContent = "[语音通话]"; - } else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VIDEO) { - chat.lastContent = "[视频通话]"; - } else if (msgInfo.type == MESSAGE_TYPE.TEXT || - msgInfo.type == MESSAGE_TYPE.RECALL || - msgInfo.type == MESSAGE_TYPE.TIP_TEXT) { + + chat = { ...chat }; + if (msgInfo.type == MESSAGE_TYPE.IMAGE) chat.lastContent = "[图片]"; + else if (msgInfo.type == MESSAGE_TYPE.FILE) chat.lastContent = "[文件]"; + else if (msgInfo.type == MESSAGE_TYPE.AUDIO) chat.lastContent = "[语音]"; + else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VOICE) chat.lastContent = "[语音通话]"; + else if (msgInfo.type == MESSAGE_TYPE.ACT_RT_VIDEO) chat.lastContent = "[视频通话]"; + else if (msgInfo.type == MESSAGE_TYPE.TEXT || msgInfo.type == MESSAGE_TYPE.RECALL || msgInfo.type == MESSAGE_TYPE.TIP_TEXT) { chat.lastContent = msgInfo.content; } chat.lastSendTime = msgInfo.sendTime; chat.sendNickName = msgInfo.sendNickName; - // 未读加1 - if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED && - msgInfo.status != MESSAGE_STATUS.RECALL && msgInfo.type != MESSAGE_TYPE.TIP_TEXT) { + + if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED && msgInfo.status != MESSAGE_STATUS.RECALL && msgInfo.type != MESSAGE_TYPE.TIP_TEXT) { chat.unreadCount++; } - // 是否有人@我 - if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds && - msgInfo.status != MESSAGE_STATUS.READED) { + + if (!msgInfo.selfSend && chat.type == "GROUP" && msgInfo.atUserIds && msgInfo.status != MESSAGE_STATUS.READED) { const userStore = useUserStore(); let userId = userStore.userInfo.id; - if (msgInfo.atUserIds.indexOf(userId) >= 0) { - chat.atMe = true; - } - if (msgInfo.atUserIds.indexOf(-1) >= 0) { - chat.atAll = true; - } + if (msgInfo.atUserIds.indexOf(userId) >= 0) chat.atMe = true; + if (msgInfo.atUserIds.indexOf(-1) >= 0) chat.atAll = true; } - // 间隔大于10分钟插入时间显示 - if (!chat.lastTimeTip || (chat.lastTimeTip < msgInfo.sendTime - 600 * 1000)) { - chat.messages.push({ - sendTime: msgInfo.sendTime, - type: MESSAGE_TYPE.TIP_TIME, - }); + + let messages = [...chat.messages]; + if (!chat.lastTimeTip || chat.lastTimeTip < msgInfo.sendTime - 600 * 1000) { + messages.push({ sendTime: msgInfo.sendTime, type: MESSAGE_TYPE.TIP_TIME }); chat.lastTimeTip = msgInfo.sendTime; } - // 插入消息 - chat.messages.push(msgInfo); + messages.push(msgInfo); + chat.messages = messages; chat.stored = false; + + this.chats = this.chats.map(c => c.type === chat.type && c.targetId === chat.targetId ? chat : c); this.saveToStorage(); }, updateMessage(msgInfo, chatInfo) { - // 获取对方id或群id let chat = this.findChat(chatInfo); - let message = this.findMessage(chat, msgInfo); - if (message) { - // 属性拷贝 - Object.assign(message, msgInfo); - chat.stored = false; - this.saveToStorage(); - } + if (!chat) return; + + this.chats = this.chats.map(c => { + if (c.type === chat.type && c.targetId === chat.targetId) { + return { + ...c, + messages: c.messages.map(m => + (m.id && m.id === msgInfo.id) || (m.tmpId && m.tmpId === msgInfo.tmpId) + ? { ...m, ...msgInfo } + : m + ), + stored: false + }; + } + return c; + }); + this.saveToStorage(); }, deleteMessage(msgInfo, chatInfo) { - let isColdMessage = false; let chat = this.findChat(chatInfo); - let delIdx = -1; - for (let idx in chat.messages) { - // 已经发送成功的,根据id删除 - if (chat.messages[idx].id && chat.messages[idx].id == msgInfo.id) { - delIdx = idx; - break; - } - // 正在发送中的消息可能没有id,只有临时id - if (chat.messages[idx].tmpId && chat.messages[idx].tmpId == msgInfo.tmpId) { - delIdx = idx; - break; - } - } - if (delIdx >= 0) { - chat.messages.splice(delIdx, 1); - if (delIdx < chat.hotMinIdx) { - isColdMessage = true; - chat.hotMinIdx--; - } - if (delIdx < chat.readedMessageIdx) { - chat.readedMessageIdx--; + if (!chat) return; + + this.chats = this.chats.map(c => { + if (c.type === chat.type && c.targetId === chat.targetId) { + let messages = c.messages.filter(m => + !(m.id && m.id === msgInfo.id) && !(m.tmpId && m.tmpId === msgInfo.tmpId) + ); + return { ...c, messages, stored: false }; } - chat.stored = false; - this.saveToStorage(isColdMessage); - } + return c; + }); + this.saveToStorage(); }, recallMessage(msgInfo, chatInfo) { let chat = this.findChat(chatInfo); if (!chat) return; - let isColdMessage = false; - // 要撤回的消息id let id = msgInfo.content; let name = msgInfo.selfSend ? '你' : chat.type == 'PRIVATE' ? '对方' : msgInfo.sendNickName; - for (let idx in chat.messages) { - let m = chat.messages[idx]; - if (m.id && m.id == id) { - // 改造成一条提示消息 - m.status = MESSAGE_STATUS.RECALL; - m.content = name + "撤回了一条消息"; - m.type = MESSAGE_TYPE.TIP_TEXT - // 会话列表 - chat.lastContent = m.content; - chat.lastSendTime = msgInfo.sendTime; - chat.sendNickName = ''; - if (!msgInfo.selfSend && msgInfo.status != MESSAGE_STATUS.READED) { - chat.unreadCount++; - } - isColdMessage = idx < chat.hotMinIdx; - } - // 被引用的消息也要撤回 - if (m.quoteMessage && m.quoteMessage.id == msgInfo.id) { - m.quoteMessage.content = "引用内容已撤回"; - m.quoteMessage.status = MESSAGE_STATUS.RECALL; - m.quoteMessage.type = MESSAGE_TYPE.TIP_TEXT + + this.chats = this.chats.map(c => { + if (c.type === chat.type && c.targetId === chat.targetId) { + let messages = c.messages.map(m => { + if (m.id && m.id == id) { + return { + ...m, + status: MESSAGE_STATUS.RECALL, + content: name + "撤回了一条消息", + type: MESSAGE_TYPE.TIP_TEXT + }; + } + if (m.quoteMessage && m.quoteMessage.id == msgInfo.id) { + return { + ...m, + quoteMessage: { ...m.quoteMessage, content: "引用内容已撤回", status: MESSAGE_STATUS.RECALL, type: MESSAGE_TYPE.TIP_TEXT } + }; + } + return m; + }); + return { ...c, messages, stored: false }; } - } - chat.stored = false; - this.saveToStorage(isColdMessage); + return c; + }); + this.saveToStorage(); }, updateChatFromFriend(friend) { - let chat = this.findChatByFriend(friend.id) - if (chat && (chat.headImage != friend.headImage || - chat.showName != friend.nickName)) { - // 更新会话中的群名和头像 - chat.headImage = friend.headImage; - chat.showName = friend.nickName; - chat.stored = false; - this.saveToStorage(); - } + this.chats = this.chats.map(chat => { + if (chat.type === 'PRIVATE' && chat.targetId === friend.id) { + return { ...chat, headImage: friend.headImage, showName: friend.nickName, stored: false }; + } + return chat; + }); + this.saveToStorage(); }, updateChatFromUser(user) { - let chat = this.findChatByFriend(user.id); - // 更新会话中的昵称和头像 - if (chat && (chat.headImage != user.headImageThumb || - chat.showName != user.nickName)) { - chat.headImage = user.headImageThumb; - chat.showName = user.nickName; - chat.stored = false; - this.saveToStorage(); - } + this.chats = this.chats.map(chat => { + if (chat.type === 'PRIVATE' && chat.targetId === user.id) { + return { ...chat, headImage: user.headImageThumb, showName: user.nickName, stored: false }; + } + return chat; + }); + this.saveToStorage(); }, updateChatFromGroup(group) { - let chat = this.findChatByGroup(group.id); - if (chat && (chat.headImage != group.headImageThumb || - chat.showName != group.showGroupName)) { - // 更新会话中的群名称和头像 - chat.headImage = group.headImageThumb; - chat.showName = group.showGroupName; - chat.stored = false; - this.saveToStorage(); - } + this.chats = this.chats.map(chat => { + if (chat.type === 'GROUP' && chat.targetId === group.id) { + return { ...chat, headImage: group.headImageThumb, showName: group.showGroupName, stored: false }; + } + return chat; + }); + this.saveToStorage(); }, setLoading(loading) { this.loading = loading; }, setDnd(chatInfo, isDnd) { - let chat = this.findChat(chatInfo); - if (chat) { - chat.isDnd = isDnd; - } + this.chats = this.chats.map(chat => { + if (chat.type === chatInfo.type && chat.targetId === chatInfo.targetId) { + return { ...chat, isDnd }; + } + return chat; + }); }, refreshChats() { let chats = cacheChats || this.chats; - // 更新会话免打扰状态 const friendStore = useFriendStore(); const groupStore = useGroupStore(); chats.forEach(chat => { if (chat.type == 'PRIVATE') { let friend = friendStore.findFriend(chat.targetId); - if (friend) { - chat.isDnd = friend.isDnd - } + if (friend) chat.isDnd = friend.isDnd; } else if (chat.type == 'GROUP') { let group = groupStore.findGroup(chat.targetId); - if (group) { - chat.isDnd = group.isDnd - } - } - }) - // 排序 - chats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); - // #ifndef APP-PLUS - // h5和小程序的stroge一般只有5m,大约只能存储1w条消息,所以可能需要清理部分历史消息 - const storageInfo = uni.getStorageInfoSync(); - console.log(`storage缓存: ${storageInfo.currentSize} KB`) - // 空间不足(大于3mb)时,清理这个设备登录过其他账户的消息 - if (storageInfo && storageInfo.currentSize > 3000) { - console.log("storage空间不足,清理其他用户缓存..") - this.cleanOtherUserCache(); - } - // 保证消息总数量不超过3000条,每个会话不超过500条 - this.fliterMessage(chats, 3000, 500); - // #endif - // 记录热数据索引位置 - chats.forEach(chat => { - if (!chat.hotMinIdx || chat.hotMinIdx != chat.messages.length) { - chat.hotMinIdx = chat.messages.length; - chat.stored = false; + if (group) chat.isDnd = group.isDnd; } }); - // 将消息一次性装载回来 + chats.sort((chat1, chat2) => chat2.lastSendTime - chat1.lastSendTime); this.chats = chats; - // 清空缓存,不再使用 cacheChats = null; - // 消息持久化 this.saveToStorage(true); }, fliterMessage(chats, maxTotalSize, maxPerChatSize) { - // 每个会话只保留maxPerChatSize条消息 let remainTotalSize = 0; chats.forEach(chat => { if (chat.messages.length > maxPerChatSize) { @@ -389,13 +324,10 @@ export default defineStore('chatStore', { chat.messages = chat.messages.slice(idx); } remainTotalSize += chat.messages.length; - }) - // 保证消息总数不超过maxTotalSize条,否则继续清理 + }); if (remainTotalSize > maxTotalSize) { this.fliterMessage(chats, maxTotalSize, maxPerChatSize / 2); } - console.log("消息留存总数量:", remainTotalSize) - console.log("单会话消息数量:", maxPerChatSize) }, cleanOtherUserCache() { const userStore = useUserStore(); @@ -403,163 +335,101 @@ export default defineStore('chatStore', { const prefix = "chats-app-" + userId; const res = uni.getStorageInfoSync(); res.keys.forEach(key => { - // 清理其他用户的消息 if (key.startsWith("chats-app") && !key.startsWith(prefix)) { uni.removeStorageSync(key); - console.log("清理key:", key) } - }) + }); }, saveToStorage(withColdMessage) { - // 加载中不保存,防止卡顿 - if (this.loading) { - return; - } + if (this.loading) return; const userStore = useUserStore(); let userId = userStore.userInfo.id; let key = "chats-app-" + userId; let chatKeys = []; - // 按会话为单位存储,只存储有改动的会话 this.chats.forEach((chat) => { - let chatKey = `${key}-${chat.type}-${chat.targetId}` + let chatKey = `${key}-${chat.type}-${chat.targetId}`; if (!chat.stored) { if (chat.delete) { uni.removeStorageSync(chatKey); } else { - // 存储冷数据 if (withColdMessage) { - let coldChat = Object.assign({}, chat); + let coldChat = { ...chat }; coldChat.messages = chat.messages.slice(0, chat.hotMinIdx); - uni.setStorageSync(chatKey, coldChat) + uni.setStorageSync(chatKey, coldChat); } - // 存储热消息 let hotKey = chatKey + '-hot'; - let hotChat = Object.assign({}, chat); - hotChat.messages = chat.messages.slice(chat.hotMinIdx) + let hotChat = { ...chat }; + hotChat.messages = chat.messages.slice(chat.hotMinIdx); uni.setStorageSync(hotKey, hotChat); } chat.stored = true; } - if (!chat.delete) { - chatKeys.push(chatKey); - } - }) - // 会话核心信息 + if (!chat.delete) chatKeys.push(chatKey); + }); let chatsData = { privateMsgMaxId: this.privateMsgMaxId, groupMsgMaxId: this.groupMsgMaxId, chatKeys: chatKeys - } - uni.setStorageSync(key, chatsData) - // 清理已删除的会话 - this.chats = this.chats.filter(chat => !chat.delete) + }; + uni.setStorageSync(key, chatsData); + this.chats = this.chats.filter(chat => !chat.delete); }, - clear(state) { + clear() { cacheChats = []; this.chats = []; this.privateMsgMaxId = 0; this.groupMsgMaxId = 0; - this.loadingPrivateMsg = false; - this.loadingGroupMsg = false; }, loadChat() { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { let userStore = useUserStore(); let userId = userStore.userInfo.id; - let chatsData = uni.getStorageSync("chats-app-" + userId) - if (chatsData) { - if (chatsData.chatKeys) { - chatsData.chats = []; - chatsData.chatKeys.forEach(key => { - let coldChat = uni.getStorageSync(key); - let hotChat = uni.getStorageSync(key + '-hot'); - if (!coldChat && !hotChat) { - return; - } - // 防止消息一直处在发送中状态 - hotChat && hotChat.messages.forEach(msg => { - if (msg.status == MESSAGE_STATUS.SENDING) { - msg.status = MESSAGE_STATUS.FAILED - } - }) - // 冷热消息合并 - let chat = Object.assign({}, coldChat, hotChat); - if (hotChat && coldChat) { - chat.messages = coldChat.messages.concat(hotChat.messages) - } - // 历史版本没有readedMessageIdx字段,做兼容一下 - chat.readedMessageIdx = chat.readedMessageIdx || 0; - chatsData.chats.push(chat); - }) - } + let chatsData = uni.getStorageSync("chats-app-" + userId); + if (chatsData && chatsData.chatKeys) { + chatsData.chats = []; + chatsData.chatKeys.forEach(key => { + let coldChat = uni.getStorageSync(key); + let hotChat = uni.getStorageSync(key + '-hot'); + if (!coldChat && !hotChat) return; + if (hotChat) { + hotChat.messages.forEach(msg => { + if (msg.status == MESSAGE_STATUS.SENDING) msg.status = MESSAGE_STATUS.FAILED; + }); + } + let chat = { ...coldChat, ...hotChat }; + if (hotChat && coldChat) { + chat.messages = [...(coldChat.messages || []), ...(hotChat.messages || [])]; + } + chat.readedMessageIdx = chat.readedMessageIdx || 0; + chatsData.chats.push(chat); + }); this.initChats(chatsData); } - resolve() - }) + resolve(); + }); } }, getters: { - curChats: (state) => { - if (cacheChats && state.loading) { - return cacheChats; - } - return state.chats; - }, + curChats: (state) => state.chats, // ✅ 修复 findChatIdx: (state) => (chat) => { - let chats = state.curChats; - for (let idx in chats) { - if (chats[idx].type == chat.type && - chats[idx].targetId === chat.targetId) { - chat = state.chats[idx]; - return idx; - } - } + return state.chats.findIndex(c => c.type == chat.type && c.targetId === chat.targetId); }, findChat: (state) => (chat) => { - let chats = state.curChats; - let idx = state.findChatIdx(chat); - return chats[idx]; + return state.chats.find(c => c.type == chat.type && c.targetId === chat.targetId); }, findChatByFriend: (state) => (fid) => { - return state.curChats.find(chat => chat.type == 'PRIVATE' && - chat.targetId == fid) + return state.chats.find(c => c.type == 'PRIVATE' && c.targetId == fid); }, findChatByGroup: (state) => (gid) => { - return state.curChats.find(chat => chat.type == 'GROUP' && - chat.targetId == gid) + return state.chats.find(c => c.type == 'GROUP' && c.targetId == gid); }, findMessage: (state) => (chat, msgInfo) => { - if (!chat) { - return null; - } - // 通过id判断 + if (!chat) return null; if (msgInfo.id) { - for (let idx = chat.messages.length - 1; idx >= 0; idx--) { - let m = chat.messages[idx]; - if (m.id && msgInfo.id == m.id) { - return m; - } - // 如果id比要查询的消息小,说明没有这条消息 - if (m.id && m.id < msgInfo.id) { - break; - } - } + return chat.messages.find(m => m.id === msgInfo.id); } - // 正在发送中的临时消息可能没有id,只有tmpId if (msgInfo.selfSend && msgInfo.tmpId) { - for (let idx = chat.messages.length - 1; idx >= 0; idx--) { - let m = chat.messages[idx]; - if (!m.selfSend || !m.tmpId) { - continue; - } - if (msgInfo.tmpId == m.tmpId) { - return m; - } - // 如果id比要查询的消息小,说明没有这条消息 - if (m.tmpId && m.tmpId < msgInfo.tmpId) { - break; - } - } + return chat.messages.find(m => m.tmpId === msgInfo.tmpId); } return null; }