refactor: 设置面板改为右侧抽屉,修复布局跳动问题

- ConfigPanel 重写为 Drawer:右侧 320px 滑入面板 + 半透明遮罩
- 设置按钮始终可见,不依赖连接状态
- 抽屉不推挤主布局,点击遮罩或✕关闭
- 设置项分组显示,带功能描述文案

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-13 16:54:57 +08:00
parent 093dc26fa0
commit f17c3c24a7
3 changed files with 158 additions and 63 deletions

View File

@@ -1,5 +1,5 @@
// ============================================================
// ConfigPanel — 会话配置面板
// ConfigPanel — 右侧抽屉式配置面板
// 职责:TTS 开关、detail level 切换、语言选择
// ============================================================
@@ -13,43 +13,60 @@ interface ConfigPanelProps {
export function ConfigPanel({ config, onUpdate, onClose }: ConfigPanelProps) {
return (
<div className="config-panel">
<div className="config-panel__header">
<span>设置</span>
<button className="config-panel__close" onClick={onClose}>✕</button>
<div className="drawer-overlay" onClick={onClose}>
<div className="drawer" onClick={(e) => e.stopPropagation()}>
<div className="drawer__header">
<span className="drawer__title">设置</span>
<button className="drawer__close" onClick={onClose}>✕</button>
</div>
<div className="drawer__body">
<div className="config-group">
<div className="config-group__title">会话</div>
<label className="config-row">
<div className="config-row__info">
<span className="config-row__label">语音回答</span>
<span className="config-row__desc">AI 回答时同步播放语音</span>
</div>
<input
type="checkbox"
checked={config.ttsEnabled}
onChange={(e) => onUpdate({ ttsEnabled: e.target.checked })}
/>
</label>
<label className="config-row">
<div className="config-row__info">
<span className="config-row__label">图像精度</span>
<span className="config-row__desc">高精度适合识别文字,低精度省流量</span>
</div>
<select
value={config.detailLevel}
onChange={(e) => onUpdate({ detailLevel: e.target.value as "low" | "high" })}
>
<option value="low">低</option>
<option value="high">高</option>
</select>
</label>
<label className="config-row">
<div className="config-row__info">
<span className="config-row__label">语言</span>
<span className="config-row__desc">交互语言偏好</span>
</div>
<select
value={config.language}
onChange={(e) => onUpdate({ language: e.target.value })}
>
<option value="zh-CN">中文</option>
<option value="en-US">English</option>
<option value="ja-JP">日本語</option>
</select>
</label>
</div>
</div>
</div>
<label className="config-row">
<span>语音回答</span>
<input
type="checkbox"
checked={config.ttsEnabled}
onChange={(e) => onUpdate({ ttsEnabled: e.target.checked })}
/>
</label>
<label className="config-row">
<span>图像精度</span>
<select
value={config.detailLevel}
onChange={(e) => onUpdate({ detailLevel: e.target.value as "low" | "high" })}
>
<option value="low">低(省流量)</option>
<option value="high">高(细节丰富)</option>
</select>
</label>
<label className="config-row">
<span>语言</span>
<select
value={config.language}
onChange={(e) => onUpdate({ language: e.target.value })}
>
<option value="zh-CN">中文</option>
<option value="en-US">English</option>
<option value="ja-JP">日本語</option>
</select>
</label>
</div>
);
}