diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index 93aced7..d51ff2d 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -108,6 +108,8 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF const nodes = useCanvasStore((state) => state.nodes); const selectedNodeIds = useCanvasStore((state) => state.selectedNodeIds); const clearSelection = useCanvasStore((state) => state.clearSelection); + const pendingChatAttachments = useCanvasStore((state) => state.pendingChatAttachments); + const clearPendingChatAttachments = useCanvasStore((state) => state.clearPendingChatAttachments); // 获取纯 UUID(去掉 canvas- 前缀)用于 API 调用 const rawChatId = chatId.startsWith('canvas-') @@ -159,33 +161,30 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF } }, []); - // 当选中画布中的图片时,自动添加到附件并插入标签 + // 🆕 监听 pendingChatAttachments,当用户点击"添加到对话"按钮时添加标签 useEffect(() => { - if (selectedImageNodes.length > 0) { - const newAttachments: Attachment[] = selectedImageNodes.map(node => { - const data = node.data as any; - return { - url: data.src, - name: data.prompt || '画布图片', - contentType: 'image/jpeg', - }; - }); - + if (pendingChatAttachments.length > 0) { // 只添加还没在附件中的图片 setAttachments(prev => { const existingUrls = new Set(prev.map(a => a.url)); - const toAdd = newAttachments.filter(a => !existingUrls.has(a.url)); + const toAdd = pendingChatAttachments.filter(a => !existingUrls.has(a.url)); if (toAdd.length > 0) { // 插入图片标签到编辑器 toAdd.forEach((att, i) => { insertImageTagInEditor(att.url, att.name, prev.length + i); }); + // 聚焦到输入框 + setTimeout(() => { + (textareaRef.current as HTMLDivElement | null)?.focus(); + }, 0); return [...prev, ...toAdd]; } return prev; }); + // 清空待添加列表 + clearPendingChatAttachments(); } - }, [selectedImageNodes.length, selectedNodeIds, insertImageTagInEditor]); + }, [pendingChatAttachments, insertImageTagInEditor, clearPendingChatAttachments]); // 获取模型列表 const { data: modelsData } = useSWR<{ diff --git a/components/canvas/nodes/ImageNode.tsx b/components/canvas/nodes/ImageNode.tsx index 54666ee..6629d43 100644 --- a/components/canvas/nodes/ImageNode.tsx +++ b/components/canvas/nodes/ImageNode.tsx @@ -2,7 +2,7 @@ import React, { useState, useRef, useEffect } from "react"; import { createPortal } from "react-dom"; -import { ImagePlus, Loader2, AlertCircle, MoreVertical, Scissors, Sparkles, Expand, Maximize2, Move3D, Layers, Download, Trash2, RefreshCw, Pencil } from "lucide-react"; +import { ImagePlus, Loader2, AlertCircle, MoreVertical, Scissors, Sparkles, Expand, Maximize2, Move3D, Layers, Download, Trash2, RefreshCw, Pencil, MessageSquarePlus } from "lucide-react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, @@ -53,6 +53,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { const updateNode = useCanvasStore((state) => state.updateNode); const deleteNode = useCanvasStore((state) => state.deleteNode); const addNode = useCanvasStore((state) => state.addNode); + const addPendingChatAttachment = useCanvasStore((state) => state.addPendingChatAttachment); // 获取工具栏位置 - 在渲染时直接计算 const getToolbarPosition = () => { @@ -572,6 +573,28 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { }} onClick={(e) => e.stopPropagation()} > + {/* 🆕 添加到对话 */} + + + {/* 分隔线 */} +
+ {/* 放大/高清 */}