chore:进入客服页面不乱跳了

This commit is contained in:
2025-12-16 14:07:59 +08:00
parent 5503758854
commit ee6c777fb1

View File

@@ -5,8 +5,8 @@
class="chat-messages" class="chat-messages"
scroll-y scroll-y
:scroll-top="scrollTop" :scroll-top="scrollTop"
@scrolltoupper="loadMoreHistory" @scroll="onScroll"
:scroll-with-animation="true"> :scroll-with-animation="false">
<!-- 加载更多历史消息 --> <!-- 加载更多历史消息 -->
<view class="load-more" v-if="hasMoreHistory"> <view class="load-more" v-if="hasMoreHistory">
@@ -16,7 +16,7 @@
<!-- 消息列表 --> <!-- 消息列表 -->
<view <view
v-for="(message, index) in messages" v-for="(message, index) in messages"
:key="message.id + '-' + index" :key="`msg-${message.id || message.timestamp}-${index}`"
class="message-item" class="message-item"
:class="[message.role, { 'first-message': index === 0 }]"> :class="[message.role, { 'first-message': index === 0 }]">
@@ -402,7 +402,7 @@ export default {
default: 20 default: 20
} }
}, },
data() { data(){
return { return {
messages: [], messages: [],
inputText: '', inputText: '',
@@ -437,7 +437,11 @@ export default {
isAIServiceAvailable: true, isAIServiceAvailable: true,
aiServiceError: null, aiServiceError: null,
isLoadingHistory: false, // 新增:标记历史加载状态 isLoadingHistory: false, // 新增:标记历史加载状态
shouldScrollToBottom: false shouldScrollToBottom: false,
scrollTimer: null,
lastScrollTop: 0,
historyOffset: 0,
isFetchingHistory: false
} }
}, },
onShow() { onShow() {
@@ -449,10 +453,17 @@ export default {
} else { } else {
this.currentConversationId = aiService.getConversationId(); this.currentConversationId = aiService.getConversationId();
} }
this.loadChatHistoryIfExist(); // 加载初始历史后同步historyOffset
this.loadChatHistoryIfExist().then(() => {
// 初始历史条数作为偏移量
}, this.historyOffset = this.messages.length;
});
// 移除this.historyOffset = 0;(避免覆盖初始历史的偏移量)
},
// 新增:组件销毁时清除防抖定时器
beforeDestroy() {
if (this.scrollTimer) clearTimeout(this.scrollTimer);
},
created() { created() {
this.messages = [...this.initialMessages] this.messages = [...this.initialMessages]
this.messageId = this.messages.length this.messageId = this.messages.length
@@ -505,7 +516,18 @@ export default {
} }
// #endif // #endif
}, },
onScroll(e) {
const currentScrollTop = e.detail.scrollTop;
this.lastScrollTop = currentScrollTop;
// 防抖处理50ms内只执行一次避免频繁触发
if (this.scrollTimer) clearTimeout(this.scrollTimer);
this.scrollTimer = setTimeout(() => {
// 滚动到顶部附近(<20px、不在加载中、显示加载更多时触发加载
if (currentScrollTop < 20 && !this.isLoadingHistory && this.showLoadMore) {
this.loadMoreHistory();
}
}, 50);
},
// 初始化用户头像(支持缓存持久化) // 初始化用户头像(支持缓存持久化)
initUserAvatarData() { initUserAvatarData() {
// 1. 优先读取本地缓存的头像 // 1. 优先读取本地缓存的头像
@@ -927,68 +949,76 @@ export default {
}, },
// 加载更多历史消息 // 加载更多历史消息
async loadMoreHistory() { async loadMoreHistory() {
if (!this.currentConversationId) { if (!this.currentConversationId) {
this.currentConversationId = this.getConversationIdFromLocal(); this.currentConversationId = this.getConversationIdFromLocal();
aiService.setConversationId(this.currentConversationId); aiService.setConversationId(this.currentConversationId);
} }
if (!this.showLoadMore || !this.currentConversationId || this.isLoadingHistory) { // 防止重复加载
return if (!this.showLoadMore || !this.currentConversationId || this.isLoadingHistory) {
} return;
}
this.isFetchingHistory = true;
this.isLoadingHistory = true;
this.loadingText = '加载历史消息中...';
this.hasMoreHistory = true;
this.isLoadingHistory = true try {
this.loadingText = '加载历史消息中...' // 关键修改用独立的historyOffset作为偏移量不再依赖messages.length
this.hasMoreHistory = true const response = await aiService.getConversationHistory({
conversation_id: this.currentConversationId,
limit: 20,
offset: this.historyOffset // 改用独立偏移量
});
try { if (response.success && Array.isArray(response.messages) && response.messages.length > 0) {
const response = await aiService.getConversationHistory({ const historyMessages = response.messages.map(msg => ({
conversation_id: this.currentConversationId, id: msg.id || `history-${Date.now()}-${Math.random().toString(36).slice(2)}`,
limit: 20, role: msg.role === 'user' ? 'user' : 'ai',
offset: this.messages.length type: 'text',
}) content: msg.content,
timestamp: msg.create_time * 1000
}));
if (response.success && Array.isArray(response.messages)) { // 1. 记录新增消息数量
const historyMessages = response.messages.map(msg => ({ const newMsgCount = historyMessages.length;
id: msg.id, // 2. 添加到消息列表开头
role: msg.role === 'user' ? 'user' : 'ai', this.messages = [...historyMessages, ...this.messages];
type: 'text', // 3. 更新历史偏移量(累加,不是覆盖)
content: msg.content, this.historyOffset += newMsgCount;
timestamp: msg.create_time * 1000
}))
if (historyMessages.length > 0) { // 4. 等待DOM渲染后精准计算滚动位置
this.messages = [...historyMessages, ...this.messages] await this.$nextTick();
// 获取新增消息的实际DOM高度
// 👇 注意:这里加了 async const query = uni.createSelectorQuery().in(this);
this.$nextTick(async () => { const heightPromises = [];
const query = uni.createSelectorQuery().in(this) for (let i = 0; i < newMsgCount; i++) {
query.select('.chat-messages').boundingClientRect() heightPromises.push(new Promise(resolve => {
query.select('.chat-messages').scrollOffset() query.select(`.message-item:nth-child(${i + 1})`).boundingClientRect(rect => {
resolve(rect ? rect.height + 32 : 0); // 加上消息间距32rpx
const res = await new Promise((resolve) => { }).exec();
query.exec(resolve) }));
}) }
// 计算总高度
const currentScrollTop = res[1]?.scrollTop || 0 const heights = await Promise.all(heightPromises);
const avgMessageHeight = 80 const totalNewHeight = heights.reduce((sum, h) => sum + h, 0);
const addedHeight = historyMessages.length * avgMessageHeight // 5. 设置scrollTop保持滚动条在顶部附近
this.scrollTop = totalNewHeight;
this.scrollTop = currentScrollTop - addedHeight } else {
}) // 无更多历史
} this.showLoadMore = false;
} else { }
this.showLoadMore = false } catch (error) {
} console.error('加载历史失败:', error);
} catch (error) { uni.showToast({ title: '加载历史失败', icon: 'none' });
console.error('加载历史失败:', error) this.showLoadMore = false;
uni.showToast({ title: '加载历史失败', icon: 'none' }) } finally {
this.showLoadMore = false this.isLoadingHistory = false;
} finally { this.isFetchingHistory = false;
this.isLoadingHistory = false this.hasMoreHistory = false;
this.hasMoreHistory = false this.loadingText = '加载更多历史消息';
this.loadingText = '加载更多历史消息' }
} },
},
// 显示更多工具 // 显示更多工具
showMoreTools() { showMoreTools() {
this.showToolsPanel = true this.showToolsPanel = true