feat: 实现会话配置与多轮上下文
All checks were successful
Backend CI / ci (pull_request) Successful in 1m0s
Frontend CI / ci (pull_request) Successful in 1m0s

- 新增 ConfigPanel 组件:TTS 开关、detail level、语言选择
- 新增 storage.ts:配置持久化到 localStorage
- useVisionSession:连接后自动发送 config,维护最近 10 轮对话历史
- App:齿轮按钮展开配置面板,HD 角标,TTS 播放联动 ttsEnabled

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-13 14:19:47 +08:00
parent 8033807f7c
commit 7e3762b589
5 changed files with 267 additions and 18 deletions

View File

@@ -2,13 +2,17 @@
// CamTalk — 主应用组件
// ============================================================
import { useState } from "react";
import { useVisionSession } from "./hooks/useVisionSession";
import { VideoPreview } from "./components/VideoPreview";
import { ChatPanel } from "./components/ChatPanel";
import { ConfigPanel } from "./components/ConfigPanel";
import { ToastContainer } from "./components/Toast";
import "./App.css";
function App() {
const [showConfig, setShowConfig] = useState(false);
const {
messages,
currentReply,
@@ -20,6 +24,8 @@ function App() {
connectionStatus,
videoRef,
stream,
config,
updateConfig,
startSession,
stopSession,
interrupt,
@@ -31,20 +37,44 @@ function App() {
<div className="app">
<header className="app-header">
<h1>CamTalk</h1>
<span className={`status status--${connectionStatus}`}>
{isConnected
? "已连接"
: connectionStatus === "connecting"
? "连接中..."
: "连接"}
</span>
<div className="header-right">
<span className={`status status--${connectionStatus}`}>
{isConnected
? "已连接"
: connectionStatus === "connecting"
? "连接中..."
: "未连接"}
</span>
{isConnected && (
<button
className="btn-icon"
onClick={() => setShowConfig((v) => !v)}
title="设置"
>
</button>
)}
</div>
</header>
{showConfig && (
<ConfigPanel
config={config}
onUpdate={updateConfig}
onClose={() => setShowConfig(false)}
/>
)}
<main className="app-main">
<div className="video-section">
<VideoPreview ref={videoRef} isStreaming={!!stream} />
{config.detailLevel === "high" && (
<div className="detail-badge">HD</div>
)}
{isSpeaking && <div className="vad-indicator">🎤 ...</div>}
{isAudioPlaying && <div className="vad-indicator vad-indicator--audio">🔊 ...</div>}
{isAudioPlaying && config.ttsEnabled && (
<div className="vad-indicator vad-indicator--audio">🔊 ...</div>
)}
{isConnected && !isVADReady && !vadError && (
<div className="vad-indicator vad-indicator--loading">
...