diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index 2b3adb4..f5804d8 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -356,6 +356,43 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF // 标记是否已经为当前画布设置过标题(避免重复调用) const hasSetCanvasTitle = useRef(false); + // 获取最近的图片 URL(用于自动附加) + const getRecentImageUrl = useCallback((): string | null => { + // 1. 优先使用画布中选中的图片 + if (selectedImageNodes.length > 0) { + return (selectedImageNodes[0].data as any)?.src || null; + } + + // 2. 其次使用画布中最近添加的图片 + const imageNodes = nodes.filter(n => n.type === 'image' && (n.data as any)?.src); + if (imageNodes.length > 0) { + // 返回最后一个添加的图片(假设数组末尾是最新的) + return (imageNodes[imageNodes.length - 1].data as any)?.src || null; + } + + // 3. 最后从历史对话中查找图片 + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]; + // 检查用户消息的附件 + if (msg.role === 'user' && (msg as any).attachments?.length > 0) { + const attachment = (msg as any).attachments[0]; + if (attachment.url && attachment.contentType?.startsWith('image/')) { + return attachment.url; + } + } + // 检查用户消息的 parts + if (msg.role === 'user' && (msg as any).parts) { + for (const part of (msg as any).parts) { + if (part.type === 'file' && part.url && part.mediaType?.startsWith('image/')) { + return part.url; + } + } + } + } + + return null; + }, [selectedImageNodes, nodes, messages]); + // 处理发送(图片已在上传时添加到画布,这里只发送消息) const handleSend = useCallback(async () => { if (!input.trim() && attachments.length === 0) return; @@ -367,8 +404,23 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF // 构建 parts 数组:文件在前,文本在后(与 multimodal-input 一致) const parts: any[] = []; + // 🆕 如果没有附件,自动使用最近的图片 + let effectiveAttachments = [...attachments]; + if (effectiveAttachments.length === 0 && input.trim()) { + const recentImageUrl = getRecentImageUrl(); + if (recentImageUrl) { + // 自动添加最近的图片作为附件 + effectiveAttachments.push({ + url: recentImageUrl, + name: '最近图片', + contentType: 'image/jpeg', + }); + console.log('[CanvasChat] 自动使用最近图片:', recentImageUrl); + } + } + // 添加文件部分(作为 file 类型的 part) - attachments.forEach((a) => { + effectiveAttachments.forEach((a) => { parts.push({ type: "file" as const, mediaType: a.contentType, @@ -378,7 +430,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF }); // 添加文本部分 - const textContent = input.trim() || (attachments.length > 0 ? "请处理这张图片" : ""); + const textContent = input.trim() || (effectiveAttachments.length > 0 ? "请处理这张图片" : ""); if (textContent) { parts.push({ type: "text" as const, text: textContent }); } @@ -391,7 +443,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF setInput(""); setAttachments([]); - }, [input, attachments, selectedModelId, sendMessage]); + }, [input, attachments, selectedModelId, sendMessage, getRecentImageUrl]); // 处理文件选择 - 上传后立即添加到画布 const handleFileSelect = async (e: React.ChangeEvent) => {