fix(web): Fix auto-scroll issue in chat dashboard

This commit is contained in:
WangzJi 2025-06-30 10:42:32 +08:00
parent ef7b17f9ab
commit f97c15b7ed
No known key found for this signature in database
GPG Key ID: C237805F3F8E1CB6

View File

@ -98,12 +98,15 @@ const Completion = ({ messages, onSubmit, onFormatContent }: Props) => {
// Process message content - if onFormatContent is provided and this is a dashboard chat, // Process message content - if onFormatContent is provided and this is a dashboard chat,
// we'll extract the thinking part from vis-thinking code blocks // we'll extract the thinking part from vis-thinking code blocks
const processMessageContent = (content: any) => { const processMessageContent = useCallback(
if (isChartChat && onFormatContent && typeof content === 'string') { (content: any) => {
return onFormatContent(content); if (isChartChat && onFormatContent && typeof content === 'string') {
} return onFormatContent(content);
return content; }
}; return content;
},
[isChartChat, onFormatContent],
);
const [messageApi, contextHolder] = message.useMessage(); const [messageApi, contextHolder] = message.useMessage();
@ -198,9 +201,9 @@ const Completion = ({ messages, onSubmit, onFormatContent }: Props) => {
useEffect(() => { useEffect(() => {
console.log('Completion updating prevMessageCountRef:', { console.log('Completion updating prevMessageCountRef:', {
currentLength: showMessages.length, currentLength: showMessages.length,
prevCount: prevMessageCountRef.current prevCount: prevMessageCountRef.current,
}); });
// Only update if this is the first time (count is 0) // Only update if this is the first time (count is 0)
if (prevMessageCountRef.current === 0) { if (prevMessageCountRef.current === 0) {
prevMessageCountRef.current = showMessages.length; prevMessageCountRef.current = showMessages.length;
@ -213,9 +216,9 @@ const Completion = ({ messages, onSubmit, onFormatContent }: Props) => {
if (isAutoScrollingRef.current) { if (isAutoScrollingRef.current) {
return; return;
} }
lastScrollTimeRef.current = Date.now(); lastScrollTimeRef.current = Date.now();
if (scrollableRef.current) { if (scrollableRef.current) {
const scrollElement = scrollableRef.current; const scrollElement = scrollableRef.current;
const { scrollTop, scrollHeight, clientHeight } = scrollElement; const { scrollTop, scrollHeight, clientHeight } = scrollElement;
@ -241,7 +244,7 @@ const Completion = ({ messages, onSubmit, onFormatContent }: Props) => {
showMessagesLength: showMessages.length, showMessagesLength: showMessages.length,
userRecentlyScrolled, userRecentlyScrolled,
isUserScrolling: isUserScrollingRef.current, isUserScrolling: isUserScrollingRef.current,
isAutoScrolling: isAutoScrollingRef.current isAutoScrolling: isAutoScrollingRef.current,
}); });
// Always handle new messages first - this is the highest priority // Always handle new messages first - this is the highest priority
@ -249,54 +252,54 @@ const Completion = ({ messages, onSubmit, onFormatContent }: Props) => {
console.log('Completion: New message detected, forcing scroll to bottom'); console.log('Completion: New message detected, forcing scroll to bottom');
// New message - always scroll to bottom regardless of user position // New message - always scroll to bottom regardless of user position
isAutoScrollingRef.current = true; isAutoScrollingRef.current = true;
// Reset states IMMEDIATELY to ensure streaming can work // Reset states IMMEDIATELY to ensure streaming can work
lastScrollTimeRef.current = Date.now() - 3000; // Allow streaming immediately lastScrollTimeRef.current = Date.now() - 3000; // Allow streaming immediately
isUserScrollingRef.current = false; isUserScrollingRef.current = false;
lastContentHeightRef.current = scrollElement.scrollHeight; // Set current height as baseline lastContentHeightRef.current = scrollElement.scrollHeight; // Set current height as baseline
scrollElement.scrollTo({ scrollElement.scrollTo({
top: scrollElement.scrollHeight, top: scrollElement.scrollHeight,
behavior: 'smooth', behavior: 'smooth',
}); });
// Reset auto scroll flag after animation // Reset auto scroll flag after animation
setTimeout(() => { setTimeout(() => {
isAutoScrollingRef.current = false; isAutoScrollingRef.current = false;
}, 100); }, 100);
prevMessageCountRef.current = currentMessageCount; // Update count immediately prevMessageCountRef.current = currentMessageCount; // Update count immediately
return; // Exit early for new messages return; // Exit early for new messages
} }
// Handle streaming content updates (only if user hasn't manually scrolled recently) // Handle streaming content updates (only if user hasn't manually scrolled recently)
if (!userRecentlyScrolled && !isUserScrollingRef.current && !isAutoScrollingRef.current) { if (!userRecentlyScrolled && !isUserScrollingRef.current && !isAutoScrollingRef.current) {
// Streaming content - scroll based on content height change // Streaming content - scroll based on content height change
const currentHeight = scrollElement.scrollHeight; const currentHeight = scrollElement.scrollHeight;
// Initialize lastContentHeightRef if not set // Initialize lastContentHeightRef if not set
if (lastContentHeightRef.current === 0) { if (lastContentHeightRef.current === 0) {
lastContentHeightRef.current = currentHeight; lastContentHeightRef.current = currentHeight;
} }
const heightDiff = currentHeight - lastContentHeightRef.current; const heightDiff = currentHeight - lastContentHeightRef.current;
console.log('Completion streaming check:', { console.log('Completion streaming check:', {
currentHeight, currentHeight,
lastHeight: lastContentHeightRef.current, lastHeight: lastContentHeightRef.current,
heightDiff, heightDiff,
threshold: 12 threshold: 12,
}); });
// Only scroll if content height increased by at least ~0.5 lines (12px) for smoother experience // Only scroll if content height increased by at least ~0.5 lines (12px) for smoother experience
if (heightDiff >= 12) { if (heightDiff >= 12) {
// Clear any pending scroll timeout // Clear any pending scroll timeout
if (scrollTimeoutRef.current) { if (scrollTimeoutRef.current) {
clearTimeout(scrollTimeoutRef.current); clearTimeout(scrollTimeoutRef.current);
} }
console.log('Completion: Triggering streaming scroll, heightDiff:', heightDiff); console.log('Completion: Triggering streaming scroll, heightDiff:', heightDiff);
// Debounce scroll calls to avoid conflicts // Debounce scroll calls to avoid conflicts
scrollTimeoutRef.current = setTimeout(() => { scrollTimeoutRef.current = setTimeout(() => {
isAutoScrollingRef.current = true; isAutoScrollingRef.current = true;
@ -314,7 +317,7 @@ const Completion = ({ messages, onSubmit, onFormatContent }: Props) => {
console.log('Completion streaming blocked:', { console.log('Completion streaming blocked:', {
userRecentlyScrolled, userRecentlyScrolled,
isUserScrolling: isUserScrollingRef.current, isUserScrolling: isUserScrollingRef.current,
isAutoScrolling: isAutoScrollingRef.current isAutoScrolling: isAutoScrollingRef.current,
}); });
} }
}, [showMessages, scene]); }, [showMessages, scene]);