From d8d62edf53ffd9d79a1269d73b1f9a1a1d878f82 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 18 Feb 2026 21:30:47 +0800 Subject: [PATCH] fix: rehydrate canvas chat history reliably on initial open --- components/canvas/CanvasChatPanel.tsx | 51 ++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index 65bef11ee..c27d8ed1b 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -597,6 +597,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF const autoContextRef = useRef(null); const pendingLaunchRef = useRef(null); const sessionMenuRef = useRef(null); + const historyScrollTimerRef = useRef | null>(null); // 🆕 标签悬停预览状态 const [tagPreview, setTagPreview] = useState(null); @@ -1597,15 +1598,41 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF } }, [selectedModelId, status, sendMessage, clearSelection]); - // 当历史消息加载完成后,更新消息列表 - const hasLoadedHistory = useRef(false); + // 当历史消息加载完成后,更新消息列表(支持同一会话的增量刷新) + const loadedHistorySignatureRef = useRef(""); useEffect(() => { - if (historyData && !hasLoadedHistory.current) { - hasLoadedHistory.current = true; - setMessages(historyData.messages || []); - console.log('[CanvasChat] 已加载历史消息:', historyData.messages?.length || 0); + if (historyScrollTimerRef.current) { + clearTimeout(historyScrollTimerRef.current); + historyScrollTimerRef.current = null; } - }, [historyData, setMessages]); + + if (!historyData || !rawChatId) return; + if (status === "streaming" || status === "submitted") return; + + const historyMessages = historyData.messages || []; + const lastMessageId = historyMessages.at(-1)?.id || "none"; + const signature = `${rawChatId}:${historyMessages.length}:${lastMessageId}`; + + if (loadedHistorySignatureRef.current === signature) return; + + loadedHistorySignatureRef.current = signature; + setMessages(historyMessages); + console.log("[CanvasChat] 已同步历史消息:", historyMessages.length, signature); + + requestAnimationFrame(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "auto", block: "end" }); + }); + historyScrollTimerRef.current = setTimeout(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "auto", block: "end" }); + historyScrollTimerRef.current = null; + }, 160); + return () => { + if (historyScrollTimerRef.current) { + clearTimeout(historyScrollTimerRef.current); + historyScrollTimerRef.current = null; + } + }; + }, [historyData, rawChatId, setMessages, status]); // 监听消息变化,提取图片并添加到画布 // 只处理新生成的图片,不处理历史消息中的图片 @@ -1613,7 +1640,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF const isInitialLoad = useRef(true); useEffect(() => { - hasLoadedHistory.current = false; + loadedHistorySignatureRef.current = ""; processedMessageIds.current.clear(); isInitialLoad.current = true; hiddenPromptRef.current = null; @@ -3175,6 +3202,14 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF } return part; }); + + const fallbackContent = + typeof (message as any).content === "string" + ? (message as any).content.trim() + : ""; + if (cleanedParts.length === 0 && fallbackContent) { + cleanedParts.push({ type: "text", text: fallbackContent } as any); + } // 检查清理后是否有实际内容(更严格的检查) let hasContent = false;