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

105 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-613
title: AI工场照片池与失败生图任务分层展示
phase: 7
deps: [T-594, T-607, T-612]
status: DONE
created: 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 既有口径不变。
- 状态卡应明确说明恢复方式:已保存远端 `task_id` 且恢复语义为可恢复的 job 显示“可继续查询”;已收到终态上游失败、过期,或尚未取得 `task_id` 即被用户停止的 job 显示“需要重新生成,可能再次扣点”。用户在已保存 `task_id` 后停止的 job 保留“可继续查询”,因为恢复只会查询既有远端任务,不会重新提交。
- 本任务不把“重新生成”伪装成无成本重试,也不在卡片点击时自动创建新 job。用户需要重新生成时,仍从现有生成设置显式发起新一轮。
- 如现有持久化字段不足以可靠区分“可继续查询”和“必须重新生成”,先补充最小、可迁移的 job 恢复语义字段或由服务层提供明确分类;不得仅靠匹配错误文案字符串猜测。
### 4. 状态变化与项目隔离
- job 成功下载、保存并产出可用资产后,任务状态卡从「生成任务」区移除,对应真实图片进入照片池。
- job 失败、取消、过期后保留状态记录,直到用户成功恢复、显式重新生成或后续单独的清理策略处理;不得为了视觉整洁静默删除失败证据。
- 项目切换、T-612 的生成运行态、T-608 的原图下载队列和 T-604 的线程清理不能让旧项目状态卡污染当前项目。
### 5. 文档同步
更新 `docs/routes.md`,明确“照片池 = 可用图片资产”,“生成任务 = 进行中/失败任务状态”,并写明继续查询不重复提交、不重复扣点,重新生成可能产生新的计费。
## 验收要点
- 失败生成后,照片池不再出现灰色单字「败」占位图;照片池中只能看到可用本地图片。
- 独立「生成任务」区显示“生成失败”及脱敏后的中文原因摘要,失败卡使用危险语义色且不可选源图、不可拖入终选。
- 已提交、生成中、取消、过期等未产出图片任务也在状态区以完整中文状态显示;没有此类任务时状态区隐藏。
- 任务成功并保存图片后,状态卡消失,图片进入照片池;失败记录不会悄悄丢失。
- 对保存了 `task_id` 的可恢复任务,用户能明确知道可用「继续查询任务」恢复,且恢复不会重复 submit 或扣点。
- 对终态失败/过期,以及未取得 `task_id` 即停止的任务,界面明确提示需重新生成且可能再次扣点;不把它错误标记为可恢复。
- 原因摘要、日志和 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 默认兼容和状态转换。
验证命令:
```bash
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、账号登录、数据库中无关表或历史图片物理清理策略。
## 执行记录
- 2026-07-13:照片池改为仅显示本地可用资产;新增独立「生成任务」区,展示等待提交、已提交、生成中、生成失败、任务过期和已停止任务,并以状态语义色、中文状态、脱敏原因、恢复方式和已有计费信息说明任务情况。任务卡不可作为源图或拖入终选;成功产出可用图片后自动从任务区移入照片池。
- 2026-07-13:`image_studio_jobs` 增加可迁移的 `recovery_action` 字段。提交成功后标记为可继续查询;下载/保存中断保留继续查询资格;远端终态失败、过期及未取得远端任务即停止时标记为需要重新生成;成功任务标记为无需恢复。`继续查询任务` 仅处理可恢复的已有 `task_id`,不会重复提交或扣点。
- 2026-07-13:补充照片池/任务区隔离、项目切换、成功转入照片池、中文状态与危险语义色、原因脱敏、恢复分类、旧 SQLite 迁移和续查不重复提交的自动化测试。
- 验证:在干净 worktree 运行 `python -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`py -3.10 -m unittest discover -s tests`(391 项通过)和 `git diff --check`,均通过。未做真实 cmhub 生图人工验收。