refactor(CloneModal): 音色克隆弹窗目录化拆分(602→440行, -27%) #1186
Reference in New Issue
Block a user
Delete Branch "refactor/clone-modal-split"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
变更内容
将
CloneModal.tsx(602行)目录化拆分,降低单文件复杂度:拆分结构
改动说明
useAudioRecorderHook,封装浏览器录音完整逻辑,可复用于其他录音场景validateFile、formatRecordTime纯函数到 utils@/components/voice/CloneModal默认导出不变src/test/components/voice/CloneModal.test.tsx路径兼容🚀 预览环境已部署
CI全绿,自动审批通过。
CI全绿,自动审批通过。
【阻塞级判定】
📊 审查概览
🔴 阻塞级问题(必须修复)
handleSubmit函数中依赖isProcessing状态(由phase派生)来控制提交,但状态更新是异步的。当用户快速双击“开始克隆”按钮时,canSubmit在两次点击时可能均为true,导致uploadAsset和createVoiceClone被并发调用两次,造成重复创建或资源浪费。handleSubmit函数入口处增加同步的守卫检查,例如使用if (isProcessing) return,或者引入一个isSubmittingRef来确保同一时间只能有一个提交流程在运行。💡 改进建议(不阻塞合并)
[apps/web/src/components/voice/CloneModal/index.tsx: 24] 默认名称计数器重置问题
cloneCounterRef被定义在组件内部,且 Modal 设置了destroyOnClose={true}。这意味着每次 Modal 关闭并重新打开时,组件会重新挂载,计数器重置为 1。用户每次打开弹窗看到的默认名称都是“我的声音 1”,体验不佳且可能导致重复命名。建议将计数器逻辑移至组件外部(如模块级变量)或使用时间戳/随机数生成唯一后缀。[apps/web/src/components/voice/CloneModal/index.tsx: 18] 辅助函数位置建议
getExtensionFromMime函数目前定义在index.tsx顶部。考虑到项目中已经存在utils.ts文件,建议将该纯函数移至utils.ts中,以保持index.tsx的简洁性和关注点分离。✅ 良好实践
isMountedRef有效防止了组件卸载后的状态更新,避免了内存泄漏和警告。useAudioRecorderHook 中使用isStartingRef防止了录音按钮的重复点击触发,逻辑严密。input的value重置,允许重复选择同一文件。🤖 由 AI 代码审查机器人自动生成 | 2026-07-30 02:42:31 | 模型:
🗑️ 预览环境已清理
PR #1186 已关闭或合并,对应的预览环境已被清理。