【功能完善】客服聊天历史数据加载和回到顶部

pull/146/head
puhui999 2025-05-08 16:35:01 +08:00
parent c149a54e83
commit 13f674ab4b
1 changed files with 101 additions and 42 deletions

View File

@ -1,9 +1,13 @@
<template> <template>
<!-- 聊天列表使用scroll-view原生组件整体倒置 --> <!-- 聊天列表使用scroll-view原生组件整体倒置 -->
<scroll-view ref="scrollRef" class="chat-scroll-view" scroll-y :refresher-enabled="false" <scroll-view ref="scrollRef" :scroll-top="scroll.top" class="chat-scroll-view" scroll-y :refresher-enabled="false"
@scroll="onScroll" style="transform: scaleY(-1);"> @scroll="onScroll" @scrolltolower="loadMoreHistory" style="transform: scaleY(-1);">
<!-- 消息列表容器 --> <!-- 消息列表容器 -->
<view class="message-container"> <view class="message-container">
<!-- 加载更多提示 -->
<view v-if="isLoading" class="loading-more" style="transform: scaleY(-1);">
<text>加载中...</text>
</view>
<!-- 消息列表 --> <!-- 消息列表 -->
<view class="message-list"> <view class="message-list">
<view v-for="(item, index) in messageList" :key="item.id" class="message-item" <view v-for="(item, index) in messageList" :key="item.id" class="message-item"
@ -18,7 +22,7 @@
<!-- 底部聊天输入框 --> <!-- 底部聊天输入框 -->
<su-fixed bottom> <su-fixed bottom>
<view v-if="showNewMessageTip" :style="backToTopStyle"> <view v-if="showNewMessageTip" :style="backToTopStyle" @click="scrollToTop">
<text>有新消息</text> <text>有新消息</text>
</view> </view>
<slot name="bottom"></slot> <slot name="bottom"></slot>
@ -35,6 +39,13 @@
const messageList = ref([]); // const messageList = ref([]); //
const showNewMessageTip = ref(false); // const showNewMessageTip = ref(false); //
const refreshMessage = ref(false); // const refreshMessage = ref(false); //
const isLoading = ref(false); //
const hasMore = ref(true); //
const scrollRef = ref(null); //
const scroll = ref({
top: 0,
oldTop: 0,
});
const queryParams = reactive({ const queryParams = reactive({
no: 1, // no: 1, //
limit: 20, limit: 20,
@ -50,19 +61,14 @@
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
}); // }); //
// const pagingRef = ref(null); //
const queryList = async (no, limit) => {
//
queryParams.no = no;
queryParams.limit = limit;
await getMessageList();
};
// //
const getMessageList = async () => { const getMessageList = async () => {
isLoading.value = true;
try {
const { data } = await KeFuApi.getKefuMessageList(queryParams); const { data } = await KeFuApi.getKefuMessageList(queryParams);
if (isEmpty(data)) { if (isEmpty(data)) {
// pagingRef.value.completeByNoMore([], true); hasMore.value = false;
return; return;
} }
if (queryParams.no > 1 && refreshMessage.value) { if (queryParams.no > 1 && refreshMessage.value) {
@ -75,24 +81,56 @@
} }
// //
messageList.value = [...newMessageList, ...messageList.value]; messageList.value = [...newMessageList, ...messageList.value];
// pagingRef.value.updateCache(); //
refreshMessage.value = false; // refreshMessage.value = false; //
return; return;
} }
if (queryParams.no > 1) {
// /
if (data.length < queryParams.limit) {
hasMore.value = false; //
}
//
const historyMessages = data.filter(msg =>
!messageList.value.some(existing => existing.id === msg.id),
);
if (historyMessages.length > 0) {
messageList.value = [...messageList.value, ...historyMessages];
}
} else {
//
messageList.value = data;
if (data.length < queryParams.limit) {
hasMore.value = false;
}
}
if (data.slice(-1).length > 0) { if (data.slice(-1).length > 0) {
// createTime // createTime
queryParams.createTime = formatDate(data.slice(-1)[0].createTime); queryParams.createTime = formatDate(data.slice(-1)[0].createTime);
} }
messageList.value = data; } finally {
// pagingRef.value.completeByNoMore(data, false); isLoading.value = false;
}
};
/** 加载更多历史数据 */
const loadMoreHistory = async () => {
if (isLoading.value || !hasMore.value) return;
//
queryParams.no += 1;
await getMessageList();
}; };
/** 刷新消息列表 */ /** 刷新消息列表 */
const refreshMessageList = async (message = undefined) => { const refreshMessageList = async (message = undefined) => {
if (typeof message !== 'undefined') { if (typeof message !== 'undefined') {
// // /
messageList.value.map(message); messageList.value.unshift(message);
// pagingRef.value.addChatRecordData([message], false);
} else { } else {
queryParams.createTime = undefined; queryParams.createTime = undefined;
refreshMessage.value = true; refreshMessage.value = true;
@ -107,10 +145,13 @@
} }
}; };
/** 滚动到最新消息 */ /** 滚动到顶部(倒置后相当于滚动到最新消息) */
const onBackToTopClick = (event) => { const scrollToTop = () => {
event(false); // scroll.value.top = scroll.value.oldTop;
// pagingRef.value.scrollToBottom(); setTimeout(() => {
scroll.value.top = 0;
}, 200) // view
showNewMessageTip.value = false;
}; };
/** 监听滚动到底部事件(因为 scroll 翻转了顶就是底) */ /** 监听滚动到底部事件(因为 scroll 翻转了顶就是底) */
@ -121,15 +162,23 @@
} }
showNewMessageTip.value = false; showNewMessageTip.value = false;
}; };
defineExpose({ getMessageList, refreshMessageList });
defineExpose({ getMessageList, refreshMessageList, scrollToTop });
/** 监听消息列表滚动 */ /** 监听消息列表滚动 */
const onScroll = (e) => { const onScroll = (e) => {
const { scrollTop } = e.detail; const { scrollTop } = e.detail;
console.log('scrollTop', scrollTop); scroll.value.oldTop = scrollTop;
// ""
if (scrollTop > 100) {
showNewMessageTip.value = true;
} else {
showNewMessageTip.value = false;
}
}; };
onMounted(() => { onMounted(() => {
queryParams.no = 1; //
getMessageList(); getMessageList();
}); });
</script> </script>
@ -166,4 +215,14 @@
.message-item { .message-item {
margin-bottom: 10px; margin-bottom: 10px;
} }
.loading-more {
width: 100%;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
color: #999;
font-size: 14px;
}
</style> </style>