feat: 上传图片自动识别并命名画布
1. 使用千问VL模型识别图片主体作为画布名称 2. 第一张上传的图片自动设为画布缩略图 3. 画布列表显示缩略图预览 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
ccf610bcf8
commit
5e642165df
@ -256,14 +256,20 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
}, [messages]);
|
||||
|
||||
// 标记是否已经为当前画布设置过标题(避免重复调用)
|
||||
const hasSetCanvasTitle = useRef(false);
|
||||
|
||||
// 处理发送
|
||||
const handleSend = useCallback(() => {
|
||||
const handleSend = useCallback(async () => {
|
||||
if (!input.trim() && attachments.length === 0) return;
|
||||
if (!selectedModelId) {
|
||||
toast.error("请选择一个模型");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取第一张图片的 URL(用于自动命名和缩略图)
|
||||
const firstImageAttachment = attachments.find(a => a.contentType?.startsWith('image/'));
|
||||
|
||||
// 构建 parts 数组:文件在前,文本在后(与 multimodal-input 一致)
|
||||
const parts: any[] = [];
|
||||
|
||||
@ -313,9 +319,50 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
toast.success(`已将 ${attachments.length} 张图片添加到画布`);
|
||||
}
|
||||
|
||||
// 如果是第一次上传图片,自动识别并设置画布标题和缩略图
|
||||
if (firstImageAttachment && !hasSetCanvasTitle.current) {
|
||||
hasSetCanvasTitle.current = true;
|
||||
|
||||
// 异步调用 AI 识别图片主体并更新画布
|
||||
(async () => {
|
||||
try {
|
||||
// 调用 auto-title API 识别图片主体
|
||||
const response = await fetch('/api/canvas/auto-title', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ imageUrl: firstImageAttachment.url }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const title = data.title || '未命名画布';
|
||||
|
||||
// 提取纯 UUID(去掉 canvas- 前缀)
|
||||
const rawId = chatId.startsWith('canvas-')
|
||||
? chatId.replace('canvas-', '')
|
||||
: chatId;
|
||||
|
||||
// 更新画布标题和缩略图
|
||||
await fetch(`/api/canvas/${rawId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
title: title,
|
||||
thumbnail: firstImageAttachment.url,
|
||||
}),
|
||||
});
|
||||
|
||||
console.log('[CanvasChat] 画布已自动命名为:', title);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[CanvasChat] 自动命名失败:', error);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
setInput("");
|
||||
setAttachments([]);
|
||||
}, [input, attachments, selectedModelId, sendMessage, addNode, nodes.length]);
|
||||
}, [input, attachments, selectedModelId, sendMessage, addNode, nodes.length, chatId]);
|
||||
|
||||
// 处理文件选择
|
||||
const handleFileSelect = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user