From 9c5b11e5517a84695f55acefa805d2657381f4cb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 28 Apr 2026 01:08:45 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(im):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF=E7=9A=84=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/im/home/components/ToolBar.vue | 4 +- .../im/home/composables/useMessagePuller.ts | 2 +- .../components/ChatGroupMember.vue | 62 +- .../components/message/MessageHistory.vue | 843 +++++++++++++++--- src/views/im/home/store/conversationStore.ts | 36 + 5 files changed, 796 insertions(+), 151 deletions(-) diff --git a/src/views/im/home/components/ToolBar.vue b/src/views/im/home/components/ToolBar.vue index 519ce7509..4d65fcef1 100644 --- a/src/views/im/home/components/ToolBar.vue +++ b/src/views/im/home/components/ToolBar.vue @@ -42,7 +42,7 @@ class="flex items-center justify-center w-10 h-10 rounded-lg text-[#a0a0a0] cursor-pointer transition-all hover:text-white hover:bg-white/10" @click="goProfile" > - + @@ -52,8 +52,6 @@ - - diff --git a/src/views/im/home/pages/conversation/components/message/MessageHistory.vue b/src/views/im/home/pages/conversation/components/message/MessageHistory.vue index d4b97111f..fa9482b0d 100644 --- a/src/views/im/home/pages/conversation/components/message/MessageHistory.vue +++ b/src/views/im/home/pages/conversation/components/message/MessageHistory.vue @@ -1,162 +1,801 @@ diff --git a/src/views/im/home/store/conversationStore.ts b/src/views/im/home/store/conversationStore.ts index 447aa582e..6c0e95fe8 100644 --- a/src/views/im/home/store/conversationStore.ts +++ b/src/views/im/home/store/conversationStore.ts @@ -560,6 +560,42 @@ export const useConversationStore = defineStore('imConversationStore', { this.saveConversations(conversation) }, + /** + * 把"更早的历史消息"批量插到会话消息列表的最前面(合并 + 去重) + * + * MessageHistory 弹窗的"加载更早"按钮调用:调用方先调 /im/message/{private,group}/list 拉一页 + + * 用 useMessagePuller 的 convert 函数转好,再传进来。 + * + * 不更新 lastContent / lastSendTime / unreadCount:这些字段反映"最新一条",加载老消息时不应改动; + * 也不触发 conversation 排序,避免会话列表抖动 + */ + prependMessages(conversationType: number, targetId: number, earlierMessages: Message[]) { + if (earlierMessages.length === 0) { + return + } + const conversation = this.getConversation(conversationType, targetId) + if (!conversation) { + return + } + // 1. 去重:拿当前会话已有消息的 id 集合,把入参里 id 撞上的过滤掉 + // (后端返回的"更早消息"可能跟本地缓存有重叠,比如增量 pull 拉到过同一段) + // id=0 是本地占位消息,不参与去重判定(也不会被 prepend,下面 filter 一并卡掉) + const existingIds = new Set( + conversation.messages.map((message) => message.id).filter((id) => id > 0) + ) + // 2. 过滤后按 id 升序:list 接口虽然按 id desc 返回,前端要展示成"早 → 晚", + // 所以 prepend 之前先 sort asc,让 fresh 数组本身的相对顺序符合时间线 + const fresh = earlierMessages + .filter((message) => message.id > 0 && !existingIds.has(message.id)) + .sort((a, b) => a.id - b.id) + if (fresh.length === 0) { + return + } + // 3. 拼接 + 落盘:fresh 在前、原 messages 在后;持久化让下次冷启动不用再调接口 + conversation.messages = [...fresh, ...conversation.messages] + this.saveConversations(conversation) + }, + /** * 从本地消息列表移除一条消息(右键"删除";不同步后端) * 按 id 优先匹配;若 id 为 0(本地发送中),则按 clientMessageId 匹配