hookehuyr

fix(消息列表): 优化消息列表更新逻辑和滚动加载

修复轮询更新时整个列表被替换的问题,改为只更新现有项状态
调整滚动加载逻辑,确保新数据正确追加到列表底部
修改滚动位置重置方式,使用固定值触发重新渲染
......@@ -38,7 +38,7 @@
<!-- 消息列表内容 -->
<scroll-view ref="scrollViewRef" class="conversation-list" :style="scrollStyle" :scroll-y="true"
@scrolltolower="loadMore" @scroll="scroll" :lower-threshold="20" :enable-flex="false"
@scrolltolower="loadMore" :lower-threshold="100" :enable-flex="false"
:scroll-top="scrollTop">
<view v-for="conversation in filteredConversations" :key="conversation.id"
class="conversation-item border-b border-gray-100 pb-2"
......@@ -154,6 +154,7 @@ const mockMessages = ref([])
/**
* 轮询获取消息列表
* 只更新现有数据的状态,不替换整个列表以保持滚动加载的数据
*/
const pollMessages = async () => {
try {
......@@ -192,8 +193,41 @@ const pollMessages = async () => {
create_time: item.create_time
}))
// 更新消息列表,保持当前页面状态
// 如果当前列表为空或者只有第一页数据,直接替换
if (conversations.value.length === 0 || page.value <= 1) {
conversations.value = transformedData
console.log('轮询:初始化或重置列表数据,数据量:', transformedData.length)
} else {
// 如果已经加载了多页数据,只更新现有项目的状态,不替换整个列表
console.log('轮询:更新现有数据状态,保持', conversations.value.length, '条数据')
// 创建新数据的映射表,便于快速查找
const newDataMap = new Map(transformedData.map(item => [item.id, item]))
// 更新现有数据的状态(如未读状态、最后消息等)
conversations.value = conversations.value.map(existingItem => {
const newItem = newDataMap.get(existingItem.id)
if (newItem) {
// 更新状态但保持在列表中的位置
return {
...existingItem,
lastMessage: newItem.lastMessage,
time: newItem.time,
unread: newItem.unread
}
}
return existingItem
})
// 检查是否有新的消息需要添加到列表顶部
const existingIds = new Set(conversations.value.map(item => item.id))
const newMessages = transformedData.filter(item => !existingIds.has(item.id))
if (newMessages.length > 0) {
console.log('轮询:发现新消息', newMessages.length, '条,添加到列表顶部')
conversations.value = [...newMessages, ...conversations.value]
}
}
}
} catch (error) {
console.error('轮询获取消息列表失败:', error)
......@@ -311,8 +345,8 @@ const setActiveTab = async (tabKey) => {
hasMore.value = true;
// 重置加载状态
loading.value = false;
// 重置滚动位置
scrollTop.value = Math.random(); // 使用随机数触发scroll-view重新渲染
// 重置滚动位置 - 使用更可靠的方式
scrollTop.value = 0.1; // 使用固定的非零值触发scroll-view重新渲染
setTimeout(() => {
scrollTop.value = 0; // 重置到顶部
}, 50);
......@@ -331,7 +365,10 @@ const setActiveTab = async (tabKey) => {
}, 150);
}
// 加载更多数据
/**
* 加载更多数据
* 向下滚动时加载下一页数据并追加到现有列表
*/
const loadMore = async () => {
if (loading.value || !hasMore.value) {
return
......@@ -339,6 +376,7 @@ const loadMore = async () => {
try {
loading.value = true
console.log('加载更多数据,当前页码:', page.value, '当前列表项数:', conversations.value.length)
// 构建请求参数,同时包含状态筛选和关键字搜索
const params = {
......@@ -375,15 +413,24 @@ const loadMore = async () => {
}))
if (transformedData.length > 0) {
conversations.value.push(...transformedData)
// 保存当前列表长度,用于调试
const prevLength = conversations.value.length
// 追加新数据到现有列表
conversations.value = [...conversations.value, ...transformedData]
// 增加页码
page.value++
// 判断是否还有更多数据
hasMore.value = transformedData.length === pageSize
} else {
hasMore.value = false
console.log('没有更多数据')
}
} else {
hasMore.value = false
console.log('API返回无数据')
}
} catch (error) {
console.error('加载更多消息失败:', error)
......