From 35c3a8d619f051f6815aaaa7e10ed67303b5d279 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 9 Feb 2026 00:39:49 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=A8=E7=94=BB=E5=B8=83=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E5=9B=BE=E7=89=87=E7=9A=84=E5=8E=9F=E5=A7=8B=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D=E5=9B=9E=E5=A1=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/canvas/CanvasChatPanel.tsx | 60 +++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index 5444b7e..dbb91ed 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -162,6 +162,21 @@ function findNearestUserPrompt(messages: ChatMessage[], assistantIndex: number): return ""; } +const GENERIC_CANVAS_PROMPT_SET = new Set([ + "对话生成", + "图片生成", + "AI生成", + "智能生成", + "自动生成", +]); + +function isGenericCanvasPrompt(prompt: unknown): boolean { + if (typeof prompt !== "string") return true; + const normalized = prompt.trim(); + if (!normalized) return true; + return GENERIC_CANVAS_PROMPT_SET.has(normalized); +} + // 🆕 拾取物品的附件类型扩展 interface PickedObjectAttachment extends Attachment { pickedObject?: { @@ -241,6 +256,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF // Canvas store const addNode = useCanvasStore((state) => state.addNode); + const updateNode = useCanvasStore((state) => state.updateNode); const nodes = useCanvasStore((state) => state.nodes); const selectedNodeIds = useCanvasStore((state) => state.selectedNodeIds); const clearSelection = useCanvasStore((state) => state.clearSelection); @@ -756,6 +772,50 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF }); }, [messages, addNode, nodes]); + // 为历史节点补全可编辑的原始提示词(旧数据里可能只有“对话生成”占位文案) + useEffect(() => { + if (!messages.length || !nodes.length) return; + + const promptByImageUrl = new Map(); + messages.forEach((message, messageIndex) => { + if (message.role !== "assistant") return; + const content = message.parts?.map((p: any) => p.text || "").join("") || ""; + const imageUrls = extractImageUrls(content); + if (!imageUrls.length) return; + + const prompt = findNearestUserPrompt(messages, messageIndex); + if (!prompt) return; + + imageUrls.forEach((url) => { + if (!promptByImageUrl.has(url)) { + promptByImageUrl.set(url, prompt); + } + }); + }); + + nodes.forEach((node) => { + if (node.type !== "image") return; + const data = (node.data as any) || {}; + const src = data.src as string | undefined; + if (!src) return; + if (!isGenericCanvasPrompt(data.prompt)) return; + + const prompt = promptByImageUrl.get(src); + if (!prompt) return; + + updateNode(node.id, { + data: { + ...data, + prompt, + metadata: { + ...(data.metadata || {}), + generationPrompt: prompt, + }, + }, + }); + }); + }, [messages, nodes, updateNode]); + // 滚动到底部 useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });