fix(voices): 配音库「配音素材」tab 补删除按钮 #1538

Merged
auto-approve-bot merged 2 commits from fix/voice-material-tab-delete-btn into develop 2026-08-29 15:11:01 +08:00
Owner

背景

配音库页面第三个 tab「配音素材」的卡片纯展示无删除入口,上传错误的素材无法清理。

改动

  • MaterialVoiceTab 卡片右上角 hover 显示 danger 删除按钮(DeleteOutlined,stopPropagation 防误触),对齐「我的克隆」tab 删除体验
  • 新增 useMaterialDelete hook:Modal.confirm 二次确认(确定删除配音素材「xx」吗?删除后不可恢复)→ deleteAsset,成功 toast「素材已删除」并 invalidate voice-materials + assets/voice 列表,失败 toast 报错
  • voices.css.vmat-card-actions / .vmat-card-action-btn 样式(对齐 voice-materials.css),.vmat-cardposition: relative
  • 只加删除不加编辑;预置音色、我的克隆 tab 不动;不改后端

验收

  • 配音素材 tab 悬停卡片出现删除按钮 → 确认框 → 卡片消失列表刷新
  • 删除中/失败有提示不卡死
  • 其他两个 tab 功能不受影响
## 背景 配音库页面第三个 tab「配音素材」的卡片纯展示无删除入口,上传错误的素材无法清理。 ## 改动 - `MaterialVoiceTab` 卡片右上角 hover 显示 danger 删除按钮(DeleteOutlined,stopPropagation 防误触),对齐「我的克隆」tab 删除体验 - 新增 `useMaterialDelete` hook:Modal.confirm 二次确认(确定删除配音素材「xx」吗?删除后不可恢复)→ `deleteAsset`,成功 toast「素材已删除」并 invalidate `voice-materials` + `assets/voice` 列表,失败 toast 报错 - `voices.css` 补 `.vmat-card-actions` / `.vmat-card-action-btn` 样式(对齐 voice-materials.css),`.vmat-card` 加 `position: relative` - 只加删除不加编辑;预置音色、我的克隆 tab 不动;不改后端 ## 验收 - 配音素材 tab 悬停卡片出现删除按钮 → 确认框 → 卡片消失列表刷新 - 删除中/失败有提示不卡死 - 其他两个 tab 功能不受影响
xiaoxia added 1 commit 2026-08-29 14:33:42 +08:00
fix(voices): 配音库配音素材tab补充删除按钮
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2m57s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 3m18s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 4m9s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 4m30s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m44s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 5m7s
AI Code Review / AI Code Review (pull_request) Failing after 5m9s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 7m25s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m42s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 4m5s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 3m8s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1m4s
1ed4bd9e0d
- MaterialVoiceTab 卡片 hover 显示 danger 删除按钮(stopPropagation 防误触)
- 新增 useMaterialDelete hook:Modal.confirm 二次确认 → deleteAsset
- 删除成功 toast 提示并 invalidate voice-materials / assets-voice 列表,失败 toast 报错
- voices.css 补 .vmat-card-actions 样式(对齐 voice-materials 页),.vmat-card 加 position:relative
- 预置音色、我的克隆 tab 不受影响

🚀 预览环境已部署

项目 详情
PR号 #1538
预览链接 https://pr-1538.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1538 | | 预览链接 | [https://pr-1538.preview.xiaoxiajianji.com](https://pr-1538.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
auto-approve-bot approved these changes 2026-08-29 14:50:31 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-08-29 14:50:31 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia added 1 commit 2026-08-29 14:54:48 +08:00
fix(voices): 修复素材删除按钮移动端不可见 + 补 aria-label
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3m39s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m46s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 3m48s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m54s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 5m33s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 6m37s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 8m17s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m59s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 3m1s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 10m8s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 3m33s
CI/CD Pipeline / CI Gate (pull_request) Successful in 32s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 2m58s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 3m41s
798c01ad5b
- @media (hover:none) 触摸屏设备常驻显示 .vmat-card-actions(移动端无 hover 伪类,按钮此前完全无法点击)
- 删除按钮补 aria-label="删除配音素材",屏幕阅读器可朗读用途
Collaborator

代码审查结果 - PR #1538

⚠️ 问题(3个需要修改)

  1. apps/web/src/pages/voices/hooks/useMaterialDelete.ts 第37行:冗余的查找逻辑与闭包陷阱风险

    • 问题描述handleMaterialDelete 接收的 asset 参数本身即为待删除对象,但代码却在传入的 materials 列表中再次执行 find 查找。这不仅逻辑冗余,还将 materials 列表加入了依赖项。当列表数据刷新时,handleMaterialDelete 引用会变更,导致子组件不必要的重渲染。更严重的是,如果 Modal.confirm 弹窗期间列表数据发生了变化(如其他操作刷新了列表),闭包中的 materials 可能已过期,导致 find 返回 undefined,从而静默取消删除操作。
    • 后果:可能导致删除功能偶发性失效,且存在性能隐患。
    • 修改建议:直接使用传入的 asset 对象,移除 materials 参数及其依赖,删除 find 判断逻辑。
  2. apps/web/src/pages/voices/hooks/useMaterialDelete.ts 第24-28行:删除素材未同步停止播放状态

    • 问题描述:删除成功后仅刷新了数据列表,但未处理播放器状态。如果用户删除了当前正在播放的素材,音频会继续播放,且播放器组件可能因找不到对应 DOM 节点或数据而报错,导致 UI 状态与实际播放不一致。
    • 后果:导致数据与 UI 状态不同步,可能引发运行时错误。
    • 修改建议:Hook 应支持传入 onSuccess 回调,或者在 VoiceLibrary.tsx 中调用删除逻辑前先判断并停止播放。
  3. apps/web/src/pages/voices/VoiceLibrary.tsx 第74行:不安全的类型断言

    • 问题描述:代码使用了 materials as AssetItem[] 进行强制类型转换。如果 useVoicesData 返回的数据结构与 AssetItem 不完全一致(例如缺少字段或类型不匹配),这种断言会掩盖类型错误,导致运行时访问属性时出现 undefined 错误。
    • 后果:可能引发运行时崩溃。
    • 修改建议:确保 useVoicesData 返回正确的类型,或使用运行时校验/类型守卫进行安全转换。

💡 建议(1个可选)

  1. apps/web/src/pages/voices/components/MaterialVoiceTab.tsx 第51-56行:移动端点击区域优化
    • 建议描述:删除按钮在 CSS 中定义为 28px * 28px。虽然 CSS 中针对触摸屏做了常驻显示处理,但 28px 的点击区域对于手指触摸来说偏小(建议至少 44x44px)。建议增加按钮的 padding 或使用伪元素扩大点击热区,提升移动端体验。

格式检查通过 | 逻辑审查需修改 | ⚠️ 建议关注性能


🤖 由 AI 代码审查机器人自动生成 | 2026-08-29 07:03:42 | 模型:

## 代码审查结果 - PR #1538 ### ⚠️ 问题(3个需要修改) 1. **apps/web/src/pages/voices/hooks/useMaterialDelete.ts 第37行**:冗余的查找逻辑与闭包陷阱风险 - **问题描述**:`handleMaterialDelete` 接收的 `asset` 参数本身即为待删除对象,但代码却在传入的 `materials` 列表中再次执行 `find` 查找。这不仅逻辑冗余,还将 `materials` 列表加入了依赖项。当列表数据刷新时,`handleMaterialDelete` 引用会变更,导致子组件不必要的重渲染。更严重的是,如果 `Modal.confirm` 弹窗期间列表数据发生了变化(如其他操作刷新了列表),闭包中的 `materials` 可能已过期,导致 `find` 返回 `undefined`,从而静默取消删除操作。 - **后果**:可能导致删除功能偶发性失效,且存在性能隐患。 - **修改建议**:直接使用传入的 `asset` 对象,移除 `materials` 参数及其依赖,删除 `find` 判断逻辑。 2. **apps/web/src/pages/voices/hooks/useMaterialDelete.ts 第24-28行**:删除素材未同步停止播放状态 - **问题描述**:删除成功后仅刷新了数据列表,但未处理播放器状态。如果用户删除了当前正在播放的素材,音频会继续播放,且播放器组件可能因找不到对应 DOM 节点或数据而报错,导致 UI 状态与实际播放不一致。 - **后果**:导致数据与 UI 状态不同步,可能引发运行时错误。 - **修改建议**:Hook 应支持传入 `onSuccess` 回调,或者在 `VoiceLibrary.tsx` 中调用删除逻辑前先判断并停止播放。 3. **apps/web/src/pages/voices/VoiceLibrary.tsx 第74行**:不安全的类型断言 - **问题描述**:代码使用了 `materials as AssetItem[]` 进行强制类型转换。如果 `useVoicesData` 返回的数据结构与 `AssetItem` 不完全一致(例如缺少字段或类型不匹配),这种断言会掩盖类型错误,导致运行时访问属性时出现 `undefined` 错误。 - **后果**:可能引发运行时崩溃。 - **修改建议**:确保 `useVoicesData` 返回正确的类型,或使用运行时校验/类型守卫进行安全转换。 ### 💡 建议(1个可选) 1. **apps/web/src/pages/voices/components/MaterialVoiceTab.tsx 第51-56行**:移动端点击区域优化 - **建议描述**:删除按钮在 CSS 中定义为 `28px * 28px`。虽然 CSS 中针对触摸屏做了常驻显示处理,但 28px 的点击区域对于手指触摸来说偏小(建议至少 44x44px)。建议增加按钮的 `padding` 或使用伪元素扩大点击热区,提升移动端体验。 --- ❌ 格式检查通过 | ❌ 逻辑审查需修改 | ⚠️ 建议关注性能 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-29 07:03:42 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot merged commit ece9ac48a8 into develop 2026-08-29 15:11:01 +08:00
auto-approve-bot deleted branch fix/voice-material-tab-delete-btn 2026-08-29 15:11:01 +08:00

🗑️ 预览环境已清理

PR #1538 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1538 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.