hookehuyr

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

修复轮询更新时整个列表被替换的问题,改为只更新现有项状态
调整滚动加载逻辑,确保新数据正确追加到列表底部
修改滚动位置重置方式,使用固定值触发重新渲染
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
38 38
39 <!-- 消息列表内容 --> 39 <!-- 消息列表内容 -->
40 <scroll-view ref="scrollViewRef" class="conversation-list" :style="scrollStyle" :scroll-y="true" 40 <scroll-view ref="scrollViewRef" class="conversation-list" :style="scrollStyle" :scroll-y="true"
41 - @scrolltolower="loadMore" @scroll="scroll" :lower-threshold="20" :enable-flex="false" 41 + @scrolltolower="loadMore" :lower-threshold="100" :enable-flex="false"
42 :scroll-top="scrollTop"> 42 :scroll-top="scrollTop">
43 <view v-for="conversation in filteredConversations" :key="conversation.id" 43 <view v-for="conversation in filteredConversations" :key="conversation.id"
44 class="conversation-item border-b border-gray-100 pb-2" 44 class="conversation-item border-b border-gray-100 pb-2"
...@@ -154,6 +154,7 @@ const mockMessages = ref([]) ...@@ -154,6 +154,7 @@ const mockMessages = ref([])
154 154
155 /** 155 /**
156 * 轮询获取消息列表 156 * 轮询获取消息列表
157 + * 只更新现有数据的状态,不替换整个列表以保持滚动加载的数据
157 */ 158 */
158 const pollMessages = async () => { 159 const pollMessages = async () => {
159 try { 160 try {
...@@ -192,8 +193,41 @@ const pollMessages = async () => { ...@@ -192,8 +193,41 @@ const pollMessages = async () => {
192 create_time: item.create_time 193 create_time: item.create_time
193 })) 194 }))
194 195
195 - // 更新消息列表,保持当前页面状态 196 + // 如果当前列表为空或者只有第一页数据,直接替换
197 + if (conversations.value.length === 0 || page.value <= 1) {
196 conversations.value = transformedData 198 conversations.value = transformedData
199 + console.log('轮询:初始化或重置列表数据,数据量:', transformedData.length)
200 + } else {
201 + // 如果已经加载了多页数据,只更新现有项目的状态,不替换整个列表
202 + console.log('轮询:更新现有数据状态,保持', conversations.value.length, '条数据')
203 +
204 + // 创建新数据的映射表,便于快速查找
205 + const newDataMap = new Map(transformedData.map(item => [item.id, item]))
206 +
207 + // 更新现有数据的状态(如未读状态、最后消息等)
208 + conversations.value = conversations.value.map(existingItem => {
209 + const newItem = newDataMap.get(existingItem.id)
210 + if (newItem) {
211 + // 更新状态但保持在列表中的位置
212 + return {
213 + ...existingItem,
214 + lastMessage: newItem.lastMessage,
215 + time: newItem.time,
216 + unread: newItem.unread
217 + }
218 + }
219 + return existingItem
220 + })
221 +
222 + // 检查是否有新的消息需要添加到列表顶部
223 + const existingIds = new Set(conversations.value.map(item => item.id))
224 + const newMessages = transformedData.filter(item => !existingIds.has(item.id))
225 +
226 + if (newMessages.length > 0) {
227 + console.log('轮询:发现新消息', newMessages.length, '条,添加到列表顶部')
228 + conversations.value = [...newMessages, ...conversations.value]
229 + }
230 + }
197 } 231 }
198 } catch (error) { 232 } catch (error) {
199 console.error('轮询获取消息列表失败:', error) 233 console.error('轮询获取消息列表失败:', error)
...@@ -311,8 +345,8 @@ const setActiveTab = async (tabKey) => { ...@@ -311,8 +345,8 @@ const setActiveTab = async (tabKey) => {
311 hasMore.value = true; 345 hasMore.value = true;
312 // 重置加载状态 346 // 重置加载状态
313 loading.value = false; 347 loading.value = false;
314 - // 重置滚动位置 348 + // 重置滚动位置 - 使用更可靠的方式
315 - scrollTop.value = Math.random(); // 使用随机数触发scroll-view重新渲染 349 + scrollTop.value = 0.1; // 使用固定的非零值触发scroll-view重新渲染
316 setTimeout(() => { 350 setTimeout(() => {
317 scrollTop.value = 0; // 重置到顶部 351 scrollTop.value = 0; // 重置到顶部
318 }, 50); 352 }, 50);
...@@ -331,7 +365,10 @@ const setActiveTab = async (tabKey) => { ...@@ -331,7 +365,10 @@ const setActiveTab = async (tabKey) => {
331 }, 150); 365 }, 150);
332 } 366 }
333 367
334 -// 加载更多数据 368 +/**
369 + * 加载更多数据
370 + * 向下滚动时加载下一页数据并追加到现有列表
371 + */
335 const loadMore = async () => { 372 const loadMore = async () => {
336 if (loading.value || !hasMore.value) { 373 if (loading.value || !hasMore.value) {
337 return 374 return
...@@ -339,6 +376,7 @@ const loadMore = async () => { ...@@ -339,6 +376,7 @@ const loadMore = async () => {
339 376
340 try { 377 try {
341 loading.value = true 378 loading.value = true
379 + console.log('加载更多数据,当前页码:', page.value, '当前列表项数:', conversations.value.length)
342 380
343 // 构建请求参数,同时包含状态筛选和关键字搜索 381 // 构建请求参数,同时包含状态筛选和关键字搜索
344 const params = { 382 const params = {
...@@ -375,15 +413,24 @@ const loadMore = async () => { ...@@ -375,15 +413,24 @@ const loadMore = async () => {
375 })) 413 }))
376 414
377 if (transformedData.length > 0) { 415 if (transformedData.length > 0) {
378 - conversations.value.push(...transformedData) 416 + // 保存当前列表长度,用于调试
417 + const prevLength = conversations.value.length
418 +
419 + // 追加新数据到现有列表
420 + conversations.value = [...conversations.value, ...transformedData]
421 +
422 + // 增加页码
379 page.value++ 423 page.value++
424 +
380 // 判断是否还有更多数据 425 // 判断是否还有更多数据
381 hasMore.value = transformedData.length === pageSize 426 hasMore.value = transformedData.length === pageSize
382 } else { 427 } else {
383 hasMore.value = false 428 hasMore.value = false
429 + console.log('没有更多数据')
384 } 430 }
385 } else { 431 } else {
386 hasMore.value = false 432 hasMore.value = false
433 + console.log('API返回无数据')
387 } 434 }
388 } catch (error) { 435 } catch (error) {
389 console.error('加载更多消息失败:', error) 436 console.error('加载更多消息失败:', error)
......