2026-07-13 15:10:40 +08:00
|
|
|
|
---
|
|
|
|
|
|
id: T-621
|
|
|
|
|
|
title: ②只生成封面支持无新标题任务并保持图文结果独立
|
|
|
|
|
|
phase: 7
|
|
|
|
|
|
deps: [T-533, T-554, T-576]
|
2026-07-13 15:22:15 +08:00
|
|
|
|
status: DONE
|
2026-07-13 15:10:40 +08:00
|
|
|
|
created: 2026-07-13
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 问题 / 背景
|
|
|
|
|
|
|
|
|
|
|
|
②「AI生成」选择“只生成封面”时,当前实现仍要求任务已有 `new_title`。当用户选中一个已经完成采集、但全部没有新标题的批次后点击“开始生成”,GUI提示:`当前筛选结果没有可生成封面的任务,请先生成标题。`
|
|
|
|
|
|
|
|
|
|
|
|
这不是批次筛选或cmhub异常,而是T-576旧口径的主动限制:
|
|
|
|
|
|
|
|
|
|
|
|
- `ai.generation_needs(..., generate_mode="cover")` 只有在 `new_title` 非空时才把缺封面的任务判为可生成;
|
|
|
|
|
|
- `GenerateTab.start_generate()` 过滤后得到空任务列表,直接显示“请先生成标题”;
|
|
|
|
|
|
- 封面prompt上下文目前把 `new_title` 作为 `{新标题}` 的值;
|
|
|
|
|
|
- 封面成功统一调用 `db.set_generated(task_id, new_title, new_cover_path)`,同时写标题和封面,尚未提供“只写封面、保持标题为空”的AI成功写库语义;
|
|
|
|
|
|
- ②表格图片状态在没有 `new_title` 时显示“未开始”,与真正独立生成封面的目标不一致。
|
|
|
|
|
|
|
|
|
|
|
|
用户已经在“生成内容”下拉中明确选择“只生成封面”,本轮不应再强制产生标题模型费用。新产品口径调整为:**只生成封面可以处理没有新标题、但已经采集到旧标题的任务;旧标题只作为封面生成的语义参考,不得写入或伪装成新标题。**
|
|
|
|
|
|
|
|
|
|
|
|
## 方案
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 调整封面生成资格
|
|
|
|
|
|
|
|
|
|
|
|
- `app/ai.py` 的 `generation_needs()` / `is_generatable_task()`:
|
|
|
|
|
|
- `generate_mode=cover` 时,只要任务处于可生成阶段、尚无 `new_cover_path`,并且存在可用标题上下文,即可进入本轮;
|
|
|
|
|
|
- 标题上下文优先级:非空 `new_title` → 非空 `old_title`;
|
|
|
|
|
|
- `new_title` 与 `old_title` 都为空时仍不可生图,避免向模型提交缺少商品语义的空prompt;
|
|
|
|
|
|
- `title`、`title_cover` 两种模式保持现有增量逻辑,`title_cover` 仍先补新标题再生成封面。
|
|
|
|
|
|
- 可提取纯helper(例如 `cover_title_context(task)`),让资格判断、prompt预览、批量生成使用同一套优先级,避免GUI预览与实际请求不一致。
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 封面prompt使用有效标题,但不伪造新标题
|
|
|
|
|
|
|
|
|
|
|
|
- `generate_mode=cover` 且无 `new_title` 时,渲染封面prompt的 `{新标题}` 使用 `old_title` 作为兼容回退;`{旧标题}` 仍保持原旧标题。
|
|
|
|
|
|
- 该回退只存在于本轮封面prompt上下文。不得把 `old_title` 回写到 `tasks.new_title`,不得让标题状态显示“已生成”。
|
|
|
|
|
|
- GUI“封面提示词预览”必须复用同一helper:在“只生成封面”模式且没有新标题时,预览结果应与实际cmhub请求一致。
|
|
|
|
|
|
- 用户日志增加简短中文说明,例如:`商品 xxx 没有新标题,本轮使用旧标题作为封面参考`;不输出完整prompt、接口路径或敏感字段。
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 增加只写封面的AI成功写库语义
|
|
|
|
|
|
|
|
|
|
|
|
- 在 `app/db.py` 增加职责明确的成功写库helper(名称可按现有风格确定,例如 `set_generated_cover()`):
|
|
|
|
|
|
- 只更新 `new_cover_path`;
|
|
|
|
|
|
- 保留原 `new_title`,包括继续保持 `NULL`;
|
|
|
|
|
|
- 设置 `stage=generated`、`status=success`,清除本轮生成错误;
|
|
|
|
|
|
- 按现有AI成功口径更新 `generate_attempts`、`generated_at`、`updated_at`;
|
|
|
|
|
|
- 不修改 `committed`、更新尝试次数或重置计数。
|
|
|
|
|
|
- `generate_batch()` 的封面成功路径改用该helper或等价的组件级写库方式;有无新标题都不得因保存封面而覆盖标题字段。
|
|
|
|
|
|
- 现有 `db.set_generated()` 继续服务标题成功及图文完整结果,不做破坏性语义变更。
|
|
|
|
|
|
- 不修改SQLite schema。
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 修正②列表、筛选和提示
|
|
|
|
|
|
|
|
|
|
|
|
- ②选择“只生成封面”时:
|
|
|
|
|
|
- 已采集、有旧标题、无新标题、无新封面的记录应进入“待生成”筛选;
|
|
|
|
|
|
- 图片状态显示“待生成”,标题状态继续显示“待生成”;
|
|
|
|
|
|
- 生成成功后图片状态显示“已生成”,标题状态仍为“待生成”。
|
|
|
|
|
|
- `GenerateTaskTableModel` 需要知道当前精确 `generate_mode`,不能只依赖“是否包含封面”的布尔值来判断无新标题时的图片状态;保持兼容接口时也要确保模式切换会刷新状态列。
|
|
|
|
|
|
- 当前筛选确实没有封面缺口时,提示改为不强制先生成标题的准确文案,例如:`当前筛选结果没有可生成的封面;请确认商品已完成采集且尚未生成新封面。`
|
|
|
|
|
|
- `title_total=0`、`cover_total=N`,标题进度明确显示本轮不生成标题;不得因无新标题把任务从封面进度总数中排除。
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 保持后续图文流程独立
|
|
|
|
|
|
|
|
|
|
|
|
- 只生成封面成功后,用户可在③选择“只更新封面”,③只按 `new_cover_path` 校验并更新线上封面。
|
|
|
|
|
|
- 此时若③选择“只更新标题”或“更新标题和封面”,仍应因缺 `new_title` 在打开Chrome前阻断。
|
|
|
|
|
|
- 用户后续回到②选择“只生成标题”或“生成标题和封面”时:
|
|
|
|
|
|
- 只补缺失的新标题;
|
|
|
|
|
|
- 保留已经生成的新封面,不重复生图、不重复扣图片点;
|
|
|
|
|
|
- 新标题成功后标题状态变为“已生成”。
|
|
|
|
|
|
- Excel回写、封面画廊、封面重置与候选图归档继续允许“有新封面、无新标题”的组件独立状态。
|
|
|
|
|
|
|
|
|
|
|
|
## 验收要点
|
|
|
|
|
|
|
|
|
|
|
|
- 已采集且有旧标题、没有新标题和新封面的整批任务,在②选择“只生成封面”后可以直接开始生图。
|
|
|
|
|
|
- 本轮不调用标题生成接口,标题点数不增加;封面请求使用 `new_title or old_title` 作为标题语义上下文。
|
|
|
|
|
|
- 封面生成成功后,SQLite中 `new_cover_path` 有值、`new_title` 仍为 `NULL`/空;不得把旧标题写成新标题。
|
|
|
|
|
|
- ②标题状态仍为“待生成”,图片状态为“已生成”;程序重启和刷新后状态保持一致。
|
|
|
|
|
|
- 无新标题但有旧标题的任务能进入“待生成”筛选;新旧标题都为空的任务不进入,并显示准确中文提示。
|
|
|
|
|
|
- 封面prompt预览与实际请求使用相同回退规则。
|
|
|
|
|
|
- 之后选择“只生成标题”只补标题并保留现有封面,不重复提交生图任务。
|
|
|
|
|
|
- ③“只更新封面”可使用该结果;③“只更新标题/更新标题和封面”继续阻断缺标题任务。
|
|
|
|
|
|
- 已有新标题的“只生成封面”和“生成标题和封面”现有增量流程不回归。
|
|
|
|
|
|
|
|
|
|
|
|
## 测试要求
|
|
|
|
|
|
|
|
|
|
|
|
- `tests/test_ai.py`:覆盖无新标题但有旧标题时 `cover` 资格为真、无任何标题时为假、标题上下文优先级,以及图文模式原逻辑不变。
|
|
|
|
|
|
- `tests/test_db.py`:覆盖组件级封面成功只更新封面、保留空/已有新标题,并正确更新成功状态和时间/尝试字段。
|
|
|
|
|
|
- `tests/test_gui.py`:覆盖整批无新标题时可以启动只生成封面、prompt预览回退、标题/图片状态、待生成筛选、进度总数、用户日志及后续只补标题保留封面。
|
|
|
|
|
|
- 覆盖③三种更新模式对“有封面、无标题”任务的前置校验回归。
|
|
|
|
|
|
- 运行:
|
|
|
|
|
|
- `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`
|
|
|
|
|
|
|
|
|
|
|
|
## 文档同步
|
|
|
|
|
|
|
|
|
|
|
|
- 更新 `docs/02-requirements.md`:移除“只生成封面要求任务已有新标题”的旧口径。
|
|
|
|
|
|
- 更新 `docs/04-architecture.md`、`docs/api.md`、`docs/routes.md`:记录封面标题上下文回退、组件级写库与“有封面、无新标题”的合法状态。
|
|
|
|
|
|
- T-576保持DONE作为历史决策;本任务在其上明确覆盖旧限制,不回写历史任务结论。
|
|
|
|
|
|
|
|
|
|
|
|
## 边界(不改什么)
|
|
|
|
|
|
|
|
|
|
|
|
- 不修改cmhub/direct HTTP协议、生图submit/poll/download、并发、重试、超时、计费和图片保存格式。
|
|
|
|
|
|
- 不修改SQLite schema、Excel列结构、Shopee/CDP选择器、账号登录或Chrome前台策略。
|
|
|
|
|
|
- 不自动生成标题,不把旧标题复制到 `new_title`,不自动切换用户选择的生成模式。
|
|
|
|
|
|
- 不放宽未采集任务;没有旧标题且没有新标题时不提交生图。
|
|
|
|
|
|
- 不改变③真实更新确认和高风险边界。
|
|
|
|
|
|
|
|
|
|
|
|
## 执行记录
|
|
|
|
|
|
|
2026-07-13 15:22:15 +08:00
|
|
|
|
- 2026-07-13:`app/ai.py` 新增统一的封面标题上下文,`cover` 模式按 `new_title` 优先、`old_title` 回退判断资格并渲染prompt;`title_cover` 仍须先生成新标题,不用旧标题绕过生文失败。
|
|
|
|
|
|
- 2026-07-13:`app/db.py` 新增组件级 `set_generated_cover()`,封面成功只更新 `new_cover_path`,保留 `new_title`(包括NULL),并按AI成功口径更新阶段、状态、尝试次数和时间。
|
|
|
|
|
|
- 2026-07-13:②表格改为持有精确 `generate_mode`;只生成封面时,无新标题但有旧标题的任务可进入待生成筛选,封面成功后保持“标题待生成 / 图片已生成”。封面prompt预览复用同一回退规则,运行日志明确提示使用旧标题作为封面参考。
|
|
|
|
|
|
- 2026-07-13:补充AI、DB、GUI和③更新模式测试,覆盖无新标题独立生图、旧标题不回写、后补标题保留封面、状态/筛选/预览/进度,以及只有“只更新封面”放行该组件结果;同步需求、架构、API和界面流程文档。
|
|
|
|
|
|
- 2026-07-13:主工作区GUI全量测试仅有2项既有默认提示词重命名断言失败,与本任务无关;在只包含T-621差异的干净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`(429项通过)、`git diff --check`,结果全部通过。
|