# Changelog: 音色选择对话框 API 集成 **日期**: 2026-02-10 **类型**: 功能增强 **模块**: 前端 - 音色选择 ## 变更概述 将 `VoiceSelectionDialog` 组件从使用 Mock 数据改为对接真实的 ElevenLabs API,支持动态加载中文音色列表,并添加完整的加载状态、错误处理和缓存机制。 ## 技术实现 ### 1. 类型定义 (`client/src/types/voice.ts`) - 定义 `ElevenLabsVoice` 接口(API 原始响应) - 定义 `VoicesResponse` 接口(API 响应包装) - 保留 `Voice` 接口(组件内部使用) - 实现 `adaptVoice()` 适配器函数(API → 组件类型转换) - 实现 `isChineseVoice()` 筛选函数(检查 `labels.language` 和 `verified_languages`) ### 2. API 服务层 (`client/src/services/api/ai.ts`) ```typescript async getVoices(): Promise { const response = await apiClient.get('/ai/voices'); const chineseVoices = response.voices.filter(isChineseVoice); return { voices: chineseVoices }; } ``` - 新增 `getVoices()` 方法 - 自动筛选支持中文的音色(`zh` 语言标识) ### 3. React Query Hook (`client/src/hooks/api/useVoices.ts`) ```typescript export function useVoices() { return useQuery({ queryKey: ['voices', 'chinese'], queryFn: async () => { const response = await aiApi.getVoices(); return response.voices.map(adaptVoice); }, staleTime: 5 * 60 * 1000, // 5 分钟缓存 gcTime: 10 * 60 * 1000, // 10 分钟垃圾回收 retry: 2, refetchOnWindowFocus: false, }); } ``` - 使用 TanStack Query 管理数据获取 - 自动缓存 5 分钟 - 失败自动重试 2 次 - 返回 `{ data, isLoading, isError, error, refetch }` ### 4. 组件改造 (`VoiceSelectionDialog.tsx`) **新增状态处理**: - ✅ 加载状态:显示 Spinner + "加载音色列表中..." - ✅ 错误状态:显示错误图标 + 错误信息 + "重试"按钮 - ✅ 空状态:显示"暂无可用音色" - ✅ 成功状态:渲染音色列表 **类型适配**: - 支持 `gender: 'male' | 'female' | 'neutral'`(新增中性选项) - 使用 `voice.id` 替代 `voice.voice_id` - 使用 `voice.previewUrl` 替代 `voice.preview_url` ## 数据流 ``` 用户打开对话框 ↓ useVoices() 触发 ↓ 检查缓存(5 分钟内) ↓ 无缓存 aiApi.getVoices() ↓ GET /api/v1/ai/voices ↓ 筛选中文音色(isChineseVoice) ↓ 类型适配(adaptVoice) ↓ 组件渲染 ``` ## 筛选逻辑 音色被认为支持中文,当满足以下任一条件: 1. `voice.labels.language === 'zh'` 2. `voice.verified_languages` 数组中包含 `language === 'zh'` 的项 ## 缓存策略 - **staleTime**: 5 分钟(数据在 5 分钟内被视为新鲜) - **gcTime**: 10 分钟(未使用的缓存 10 分钟后清理) - **refetchOnWindowFocus**: false(窗口聚焦不重新请求) - **retry**: 2 次(失败自动重试) ## 影响范围 **新增文件**: - `client/src/types/voice.ts` - `client/src/hooks/api/useVoices.ts` **修改文件**: - `client/src/services/api/ai.ts` - `client/src/components/features/preview/dialogs/VoiceSelectionDialog.tsx` **保留文件**: - `client/src/mocks/voices.ts`(保留用于开发/测试) ## 后续优化建议 1. **性能优化**:考虑虚拟滚动(音色列表超过 50 个时) 2. **搜索功能**:添加音色名称/标签搜索 3. **分类筛选**:按性别、年龄、用途分类 4. **预加载**:在用户可能打开对话框前预加载数据 5. **错误细化**:区分网络错误、服务器错误、权限错误 ## 测试建议 - [ ] 正常加载:验证音色列表正确显示 - [ ] 加载状态:网络延迟时显示 Spinner - [ ] 错误处理:断网时显示错误提示 - [ ] 重试功能:点击"重试"按钮重新请求 - [ ] 缓存验证:5 分钟内重新打开不发起请求 - [ ] 音色筛选:仅显示中文音色 - [ ] 音频播放:点击播放按钮正常播放预览