import { useState, useEffect, useRef } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Send, Trash2, RefreshCw, Bot, User, Key, Settings2 } from 'lucide-react'; import { useAuth } from '../context/AuthContext'; import { cn } from '../lib/utils'; export default function Test() { const { token: adminToken } = useAuth(); // Initialize state from localStorage const [messages, setMessages] = useState(() => { const saved = localStorage.getItem('test_messages'); return saved ? JSON.parse(saved) : []; }); const [input, setInput] = useState(''); const [models, setModels] = useState([]); const [selectedModel, setSelectedModel] = useState(() => localStorage.getItem('test_selected_model') || ''); const [apiKey, setApiKey] = useState(() => localStorage.getItem('test_api_key') || ''); // Persist API key useEffect(() => { localStorage.setItem('test_api_key', apiKey); }, [apiKey]); // Persist messages useEffect(() => { localStorage.setItem('test_messages', JSON.stringify(messages)); }, [messages]); // Persist selected model useEffect(() => { if (selectedModel) { localStorage.setItem('test_selected_model', selectedModel); } }, [selectedModel]); const [isLoading, setIsLoading] = useState(false); const [isStreaming, setIsStreaming] = useState(false); const messagesEndRef = useRef(null); const fetchModels = async () => { try { const headers = {}; if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`; else if (adminToken) headers['Authorization'] = `Bearer ${adminToken}`; const res = await fetch('/v1/models', { headers: { 'Authorization': `Bearer ${apiKey || 'sk-test'}` } }); if (res.ok) { const data = await res.json(); setModels(data.data || []); if (data.data?.length > 0 && !selectedModel) setSelectedModel(data.data[0].id); } } catch (error) { console.error('Failed to fetch models', error); } }; useEffect(() => { fetchModels(); }, []); useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]); const handleSend = async () => { if (!input.trim() || !selectedModel) return; const userMsg = { role: 'user', content: input }; setMessages(prev => [...prev, userMsg]); setInput(''); setIsLoading(true); setIsStreaming(true); const assistantMsgId = Date.now(); setMessages(prev => [...prev, { role: 'assistant', content: '', id: assistantMsgId }]); try { const response = await fetch('/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey || 'sk-test'}` }, body: JSON.stringify({ model: selectedModel, messages: [...messages, userMsg].map(m => ({ role: m.role, content: m.content })), stream: true }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let assistantContent = ''; while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ') && line !== 'data: [DONE]') { try { const data = JSON.parse(line.slice(6)); const content = data.choices[0]?.delta?.content || ''; assistantContent += content; setMessages(prev => prev.map(msg => msg.id === assistantMsgId ? { ...msg, content: assistantContent } : msg )); } catch (e) { console.error('Error parsing chunk', e); } } } } } catch (error) { setMessages(prev => prev.map(msg => msg.id === assistantMsgId ? { ...msg, content: `Error: ${error.message}` } : msg )); } finally { setIsLoading(false); setIsStreaming(false); } }; return (
开始一段新的对话...