diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index e9fb48a26..44a2db76f 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -1186,6 +1186,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF const imageParamsRef = useRef(imageParams); const videoParamsRef = useRef(videoParams); const deepThinkingEnabledRef = useRef(deepThinkingEnabled); + const imageAutoTitleCacheRef = useRef>(new Map()); const handleTypewriterActiveChange = useCallback((typingKey: string, active: boolean) => { setActiveTypingSections((prev) => { @@ -1206,6 +1207,60 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF ); }, []); + const autoNameGeneratedImageNode = useCallback( + async (nodeId: string, imageUrl: string) => { + if (!nodeId || !imageUrl) return; + + const normalizeAutoTitle = (rawTitle: string) => { + const compact = String(rawTitle || "").replace(/\s+/g, "").trim(); + if (!compact || compact === "新画布" || compact === "未命名画布" || compact.includes("画布")) { + return "图片"; + } + return compact.slice(0, 12); + }; + + const applyNodeTitle = (title: string) => { + const storeState = useCanvasStore.getState(); + const currentNode = storeState.getNode(nodeId); + if (!currentNode) return; + const currentData = ((currentNode.data as any) || {}) as Record; + storeState.updateNode(nodeId, { + data: { + ...currentData, + title, + metadata: { + ...(currentData.metadata || {}), + autoTitle: title, + }, + }, + }); + }; + + const cachedTitle = imageAutoTitleCacheRef.current.get(imageUrl); + if (cachedTitle) { + applyNodeTitle(cachedTitle); + return; + } + + try { + const response = await fetch('/api/canvas/auto-title', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ imageUrl }), + }); + + const data = await response.json().catch(() => ({})); + const title = normalizeAutoTitle(String(data?.title || "")); + imageAutoTitleCacheRef.current.set(imageUrl, title); + applyNodeTitle(title); + } catch (error) { + console.warn('[CanvasChat] 自动命名图片失败:', error); + applyNodeTitle("图片"); + } + }, + [], + ); + // 🆕 保存图片参数到 localStorage const handleImageParamsChange = (params: ImageGenerationParams) => { setImageParams(params); @@ -2809,7 +2864,6 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF // 标记是否已经为当前画布设置过标题(避免重复调用) const hasSetCanvasTitle = useRef(false); - const imageAutoTitleCacheRef = useRef>(new Map()); // 🆕 Agent模式上下文(画布图片布局) const buildAutoContext = useCallback(() => { @@ -4458,60 +4512,6 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF } }, [chatId]); - const autoNameGeneratedImageNode = useCallback( - async (nodeId: string, imageUrl: string) => { - if (!nodeId || !imageUrl) return; - - const normalizeAutoTitle = (rawTitle: string) => { - const compact = String(rawTitle || "").replace(/\s+/g, "").trim(); - if (!compact || compact === "新画布" || compact === "未命名画布" || compact.includes("画布")) { - return "图片"; - } - return compact.slice(0, 12); - }; - - const applyNodeTitle = (title: string) => { - const storeState = useCanvasStore.getState(); - const currentNode = storeState.getNode(nodeId); - if (!currentNode) return; - const currentData = ((currentNode.data as any) || {}) as Record; - storeState.updateNode(nodeId, { - data: { - ...currentData, - title, - metadata: { - ...(currentData.metadata || {}), - autoTitle: title, - }, - }, - }); - }; - - const cachedTitle = imageAutoTitleCacheRef.current.get(imageUrl); - if (cachedTitle) { - applyNodeTitle(cachedTitle); - return; - } - - try { - const response = await fetch('/api/canvas/auto-title', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ imageUrl }), - }); - - const data = await response.json().catch(() => ({})); - const title = normalizeAutoTitle(String(data?.title || "")); - imageAutoTitleCacheRef.current.set(imageUrl, title); - applyNodeTitle(title); - } catch (error) { - console.warn('[CanvasChat] 自动命名图片失败:', error); - applyNodeTitle("图片"); - } - }, - [], - ); - const uploadImageFileAndAddToCanvas = useCallback(async ( file: File, nodeIndex: number