feat: 画布聊天面板功能增强

1. 加载历史对话消息(从 API 获取)
2. 选中画布图片时自动添加到对话附件
3. 修复类型错误

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Your Name 2026-02-01 15:13:09 +08:00
parent 6464135cf6
commit 8f90aaba08

View File

@ -104,6 +104,46 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
// Canvas store
const addNode = useCanvasStore((state) => state.addNode);
const nodes = useCanvasStore((state) => state.nodes);
const selectedNodeIds = useCanvasStore((state) => state.selectedNodeIds);
// 获取纯 UUID(去掉 canvas- 前缀)用于 API 调用
const rawChatId = chatId.startsWith('canvas-')
? chatId.replace('canvas-', '')
: chatId;
// 从 API 加载历史消息
const { data: historyData, isLoading: isLoadingHistory } = useSWR<{
messages: ChatMessage[];
}>(rawChatId ? `/api/messages?chatId=${rawChatId}` : null, fetcher);
// 获取选中的图片节点
const selectedImageNodes = nodes.filter(
n => selectedNodeIds.includes(n.id) && n.type === 'image' && (n.data as any)?.src
);
// 当选中画布中的图片时,自动添加到附件
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',
};
});
// 只添加还没在附件中的图片
setAttachments(prev => {
const existingUrls = new Set(prev.map(a => a.url));
const toAdd = newAttachments.filter(a => !existingUrls.has(a.url));
if (toAdd.length > 0) {
return [...prev, ...toAdd];
}
return prev;
});
}
}, [selectedImageNodes.length, selectedNodeIds]);
// 获取模型列表
const { data: modelsData } = useSWR<{
@ -145,6 +185,11 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
imageParamsRef.current = imageParams;
}, [imageParams]);
// 合并 initialMessages 和历史消息
const mergedInitialMessages = historyData?.messages?.length
? historyData.messages
: initialMessages;
const {
messages,
setMessages,
@ -153,7 +198,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
stop,
} = useChat<ChatMessage>({
id: chatId,
messages: initialMessages,
messages: mergedInitialMessages,
experimental_throttle: 100,
generateId: generateUUID,
transport: new DefaultChatTransport({
@ -217,6 +262,16 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
toast.error(error.message || "生成失败");
},
});
// 当历史消息加载完成后,更新消息列表
const hasLoadedHistory = useRef(false);
useEffect(() => {
if (historyData?.messages?.length && !hasLoadedHistory.current) {
hasLoadedHistory.current = true;
setMessages(historyData.messages);
console.log('[CanvasChat] 已加载历史消息:', historyData.messages.length);
}
}, [historyData, setMessages]);
// 监听消息变化,提取图片并添加到画布
const processedMessageIds = useRef<Set<string>>(new Set());
@ -574,9 +629,9 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
)}
>
{/* 附件预览 */}
{message.attachments && message.attachments.length > 0 && (
{(message as any).attachments && (message as any).attachments.length > 0 && (
<div className="flex flex-wrap gap-2 mb-2">
{message.attachments.map((att: any, i: number) => (
{(message as any).attachments.map((att: any, i: number) => (
<img
key={i}
src={att.url}