feat(assets): 素材余量角标 + Step2 过滤已用尽素材 #1548

Merged
auto-approve-bot merged 1 commits from feat/asset-usage-badge-filter into develop 2026-08-30 01:26:00 +08:00
Owner

背景

后端正在上线片段重复率控制机制(任意两条成片画面重复率 ≤15%、单区间复用上限 3 次)。素材被反复切到彻底用尽后,不应再出现在生成流程的可选列表里。设计原则:素材库是管理视角,余量状态在素材库看;Step2 是选用视角,不能用的素材不显示、选不到。

改动

1. 素材库卡片余量角标(AssetCard)

视频素材卡片 meta 区(StatusPill/时长同一行)增加余量角标:

  • usable === false:红色实心「已用尽」
  • used_ratio >= 0.85:红色软底「即将用尽」
  • used_ratio >= 0.5:橙色软底「已用 xx%」
  • < 0.5 或字段缺失:不显示
  • 角标纯展示,不影响播放/选择/删除/诊断;已用尽素材在素材库正常显示,不置灰不隐藏

2. Step2 手动模式过滤

  • 素材列表过滤掉 usable === false,已用尽素材不出现、无法勾选
  • 库内有素材但全部用尽时,空状态文案为「暂无可选素材(素材可能已用尽,请先上传新素材)」,区别于空库的「暂无素材,请先在视频库中上传」

3. Step2 智能匹配兜底过滤

  • SmartMatch 结果列表、全选/回退逻辑、自动触发判断均过滤已用尽素材(后端推荐接口也会排除,前端这层兜底)
  • 全部用尽时 toast 提示「素材可能已用尽,请先上传新素材」

4. 降级与约束

  • 后端字段未上线前(usable/used_ratio 缺失):所有素材按可用处理、不显示角标、不过滤,不报错/不 toast/不打 error 日志,现有流程零影响
  • 共用工具 isAssetUsable(api/assets/usage.ts)+ 角标计算 getUsageBadge(pages/assets/types.ts)
  • 补 10 条单测(降级/阈值/非视频/优先级),全量 604 条测试通过
  • 不动素材选择、from-assets 调用、草稿保存逻辑;无新依赖

验收

  • 素材库视频卡片按 used_ratio/usable 显示对应角标,非视频/无字段不显示
  • Step2 手动模式不显示已用尽素材;全部用尽时展示区分文案
  • Step2 智能匹配结果/全选不含已用尽素材
  • 后端字段未上线时行为与当前完全一致
  • CI 全绿(tsc / ESLint / vitest)
## 背景 后端正在上线片段重复率控制机制(任意两条成片画面重复率 ≤15%、单区间复用上限 3 次)。素材被反复切到彻底用尽后,不应再出现在生成流程的可选列表里。设计原则:**素材库是管理视角,余量状态在素材库看;Step2 是选用视角,不能用的素材不显示、选不到。** ## 改动 ### 1. 素材库卡片余量角标(AssetCard) 视频素材卡片 meta 区(StatusPill/时长同一行)增加余量角标: - `usable === false`:红色实心「已用尽」 - `used_ratio >= 0.85`:红色软底「即将用尽」 - `used_ratio >= 0.5`:橙色软底「已用 xx%」 - `< 0.5` 或字段缺失:不显示 - 角标纯展示,不影响播放/选择/删除/诊断;已用尽素材在素材库正常显示,不置灰不隐藏 ### 2. Step2 手动模式过滤 - 素材列表过滤掉 `usable === false`,已用尽素材不出现、无法勾选 - 库内有素材但全部用尽时,空状态文案为「暂无可选素材(素材可能已用尽,请先上传新素材)」,区别于空库的「暂无素材,请先在视频库中上传」 ### 3. Step2 智能匹配兜底过滤 - SmartMatch 结果列表、全选/回退逻辑、自动触发判断均过滤已用尽素材(后端推荐接口也会排除,前端这层兜底) - 全部用尽时 toast 提示「素材可能已用尽,请先上传新素材」 ### 4. 降级与约束 - 后端字段未上线前(usable/used_ratio 缺失):所有素材按可用处理、不显示角标、不过滤,不报错/不 toast/不打 error 日志,现有流程零影响 - 共用工具 `isAssetUsable`(api/assets/usage.ts)+ 角标计算 `getUsageBadge`(pages/assets/types.ts) - 补 10 条单测(降级/阈值/非视频/优先级),全量 604 条测试通过 - 不动素材选择、from-assets 调用、草稿保存逻辑;无新依赖 ## 验收 - [ ] 素材库视频卡片按 used_ratio/usable 显示对应角标,非视频/无字段不显示 - [ ] Step2 手动模式不显示已用尽素材;全部用尽时展示区分文案 - [ ] Step2 智能匹配结果/全选不含已用尽素材 - [ ] 后端字段未上线时行为与当前完全一致 - [ ] CI 全绿(tsc / ESLint / vitest)
xiaoxia added 1 commit 2026-08-30 01:14:53 +08:00
feat(assets): 素材余量角标 + Step2 过滤已用尽素材
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
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 / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (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 / Check if frontend-only change (pull_request) Successful in 3m0s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m38s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 3m38s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 4m3s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m40s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 2m2s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m27s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m46s
AI Code Review / AI Code Review (pull_request) Successful in 6m55s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m0s
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 / CI Gate (pull_request) Successful in 25s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 4m29s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m42s
bf29d1e812
- 素材库视频卡片 meta 区增加余量角标:已用尽(红实心)/即将用尽(红)/已用xx%(橙)
- Step2 手动模式过滤 usable===false 的素材,全部用尽时空状态文案区分提示
- Step2 智能匹配兜底过滤已用尽素材(全选/回退/结果列表均不包含)
- 后端字段缺失时降级为全部可用、不显示角标,零影响
- 新增 isAssetUsable 共用工具与 getUsageBadge 角标计算,补 10 条单测

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1548 | | 预览链接 | [https://pr-1548.preview.xiaoxiajianji.com](https://pr-1548.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:否
  • 阻塞级问题数量:0 个

📊 审查概览

  • 整体评价:通过
  • 建议级问题数量:2 个

🔴 阻塞级问题(必须修复)

💡 改进建议(不阻塞合并)

  1. [apps/web/src/pages/generate/hooks/step2-materials/useSmartMatch.ts: 36] 智能匹配错误提示可能不够精确

    • 具体内容:在 useStep2Materials.ts 中,useSmartMatch 接收的 materials 参数已经被过滤为 selectableMaterials(仅包含可用素材)。因此,在 handleSmartMatch 函数中,当 usableItems.length === 0 时,materials.items.length 必然也为 0。这意味着三元运算符中的 "素材可能已用尽,请先上传新素材" 这条提示语在当前调用链下是死代码,永远不会触发。用户只会看到“当前视频库暂无素材”。
    • 修改建议:如果希望保留“素材已用尽”的提示,需要将原始的 materials(包含已用尽素材)传递给 useSmartMatch,并在 Hook 内部进行过滤;或者接受当前行为,删除不可达的分支代码以简化逻辑。
  2. [apps/web/src/pages/generate/hooks/step2-materials/useMaterialLibrary.ts: 38] selectableMaterialstotal 字段语义可能存在偏差

    • 具体内容:selectableMaterials 是通过过滤 materials.items 得到的,但其 total 字段直接沿用了 materials.total(即素材库的原始总数)。如果 UI 组件(如 ManualMaterialList)使用 total 来显示“共 X 条”或用于判断分页结束(例如 items.length < total),则会出现数据不一致(显示总数很大,但列表为空)或分页逻辑判断错误(误以为还有下一页)的情况。
    • 修改建议:确认 UI 组件如何使用 total 字段。如果用于展示“可选素材总数”,建议计算过滤后的实际总数;如果用于分页加载控制,需确保前端过滤不会干扰“加载更多”的触发条件。

良好实践

  1. 向后兼容性设计isAssetUsable 函数通过 asset.usable !== false 的判断,优雅地处理了后端字段未上线时的降级逻辑,保证了新旧代码的平滑过渡。
  2. 类型安全:新增的 AssetUsageLike 接口和 UsageBadge 类型定义清晰,单元测试覆盖了边界情况(如 nullundefined、阈值判断),增强了代码健壮性。
  3. 防御性编程:在 useSmartMatch 中,即使后端 API 返回了包含已用尽素材的数据,前端也进行了二次过滤(filter(isAssetUsable)),防止了无效数据进入选片流程。

🤖 由 AI 代码审查机器人自动生成 | 2026-08-29 17:21:49 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:否 - 阻塞级问题数量:0 个 ### 📊 审查概览 - 整体评价:通过 - 建议级问题数量:2 个 ### 🔴 阻塞级问题(必须修复) 无 ### 💡 改进建议(不阻塞合并) 1. **[apps/web/src/pages/generate/hooks/step2-materials/useSmartMatch.ts: 36] 智能匹配错误提示可能不够精确** - 具体内容:在 `useStep2Materials.ts` 中,`useSmartMatch` 接收的 `materials` 参数已经被过滤为 `selectableMaterials`(仅包含可用素材)。因此,在 `handleSmartMatch` 函数中,当 `usableItems.length === 0` 时,`materials.items.length` 必然也为 0。这意味着三元运算符中的 `"素材可能已用尽,请先上传新素材"` 这条提示语在当前调用链下是**死代码**,永远不会触发。用户只会看到“当前视频库暂无素材”。 - 修改建议:如果希望保留“素材已用尽”的提示,需要将原始的 `materials`(包含已用尽素材)传递给 `useSmartMatch`,并在 Hook 内部进行过滤;或者接受当前行为,删除不可达的分支代码以简化逻辑。 2. **[apps/web/src/pages/generate/hooks/step2-materials/useMaterialLibrary.ts: 38] `selectableMaterials` 的 `total` 字段语义可能存在偏差** - 具体内容:`selectableMaterials` 是通过过滤 `materials.items` 得到的,但其 `total` 字段直接沿用了 `materials.total`(即素材库的原始总数)。如果 UI 组件(如 `ManualMaterialList`)使用 `total` 来显示“共 X 条”或用于判断分页结束(例如 `items.length < total`),则会出现数据不一致(显示总数很大,但列表为空)或分页逻辑判断错误(误以为还有下一页)的情况。 - 修改建议:确认 UI 组件如何使用 `total` 字段。如果用于展示“可选素材总数”,建议计算过滤后的实际总数;如果用于分页加载控制,需确保前端过滤不会干扰“加载更多”的触发条件。 ### ✅ 良好实践 1. **向后兼容性设计**:`isAssetUsable` 函数通过 `asset.usable !== false` 的判断,优雅地处理了后端字段未上线时的降级逻辑,保证了新旧代码的平滑过渡。 2. **类型安全**:新增的 `AssetUsageLike` 接口和 `UsageBadge` 类型定义清晰,单元测试覆盖了边界情况(如 `null`、`undefined`、阈值判断),增强了代码健壮性。 3. **防御性编程**:在 `useSmartMatch` 中,即使后端 API 返回了包含已用尽素材的数据,前端也进行了二次过滤(`filter(isAssetUsable)`),防止了无效数据进入选片流程。 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-29 17:21:49 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-08-30 01:25:30 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-08-30 01:25:30 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot merged commit 652bbfe12b into develop 2026-08-30 01:26:00 +08:00
auto-approve-bot deleted branch feat/asset-usage-badge-filter 2026-08-30 01:26:01 +08:00

🗑️ 预览环境已清理

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

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

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