Files
cmshoppe/docs/tasks/T-613.md
T

7.4 KiB

id, title, phase, deps, status, created
id title phase deps status created
T-613 AI工场照片池与失败生图任务分层展示 7
T-594
T-607
T-612
TODO 2026-07-13

问题 / 背景

当前 ImageStudioTab._fill_pool_grid() 将可用图片资产与 pending、submitted、running、failed、expired、cancelled 的生图 job 一并放进「照片池」网格。失败 job 使用 _job_icon("failed") 生成中间写着「败」的占位缩略图。

这能避免失败任务悄悄消失,并保留 cmhub task_id 供 T-594 的“继续查询任务”恢复,防止下载失败时重新 submit 或重复扣点。但它把“可选图片”和“不可用任务记录”混为同一类卡片:

  • 运营会把照片池理解为可选择、可拖入终选的图片集合,却看到没有实际图片的「败」卡;
  • 单个「败」字无法解释是上游生成失败、轮询超时、结果下载失败、本地保存失败、过期还是用户停止;
  • 卡片没有明确告诉用户该任务是否可以继续查询,还是必须重新生成并可能再次扣点;
  • 失败卡当前的视觉主色与禁用态/空白占位接近,警示性不足。

方案

1. 照片池只展示可用图片资产

「照片池」只保留本地文件存在且可解码使用的 original、generated_main、generated_detail 资产。照片池内的卡片仍支持选源图、预览、拖入主图/详情图终选和已有右键操作。

不再把 job 状态卡插入照片池,因此失败、生成中、已提交、取消和过期任务不能被误认为一张候选图片,也不能拖拽或加入终选。

2. 新增独立“生成任务”状态区

在照片池附近增加紧凑的「生成任务」状态区,仅展示尚未产出可用图片的 job:pending、submitted、running、failed、expired、cancelled。没有此类任务时该区隐藏,不占用照片池空间。

  • 每张状态卡显示完整中文状态,例如「等待提交」「已提交」「生成中」「生成失败」「任务过期」「已停止」;不得只显示单个「败」「过」「停」字符。
  • failed / expired 使用明确的危险语义色和失败图标;pending / submitted / running 使用中性或进行中语义色;cancelled 使用中性停用色。不得把失败任务渲染成可用图片、普通空白或无含义灰色占位。
  • 卡片显示经 diagnostics.redact_log_text() 脱敏、截断后的中文原因摘要;例如「下载图片失败,可继续查询」「上游生成失败,需要重新生成」。不得显示 API 路径、远程图片 URL、密钥、Cookie、完整堆栈或英文技术异常。
  • 卡片保留已有的扣点、余额、call_id 等运营可理解的计费信息;没有该字段时不显示占位技术文本。
  • 照片池标题或状态区标题显示简短汇总,例如「可用图片 8 张 · 未完成/异常任务 1 个」,方便用户知道为什么少了一张候选图。

3. 恢复动作必须符合计费语义

  • 继续保留项目级「继续查询任务」入口。对于已保存 task_id 的 job,继续查询只能 poll/download 既有任务,不能再次 submit、不能重复扣点;T-594 既有口径不变。
  • 状态卡应明确说明恢复方式:可恢复 job 显示“可继续查询”;已收到终态上游失败、过期或用户停止的 job 显示“需要重新生成,可能再次扣点”。
  • 本任务不把“重新生成”伪装成无成本重试,也不在卡片点击时自动创建新 job。用户需要重新生成时,仍从现有生成设置显式发起新一轮。
  • 如现有持久化字段不足以可靠区分“可继续查询”和“必须重新生成”,先补充最小、可迁移的 job 恢复语义字段或由服务层提供明确分类;不得仅靠匹配错误文案字符串猜测。

4. 状态变化与项目隔离

  • job 成功下载、保存并产出可用资产后,任务状态卡从「生成任务」区移除,对应真实图片进入照片池。
  • job 失败、取消、过期后保留状态记录,直到用户成功恢复、显式重新生成或后续单独的清理策略处理;不得为了视觉整洁静默删除失败证据。
  • 项目切换、T-612 的生成运行态、T-608 的原图下载队列和 T-604 的线程清理不能让旧项目状态卡污染当前项目。

5. 文档同步

更新 docs/routes.md,明确“照片池 = 可用图片资产”,“生成任务 = 进行中/失败任务状态”,并写明继续查询不重复提交、不重复扣点,重新生成可能产生新的计费。

验收要点

  • 失败生成后,照片池不再出现灰色单字「败」占位图;照片池中只能看到可用本地图片。
  • 独立「生成任务」区显示“生成失败”及脱敏后的中文原因摘要,失败卡使用危险语义色且不可选源图、不可拖入终选。
  • 已提交、生成中、取消、过期等未产出图片任务也在状态区以完整中文状态显示;没有此类任务时状态区隐藏。
  • 任务成功并保存图片后,状态卡消失,图片进入照片池;失败记录不会悄悄丢失。
  • 对保存了 task_id 的可恢复任务,用户能明确知道可用「继续查询任务」恢复,且恢复不会重复 submit 或扣点。
  • 对终态失败/过期/停止任务,界面明确提示需重新生成且可能再次扣点;不把它错误标记为可恢复。
  • 原因摘要、日志和 tooltip 不泄露 cmhub URL、接口路径、密钥、Cookie、完整堆栈或英文技术错误。
  • 不影响 T-612 的生图运行态分级、T-608 的原图下载队列、T-594 的重启续查和计费保护、终选拖拽以及导出。

测试要求

更新或新增:

  • tests/test_gui.py
    • 断言照片池只包含可用资产;failed / submitted / running 等 job 不再以照片池图片项出现。
    • 覆盖生成任务区的空态隐藏、进行中、失败、过期、停止和成功转入照片池。
    • 覆盖失败卡完整中文状态、危险语义色、脱敏原因摘要、不可拖拽/不可加入终选和计费信息显示。
    • 覆盖项目切换后状态卡与照片池不串项目。
  • tests/test_image_studio_generation.py / tests/test_image_studio.py
    • 覆盖可恢复与不可恢复任务的明确分类;可恢复路径只 poll/download,不重新 submit 或扣点。
    • 如新增恢复语义字段,覆盖 schema 初始化、迁移、旧 job 默认兼容和状态转换。

验证命令:

python -m ruff check app tests main.py
py -3.10 -m compileall app main.py
py -3.10 -m unittest discover -s tests
git diff --check

人工验收:模拟一轮含成功、下载失败、上游失败、停止和生成中的任务,确认运营能清楚区分“已有可用图片”“可继续查询”“需要重新生成”,且不会把失败任务拖入终选。

边界(不改什么)

  • 不新增本地图片导入、图片编辑、自动上传蝦皮或终选规则。
  • 不改变 cmhub 的 submit/poll/download 接口、超时、并发、点数价格、余额或退点契约。
  • 不实现点击失败卡即自动重新生成;新的生成必须通过既有显式生成操作启动。
  • 不通过解析自然语言错误字符串判断恢复方式;若需区分,使用服务层明确状态或可迁移字段。
  • 不改①至⑤模块、Chrome/CDP、账号登录、数据库中无关表或历史图片物理清理策略。

执行记录

(完成后记录实现、验证命令与人工验收结果。)