fix(smart-match): 过滤前置+余量/高频全过滤时空结果回退保留素材 #1590
Reference in New Issue
Block a user
Delete Branch "fix/smart-match-empty-results"
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?
问题
前端调用 POST /assets/smart-match 返回空 items,前端回退全选。
根因
路由旧实现顺序错误:先 smart_select_assets(limit=N) 截取 Top-N,再对这 N 条做 usable/高频过滤,过滤后不回补:
修复
测试
🚀 预览环境已部署
【阻塞级判定】
📊 审查概览
🔴 阻塞级问题(必须修复)
[apps/api/api/routes/assets.py: 653-658] 逻辑错误:响应构建时丢失计算字段
compute_asset_availability的调用移到了前置过滤阶段(第593行),计算结果avail仅用于判断是否过滤,未保存。在后续构建SmartMatchItem时(第653-658行),直接尝试从smart_select_assets返回的对象r中读取usable和availability字段。由于smart_select_assets未在此PR中修改,且通常返回原始Asset对象或仅包含评分的包装对象,这些对象上不存在动态计算的usable/availability属性。这将导致AttributeError或字段为空,使得前端无法获取素材余量信息,且测试用例assert all(item.usable ...)将失败。usable/availability数据传递到最终响应构建环节。建议在过滤循环中将计算结果附加到 Asset 对象上(如a._computed_avail = avail),或在最终循环中重新调用compute_asset_availability(需权衡性能),或者修改smart_select_assets以支持携带这些元数据。[apps/api/api/routes/assets.py: 653] 逻辑错误:对象属性访问不匹配
r.asset.id,表明smart_select_assets返回的是一个包装对象(Wrapper),其中包含.asset属性指向原始素材。新代码改为直接访问r.id、r.name等,而smart_select_assets函数并未在此PR中修改。这意味着调用方式与函数返回值的结构不兼容,极大概率会导致运行时出现AttributeError: 'ScoredAsset' object has no attribute 'id'。smart_select_assets的返回值结构。如果它返回包装对象,应保持使用r.asset.id;如果它返回原始对象,则需确认为何旧代码使用了r.asset.id。在未修改smart_select_assets实现的前提下,恢复为r.asset.id访问方式更为安全。💡 改进建议(不阻塞合并)
无
✅ 良好实践
test_smart_match_fallback.py详细覆盖了各种边界情况(全耗尽、部分耗尽、高频回退等),能有效验证回退逻辑的正确性。🤖 由 AI 代码审查机器人自动生成 | 2026-08-31 17:06:17 | 模型:
🗑️ 预览环境已清理
PR #1590 已关闭或合并,对应的预览环境已被清理。