feat(app): add textEngine toggle for chat mode (Coze ↔ S2S)
- localStorage-persistent textEngine state ('coze' | 's2s')
- Header button toggles between the two engines when in chat mode
- ChatPanel remounts on engine switch via key=sessionId-textEngine
- Voice mode completely unaffected
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||||
import { Settings2, Zap, Mic, MessageSquare, History, Plus } from 'lucide-react';
|
import { Settings2, Zap, Mic, MessageSquare, History, Plus, Film } from 'lucide-react';
|
||||||
import VoicePanel from './components/VoicePanel';
|
import VoicePanel from './components/VoicePanel';
|
||||||
import ChatPanel from './components/ChatPanel';
|
import ChatPanel from './components/ChatPanel';
|
||||||
import SettingsPanel from './components/SettingsPanel';
|
import SettingsPanel from './components/SettingsPanel';
|
||||||
import { getVoiceConfig } from './services/voiceApi';
|
import { getVoiceConfig } from './services/voiceApi';
|
||||||
import SessionHistoryPanel from './components/SessionHistoryPanel';
|
import SessionHistoryPanel from './components/SessionHistoryPanel';
|
||||||
|
import VideoPanel from './components/VideoPanel';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const [showSettings, setShowSettings] = useState(false);
|
const [showSettings, setShowSettings] = useState(false);
|
||||||
@@ -19,14 +20,25 @@ export default function App() {
|
|||||||
// 文字聊天消息(用于切回语音时注入上下文)
|
// 文字聊天消息(用于切回语音时注入上下文)
|
||||||
const [chatMessages, setChatMessages] = useState([]);
|
const [chatMessages, setChatMessages] = useState([]);
|
||||||
const [settings, setSettings] = useState({
|
const [settings, setSettings] = useState({
|
||||||
botName: '小智',
|
modelVersion: 'O',
|
||||||
systemRole: '你是一个友善的智能助手,名叫小智。你擅长帮用户解答各类问题。',
|
|
||||||
speakingStyle: '请使用温和、清晰的口吻。',
|
|
||||||
greetingText: '你好,我是你的智能语音助手,有什么可以帮你的吗?',
|
|
||||||
modelVersion: '1.2.1.0',
|
|
||||||
speaker: 'zh_female_vv_jupiter_bigtts',
|
speaker: 'zh_female_vv_jupiter_bigtts',
|
||||||
enableWebSearch: false,
|
enableWebSearch: false,
|
||||||
});
|
});
|
||||||
|
// 文字对话引擎: 'coze' (原方舟 HTTP/SSE) | 's2s' (S2S WebSocket, event 501)
|
||||||
|
const [textEngine, setTextEngine] = useState(() => {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem('bigwo_text_engine') || 'coze';
|
||||||
|
} catch (_) {
|
||||||
|
return 'coze';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const toggleTextEngine = useCallback(() => {
|
||||||
|
setTextEngine((prev) => {
|
||||||
|
const next = prev === 'coze' ? 's2s' : 'coze';
|
||||||
|
try { localStorage.setItem('bigwo_text_engine', next); } catch (_) {}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getVoiceConfig()
|
getVoiceConfig()
|
||||||
@@ -108,14 +120,18 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-sm font-semibold text-white leading-tight">
|
<h1 className="text-sm font-semibold text-white leading-tight">
|
||||||
{mode === 'voice' ? '语音通话' : '文字对话'}
|
{mode === 'voice' ? '语音通话' : mode === 'chat' ? '文字对话' : 'AI 视频'}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-[11px] text-slate-400 leading-tight">
|
<p className="text-[11px] text-slate-400 leading-tight">
|
||||||
{mode === 'voice'
|
{mode === 'voice'
|
||||||
? '直连 S2S 语音 · ChatTTSText'
|
? '直连 S2S 语音 · ChatTTSText'
|
||||||
: handoff?.subtitles?.length > 0
|
: mode === 'chat'
|
||||||
? '语音转接 · 上下文已延续'
|
? (textEngine === 's2s'
|
||||||
: '方舟 LLM · Function Calling'}
|
? 'S2S 文字 · event 501 ChatTextQuery'
|
||||||
|
: (handoff?.subtitles?.length > 0
|
||||||
|
? '语音转接 · 上下文已延续'
|
||||||
|
: '方舟 LLM · Function Calling'))
|
||||||
|
: 'Seedance · AI 视频生成'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -158,7 +174,30 @@ export default function App() {
|
|||||||
>
|
>
|
||||||
<MessageSquare className="w-3 h-3" /> 文字
|
<MessageSquare className="w-3 h-3" /> 文字
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setMode('video')}
|
||||||
|
className={`flex items-center gap-1 px-2.5 py-1 rounded-md text-xs transition-all ${
|
||||||
|
mode === 'video'
|
||||||
|
? 'bg-violet-500/20 text-violet-300 font-medium'
|
||||||
|
: 'text-slate-500 hover:text-slate-300'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Film className="w-3 h-3" /> 视频
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{mode === 'chat' && (
|
||||||
|
<button
|
||||||
|
onClick={toggleTextEngine}
|
||||||
|
className={`px-2 py-1 rounded-md text-[11px] font-medium transition-colors border ${
|
||||||
|
textEngine === 's2s'
|
||||||
|
? 'bg-emerald-500/15 text-emerald-300 border-emerald-500/30'
|
||||||
|
: 'bg-slate-700/40 text-slate-300 border-slate-600/40'
|
||||||
|
}`}
|
||||||
|
title="切换文字对话引擎 (S2S 走 event 501, Coze 走 HTTP/SSE)"
|
||||||
|
>
|
||||||
|
{textEngine === 's2s' ? 'S2S' : 'Coze'}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
{mode === 'voice' && (
|
{mode === 'voice' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowSettings(!showSettings)}
|
onClick={() => setShowSettings(!showSettings)}
|
||||||
@@ -207,18 +246,23 @@ export default function App() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : mode === 'chat' ? (
|
||||||
/* Chat Panel */
|
/* Chat Panel */
|
||||||
handoff && (
|
handoff && (
|
||||||
<ChatPanel
|
<ChatPanel
|
||||||
key={handoff.sessionId}
|
key={`${handoff.sessionId}-${textEngine}`}
|
||||||
sessionId={handoff.sessionId}
|
sessionId={handoff.sessionId}
|
||||||
voiceSubtitles={handoff.subtitles}
|
voiceSubtitles={handoff.subtitles}
|
||||||
settings={settings}
|
settings={settings}
|
||||||
onBack={handleBackToVoice}
|
onBack={handleBackToVoice}
|
||||||
onMessagesChange={setChatMessages}
|
onMessagesChange={setChatMessages}
|
||||||
|
useS2S={textEngine === 's2s'}
|
||||||
|
playAudioReply={false}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
) : (
|
||||||
|
/* Video Panel */
|
||||||
|
<VideoPanel />
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user