diff --git a/web/src/app/admin/ai-chat/page.tsx b/web/src/app/admin/ai-chat/page.tsx index 3e640d6..a9ed66b 100644 --- a/web/src/app/admin/ai-chat/page.tsx +++ b/web/src/app/admin/ai-chat/page.tsx @@ -46,7 +46,6 @@ export default function AiChatPage() { const [streamingMessageId, setStreamingMessageId] = useState(null); const [optimisticMessages, setOptimisticMessages] = useState>({}); const messagesEndRef = useRef(null); - const hasAttemptedAutoCreate = useRef(false); useToastFeedback({ errorMessage: error, @@ -104,11 +103,9 @@ export default function AiChatPage() { queryClient.invalidateQueries({ queryKey: ["ai-chat-conversations"] }); setSelectedConvId(data.id); setSuccess("创建对话成功"); - hasAttemptedAutoCreate.current = false; }, onError: (err: Error) => { setError(`创建对话失败: ${err.message}`); - hasAttemptedAutoCreate.current = false; }, }); @@ -271,13 +268,36 @@ export default function AiChatPage() { }, }); - const handleSendMessage = useCallback(() => { - if (!selectedConvId || !messageInput.trim()) return; - sendMessageMutation.mutate({ - convId: selectedConvId, - content: messageInput.trim(), - }); - }, [selectedConvId, messageInput, sendMessageMutation]); + const handleSendMessage = useCallback(async () => { + const content = messageInput.trim(); + if (!content) return; + + // If no conversation is selected, create one with a title based on the message + if (!selectedConvId) { + try { + // Generate title from the first message (take first 20 chars or up to first newline) + const title = content.length > 20 + ? content.substring(0, 20) + "..." + : content.split('\n')[0] || "新对话"; + + const newConv = await createConvMutation.mutateAsync(title); + // Send the message to the newly created conversation + sendMessageMutation.mutate({ + convId: newConv.id, + content, + }); + } catch (err) { + // Error already handled by createConvMutation + return; + } + } else { + // Send to existing conversation + sendMessageMutation.mutate({ + convId: selectedConvId, + content, + }); + } + }, [selectedConvId, messageInput, sendMessageMutation, createConvMutation]); useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); @@ -290,14 +310,6 @@ export default function AiChatPage() { } }, [convLoading, conversations?.items, selectedConvId, createConvMutation.isPending]); - // Auto-create conversation if none exist (only on initial load, not after deletions) - useEffect(() => { - if (!convLoading && conversations?.items && conversations.items.length === 0 && !hasAttemptedAutoCreate.current && !createConvMutation.isPending) { - hasAttemptedAutoCreate.current = true; - createConvMutation.mutate("新对话"); - } - }, [convLoading, conversations?.items, createConvMutation]); - if (initializing) { return (
@@ -335,7 +347,7 @@ export default function AiChatPage() { ) : conversations?.items.length === 0 ? (
- {createConvMutation.isPending ? "正在创建对话..." : "暂无对话"} + 暂无对话
) : ( @@ -441,12 +453,74 @@ export default function AiChatPage() { }} > {!selectedConvId ? ( -
- -
+ <> + {/* Welcome Area */} +
+
+ + + 欢迎使用 AI 问答助手 + + + {conversations?.items && conversations.items.length > 0 + ? "选择左侧对话继续,或直接输入问题开始新对话" + : "输入您的问题,开始第一个对话"} + +
+ } + image={Empty.PRESENTED_IMAGE_SIMPLE} + /> +
+
+ + {/* Input Area for new conversation */} +
+
+