import React, { useState, useEffect, useRef } from 'react'; import { useAuth } from '@/hooks/useAuth'; import AIToolsLayout from '@/components/aitools/AIToolsLayout'; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Bot, Send, Loader2, Eraser } from 'lucide-react'; import { toast } from 'sonner'; import { cn } from '@/lib/utils'; import ReactMarkdown from 'react-markdown'; interface Message { role: 'user' | 'assistant' | 'system'; content: string; timestamp: number; } export default function AIChat() { const { user } = useAuth(); const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const [selectedAssistant, setSelectedAssistant] = useState('system'); const messagesEndRef = useRef(null); // Auto-scroll to bottom useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages]); // Load initial system message based on selected assistant useEffect(() => { if (selectedAssistant === 'system') { // System default } else { // Find custom assistant const assistant = user?.AI配置?.自定义助手列表?.find((a: any) => a.名称 === selectedAssistant); if (assistant && assistant.系统提示词) { // Optionally add a system message to context (not visible) } } }, [selectedAssistant, user]); const handleSend = async () => { if (!input.trim() || isLoading) return; const userMessage: Message = { role: 'user', content: input, timestamp: Date.now() }; setMessages(prev => [...prev, userMessage]); setInput(''); setIsLoading(true); try { const response = await fetch('/api/ai/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: [...messages, userMessage].map(m => ({ role: m.role, content: m.content })), assistantId: selectedAssistant === 'system' ? 'system' : selectedAssistant, mode: selectedAssistant === 'system' ? 'system' : 'custom', // Pass custom config if needed, but backend should fetch from user profile for security }), }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.message || 'Failed to send message'); } // Handle streaming response const reader = response.body?.getReader(); const decoder = new TextDecoder(); const assistantMessage: Message = { role: 'assistant', content: '', timestamp: Date.now() }; setMessages(prev => [...prev, assistantMessage]); if (reader) { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); assistantMessage.content += chunk; setMessages(prev => { const newMessages = [...prev]; newMessages[newMessages.length - 1] = { ...assistantMessage }; return newMessages; }); } } } catch (error: any) { toast.error(error.message || '发送失败,请重试'); // Remove the failed user message or show error state? // For now just show toast } finally { setIsLoading(false); } }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }; const clearHistory = () => { setMessages([]); toast.success('对话历史已清空'); }; // Get available assistants const assistants = [ { value: 'system', label: '系统默认助手 (System)' }, ...(user?.AI配置?.自定义助手列表?.map((a: any) => ({ value: a.名称, label: `${a.名称} (Custom)` })) || []) ]; return (
{/* Header */}

AI 智能对话

当前模式: {selectedAssistant === 'system' ? '系统托管 (消耗积分)' : '自定义 (免费)'}

{/* Chat Area */}
{messages.length === 0 ? (

开始一个新的对话吧...

{['帮我写一篇关于AI的文章', '解释一下量子纠缠', '如何优化React性能', '翻译这段代码'].map((q, i) => ( ))}
) : ( messages.map((msg, index) => (
{msg.role === 'user' ? ( ) : (
)} {msg.role === 'user' ? 'U' : 'AI'}
{msg.role === 'assistant' ? (
{msg.content}
) : (
{msg.content}
)}
)) )} {isLoading && (
正在思考...
)}
{/* Input Area */}
setInput(e.target.value)} onKeyDown={handleKeyDown} placeholder="输入您的问题... (Shift+Enter 换行)" className="pr-12 py-6 rounded-xl bg-muted/50 border-border focus:bg-background transition-colors" disabled={isLoading} />

AI 生成的内容可能不准确,请核实重要信息。

); }