import { useState, useEffect, useCallback, useRef } from 'react'; import { Settings2, Zap, Mic, MessageSquare } from 'lucide-react'; import VoicePanel from './components/VoicePanel'; import ChatPanel from './components/ChatPanel'; import SettingsPanel from './components/SettingsPanel'; import { getVoiceConfig } from './services/voiceApi'; export default function App() { const [showSettings, setShowSettings] = useState(false); const [voiceConfig, setVoiceConfig] = useState(null); // 'voice' | 'chat' const [mode, setMode] = useState('voice'); // 统一会话 ID(贯穿语音和文字模式,数据库用此 ID 关联所有消息) const [currentSessionId, setCurrentSessionId] = useState(null); // 语音转文字的交接数据(保留兼容) const [handoff, setHandoff] = useState(null); // 文字聊天消息(用于切回语音时注入上下文) const [chatMessages, setChatMessages] = useState([]); const [settings, setSettings] = useState({ botName: '小智', systemRole: '你是一个友善的智能助手,名叫小智。你擅长帮用户解答各类问题。', speakingStyle: '请使用温和、清晰的口吻。', modelVersion: '1.2.1.0', speaker: 'zh_female_vv_jupiter_bigtts', enableWebSearch: false, }); useEffect(() => { getVoiceConfig() .then(setVoiceConfig) .catch((err) => console.warn('Failed to load config:', err)); }, []); // 语音通话结束后,无缝切换到文字对话(携带同一个 sessionId) const handleVoiceEnd = useCallback((data) => { if (data?.sessionId) { const sid = data.sessionId; setCurrentSessionId(sid); setHandoff({ sessionId: sid, subtitles: data.subtitles || [], }); setMode('chat'); console.log(`[App] Voice→Chat, sessionId=${sid}`); } }, []); // 从文字模式返回语音模式(使用同一个 sessionId,数据库已有完整历史) const handleBackToVoice = useCallback(() => { console.log(`[App] Chat→Voice, sessionId=${currentSessionId}`); setMode('voice'); }, [currentSessionId]); // 直接进入文字模式(新会话) const handleStartChat = useCallback(() => { const newSid = `chat_${Date.now().toString(36)}`; setCurrentSessionId(newSid); setHandoff({ sessionId: newSid, subtitles: [], }); setMode('chat'); console.log(`[App] New chat session: ${newSid}`); }, []); return (
{mode === 'voice' ? '混合编排模式 · OutputMode=1' : handoff?.subtitles?.length > 0 ? '语音转接 · 上下文已延续' : '方舟 LLM · Function Calling'}