feat: 处理消息发送之后的页面滚动问题
This commit is contained in:
@@ -83,8 +83,8 @@ import userAvatar from '@assets/images/login/user_icon.png';
|
|||||||
import aiAvatar from '@assets/images/login/blue_logo.png';
|
import aiAvatar from '@assets/images/login/blue_logo.png';
|
||||||
|
|
||||||
|
|
||||||
///(控制滚动位置)
|
// 列表滚动容器引用
|
||||||
const scrollTop = ref(99999);
|
const listRef = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
/// 会话列表
|
/// 会话列表
|
||||||
const chatMsgList = ref<ChatMessage[]>([]);
|
const chatMsgList = ref<ChatMessage[]>([]);
|
||||||
@@ -93,8 +93,8 @@ const inputMessage = ref("");
|
|||||||
/// 发送消息中标志
|
/// 发送消息中标志
|
||||||
const isSendingMessage = ref(false);
|
const isSendingMessage = ref(false);
|
||||||
|
|
||||||
/// agentId 首页接口中获取
|
/// agentId 首页接口中获取 1953462165250859010
|
||||||
const agentId = ref("1953462165250859010");
|
const agentId = ref("1");
|
||||||
/// 会话ID 历史数据接口中获取
|
/// 会话ID 历史数据接口中获取
|
||||||
const conversationId = ref("");
|
const conversationId = ref("");
|
||||||
// 会话进行中标志
|
// 会话进行中标志
|
||||||
@@ -123,15 +123,39 @@ const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms));
|
|||||||
// 当前会话的消息ID,用于保持发送和终止的messageId一致
|
// 当前会话的消息ID,用于保持发送和终止的messageId一致
|
||||||
let currentSessionMessageId: string | null = null;
|
let currentSessionMessageId: string | null = null;
|
||||||
|
|
||||||
// 滚动到底部 - 优化版本,确保打字机效果始终可见
|
// 滚动到底部 - 精确计算 last 元素位置并使用双 rAF 保证布局稳定
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = (smooth = false) => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 使用更大的值确保滚动到真正的底部
|
const el = listRef.value;
|
||||||
scrollTop.value = 99999;
|
if (!el) return;
|
||||||
// 强制触发滚动更新,增加延迟确保DOM更新完成
|
|
||||||
setTimeout(() => {
|
const doScroll = () => {
|
||||||
scrollTop.value = scrollTop.value + Math.random();
|
const last = el.lastElementChild as HTMLElement | null;
|
||||||
}, 10);
|
// 计算容器 style padding-bottom,保证滚动到真正可视底部
|
||||||
|
const style = window.getComputedStyle(el);
|
||||||
|
const paddingBottom = parseFloat(style.paddingBottom || '0') || 0;
|
||||||
|
|
||||||
|
if (last) {
|
||||||
|
const lastOffset = last.offsetTop + last.offsetHeight;
|
||||||
|
const target = lastOffset + paddingBottom - el.clientHeight;
|
||||||
|
const top = Math.max(0, Math.ceil(target));
|
||||||
|
if (smooth && typeof el.scrollTo === 'function') {
|
||||||
|
el.scrollTo({ top, behavior: 'smooth' });
|
||||||
|
} else {
|
||||||
|
el.scrollTop = top;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兜底:滚到底
|
||||||
|
if (smooth && typeof el.scrollTo === 'function') {
|
||||||
|
el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });
|
||||||
|
} else {
|
||||||
|
el.scrollTop = el.scrollHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 使用两次 requestAnimationFrame 增强在复杂渲染/打字机更新场景的可靠性
|
||||||
|
requestAnimationFrame(() => requestAnimationFrame(doScroll));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -388,6 +412,7 @@ const handleWebSocketMessage = (data: any) => {
|
|||||||
isSessionActive.value = false;
|
isSessionActive.value = false;
|
||||||
// 清理当前会话的 messageId,避免保留陈旧 id
|
// 清理当前会话的 messageId,避免保留陈旧 id
|
||||||
resetMessageState();
|
resetMessageState();
|
||||||
|
setTimeoutScrollToBottom();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user