diff --git a/src/pages/index/ChatPage.vue b/src/pages/index/ChatPage.vue index 3504865..130567e 100644 --- a/src/pages/index/ChatPage.vue +++ b/src/pages/index/ChatPage.vue @@ -240,6 +240,12 @@ export default { recentChats: [], // 聊天消息 contactMessages: [], + // 首次加载 + firstLoad: true, + // 正在加载更多消息 + loadingMore: false, + // 是否所有消息都加载完毕 + loadEnd: false, // 搜索联系人 searchText: "", // 输入的消息内容 @@ -315,14 +321,19 @@ export default { }, // 选择联系人 - selectContact(contact) { + async selectContact(contact) { this.currentContact = contact; - this.getContactMessageList(contact.contactName, 10, 0); + this.contactMessages = []; + // 每次选择联系人的时候需要首次加载消息 + this.firstLoad = true; + await this.getContactMessageList(contact.contactName, 10, 0); // 查看联系人后清除未读数量 contact.unread = 0; + // 使用同步等消息获取完成后再让滚动条滚到底部,否则滚动条的位置不对 this.$nextTick(() => { + this.firstLoad = false; this.scrollToBottom(); }); }, @@ -335,32 +346,34 @@ export default { }, // 获取当前联系人的消息列表 - getContactMessageList(contactName, limit, offset) { - // 获取当前联系人的消息列表 - getContactMessages({ - contactName: contactName, - limit: limit, - offset: offset - }) - .then((response) => { - const contactMessages = []; - const messages = response.data.messages || []; - messages.forEach((item) => { - contactMessages.push({ - ...item, - from: - item.senderName === this.currentUser.username ? "me" : "other", - time: item.time || item.createdAt, - }); - }); - // 将新获取的消息放到现有消息的最前面,用于按时间顺序倒序展示 - this.contactMessages = contactMessages.reverse().concat(this.contactMessages); - console.log("contactMessages", contactMessages); - }) - .catch((error) => { - console.error(error); - this.$message.error("获取消息列表失败"); + async getContactMessageList(contactName, limit, offset) { + try { + // 获取当前联系人的消息列表 + const response = await getContactMessages({ + contactName: contactName, + limit: limit, + offset: offset, }); + + const contactMessages = []; + const messages = response.data.messages || []; + messages.forEach((item) => { + contactMessages.push({ + ...item, + from: + item.senderName === this.currentUser.username ? "me" : "other", + time: item.time || item.createdAt, + }); + }); + // 将新获取的消息放到现有消息的最前面,用于按时间顺序倒序展示 + this.contactMessages = contactMessages + .reverse() + .concat(this.contactMessages); + console.log("contactMessages", contactMessages); + } catch (error) { + console.error(error); + this.$message.error("获取消息列表失败"); + } }, // 获取联系人列表 @@ -378,17 +391,6 @@ export default { }); }, - // 获取最后一条消息 - getLastMessage(contactName) { - const messageList = this.contactMessages[contactName]; - - if (!messageList || messageList.length === 0) { - return "暂无消息"; - } - - return messageList[messageList.length - 1].content; - }, - // 发送消息 sendMessage() { const content = this.messageText.trim(); @@ -421,7 +423,8 @@ export default { (item) => item.contactName === contactName ); - if (index !== -1) { //找到这条数据,修改内容并移除后添加到数组最前面 + if (index !== -1) { + //找到这条数据,修改内容并移除后添加到数组最前面 const chat = this.recentChats[index]; chat.content = content; @@ -429,25 +432,27 @@ export default { this.recentChats.splice(index, 1); this.recentChats.unshift(chat); - } else { // 没有找到这条数据,直接添加到数组最前面 + } else { + // 没有找到这条数据,直接添加到数组最前面 this.recentChats.unshift({ contactName: contactName, content: content, createdAt: newMessage.createdAt, }); } + + // 清空输入框 + this.messageText = ""; + this.$nextTick(() => { + this.scrollToBottom(); + }); }) .catch((error) => { + // 清空输入框 + this.messageText = ""; console.error(error); this.$message.error("发送消息失败"); }); - - // 清空输入框 - this.messageText = ""; - - this.$nextTick(() => { - this.scrollToBottom(); - }); }, // 滚动到底部 @@ -455,23 +460,46 @@ export default { const messageList = this.$refs.messageList; if (messageList) { + console.log("滚动到底部", messageList.scrollHeight); messageList.scrollTop = messageList.scrollHeight; } }, // 处理聊天框滚动事件 - handleMessageScroll() { - const el = this.$refs.messageList; - // 滚动到顶部 - if (el.scrollTop === 0) { - console.log("滚动到顶部,加载更多消息"); - - this.getContactMessageList(this.currentContact.contactName, 10, this.contactMessages.length); - - // 滚动条往下移动 500px,利于继续往上滚动 - el.scrollTop = 500; + async handleMessageScroll() { + if (this.loadingMore || this.loadEnd) { + return; } - } + if (!this.firstLoad) { + const el = this.$refs.messageList; + // 滚动到顶部 + if (el.scrollTop === 0) { + console.log("滚动到顶部,加载更多消息"); + this.loadingMore = true; + const oldScrollHeight = el.scrollHeight; + + try { + await this.getContactMessageList( + this.currentContact.contactName, + 10, + this.contactMessages.length + ); + + // 等待 Vue DOM 更新,再计算滚动高度 + await this.$nextTick(); + + // 让滚动条调整到原来滚动高度的位置 + const newScrollHeight = el.scrollHeight; + const addedHeight = newScrollHeight - oldScrollHeight; + el.scrollTop = addedHeight; + + if(el.scrollTop === 0) this.loadEnd = true; //所有数据已经加载完成,不需要再继续请求了 + } finally { + this.loadingMore = false; + } + } + } + }, }, }; @@ -743,6 +771,7 @@ export default { .message-list { flex: 1; padding: 25px 35px; + min-height: 0; overflow-y: auto; display: none; }