2026-07-13 09:12:11 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-613
|
|
|
|
|
|
title: AI工场照片池与失败生图任务分层展示
|
|
|
|
|
|
phase: 7
|
|
|
|
|
|
deps: [T-594, T-607, T-612]
|
2026-07-13 09:54:08 +08:00
|
|
|
|
status: DONE
|
2026-07-13 09:12:11 +08:00
|
|
|
|
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 既有口径不变。
|
2026-07-13 09:54:08 +08:00
|
|
|
|
- 状态卡应明确说明恢复方式:已保存远端 `task_id` 且恢复语义为可恢复的 job 显示“可继续查询”;已收到终态上游失败、过期,或尚未取得 `task_id` 即被用户停止的 job 显示“需要重新生成,可能再次扣点”。用户在已保存 `task_id` 后停止的 job 保留“可继续查询”,因为恢复只会查询既有远端任务,不会重新提交。
|
2026-07-13 09:12:11 +08:00
|
|
|
|
- 本任务不把“重新生成”伪装成无成本重试,也不在卡片点击时自动创建新 job。用户需要重新生成时,仍从现有生成设置显式发起新一轮。
|
|
|
|
|
|
- 如现有持久化字段不足以可靠区分“可继续查询”和“必须重新生成”,先补充最小、可迁移的 job 恢复语义字段或由服务层提供明确分类;不得仅靠匹配错误文案字符串猜测。
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 状态变化与项目隔离
|
|
|
|
|
|
|
|
|
|
|
|
- job 成功下载、保存并产出可用资产后,任务状态卡从「生成任务」区移除,对应真实图片进入照片池。
|
|
|
|
|
|
- job 失败、取消、过期后保留状态记录,直到用户成功恢复、显式重新生成或后续单独的清理策略处理;不得为了视觉整洁静默删除失败证据。
|
|
|
|
|
|
- 项目切换、T-612 的生成运行态、T-608 的原图下载队列和 T-604 的线程清理不能让旧项目状态卡污染当前项目。
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 文档同步
|
|
|
|
|
|
|
|
|
|
|
|
更新 `docs/routes.md`,明确“照片池 = 可用图片资产”,“生成任务 = 进行中/失败任务状态”,并写明继续查询不重复提交、不重复扣点,重新生成可能产生新的计费。
|
|
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
|
|
|
|
|
|
|
|
|
|
|
- 失败生成后,照片池不再出现灰色单字「败」占位图;照片池中只能看到可用本地图片。
|
|
|
|
|
|
- 独立「生成任务」区显示“生成失败”及脱敏后的中文原因摘要,失败卡使用危险语义色且不可选源图、不可拖入终选。
|
|
|
|
|
|
- 已提交、生成中、取消、过期等未产出图片任务也在状态区以完整中文状态显示;没有此类任务时状态区隐藏。
|
|
|
|
|
|
- 任务成功并保存图片后,状态卡消失,图片进入照片池;失败记录不会悄悄丢失。
|
|
|
|
|
|
- 对保存了 `task_id` 的可恢复任务,用户能明确知道可用「继续查询任务」恢复,且恢复不会重复 submit 或扣点。
|
2026-07-13 09:54:08 +08:00
|
|
|
|
- 对终态失败/过期,以及未取得 `task_id` 即停止的任务,界面明确提示需重新生成且可能再次扣点;不把它错误标记为可恢复。
|
2026-07-13 09:12:11 +08:00
|
|
|
|
- 原因摘要、日志和 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 09:54:08 +08:00
|
|
|
|
- 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 生图人工验收。
|