fix: 在 onFinish 后从数据库重新加载消息

这是根治方案 B:
1. 添加 GET /api/messages 端点从数据库获取消息
2. 在 onFinish 后延迟 500ms,然后从数据库重新加载消息
3. 更新 setMessages 和清空 appendedMessages

这确保了 data-appendMessage 保存到数据库的消息能正确显示

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Your Name 2026-02-01 10:58:08 +08:00
parent 7943b7fa5b
commit 05236a7b86
2 changed files with 72 additions and 4 deletions

View File

@ -1,8 +1,56 @@
import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/app/(auth)/auth";
import { saveMessages } from "@/lib/db/queries";
import { saveMessages, getMessagesByChatId } from "@/lib/db/queries";
import type { DBMessage } from "@/lib/db/schema";
/**
* 获取聊天消息
* 用于从数据库重新加载消息
*/
export async function GET(request: NextRequest) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const chatId = request.nextUrl.searchParams.get("chatId");
if (!chatId) {
return NextResponse.json(
{ error: "Missing required parameter: chatId" },
{ status: 400 }
);
}
// 从数据库获取消息
const messages = await getMessagesByChatId({ id: chatId });
// 转换为前端格式
const formattedMessages = messages.map((msg: DBMessage) => {
const parts = msg.parts as any[] || [];
const firstPart = parts[0] as any;
return {
id: msg.id,
role: msg.role,
content: firstPart?.text || "",
createdAt: msg.createdAt,
parts: parts,
attachments: msg.attachments || [],
};
});
return NextResponse.json({ messages: formattedMessages });
} catch (error) {
console.error("[Messages API] GET Error:", error);
return NextResponse.json(
{ error: "Failed to get messages" },
{ status: 500 }
);
}
}
/**
* 保存消息到数据库的API
* 用于图片处理等场景中保存助手回复消息

View File

@ -356,13 +356,33 @@ export function Chat({
}
}
},
onFinish: () => {
onFinish: async () => {
mutate(unstable_serialize(getChatHistoryPaginationKey));
// 🆕 生成完成,清除持久化状态
completeGeneration();
console.log("[Chat] onFinish called");
// 🆕 不再尝试在 onFinish 中合并消息,完全依赖 mergedMessages
// 消息会在下次页面加载时从数据库正确获取
// 🆕 从数据库重新加载消息,确保 data-appendMessage 的消息正确显示
// 这是根治方案 B:后端已保存消息到数据库,前端从数据库重新加载
try {
// 延迟一小段时间确保数据库写入完成
await new Promise(resolve => setTimeout(resolve, 500));
// 获取最新消息
const response = await fetch(`/api/messages?chatId=${id}`);
if (response.ok) {
const data = await response.json();
if (data.messages && Array.isArray(data.messages)) {
console.log("[Chat] Reloading messages from database:", data.messages.length);
// 更新消息状态
setMessages(data.messages);
// 清空 appendedMessages,因为已经从数据库加载了完整消息
setAppendedMessages([]);
}
}
} catch (error) {
console.error("[Chat] Failed to reload messages:", error);
}
},
onError: (error) => {
if (error instanceof ChatSDKError) {