8.1 KiB
8.1 KiB
id, title, phase, deps, status, created
| id | title | phase | deps | status | created | |||
|---|---|---|---|---|---|---|---|---|
| T-621 | ②只生成封面支持无新标题任务并保持图文结果独立 | 7 |
|
TODO | 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.pypy -3.10 -m compileall app main.pypy -3.10 -m unittest discover -s testsgit 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,不自动切换用户选择的生成模式。 - 不放宽未采集任务;没有旧标题且没有新标题时不提交生图。
- 不改变③真实更新确认和高风险边界。
执行记录
(完成后记录实现、验证命令与结果。)