refactor: 设置面板改为右侧抽屉,修复布局跳动问题
- ConfigPanel 重写为 Drawer:右侧 320px 滑入面板 + 半透明遮罩 - 设置按钮始终可见,不依赖连接状态 - 抽屉不推挤主布局,点击遮罩或✕关闭 - 设置项分组显示,带功能描述文案 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user