feat: 画布聊天面板功能增强
1. 加载历史对话消息(从 API 获取) 2. 选中画布图片时自动添加到对话附件 3. 修复类型错误 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
6464135cf6
commit
8f90aaba08
@ -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}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user