--- id: T-584 title: ②左侧提示词区 reorg:标题提示词加模板控件行 + 封面控件压一行 + 插入类按钮下移工具条 + 增高标题输入框 phase: 7 deps: [T-583] status: DONE created: 2026-07-10 --- ## 问题 / 背景 ②标题提示词区现无模板管理(只有 label + 输入框 + 「保存标题提示词」+「插入旧标题」);封面提示词区已有「下拉框/新建/保存/模板操作(另存为/重命名/删除)」但铺了多行。T-583 已提供标题模板数据层(`data/prompts/title/` + 通用 CRUD + 默认模板播种)。本任务做左侧 UI 重排,让标题拥有与封面对等的模板管理,并腾出纵向空间给标题输入框。 定案排布(已评审): - 模板控件放在 **label 下方单独一行**(不贴 label 同行——窄栏塞不下下拉+3按钮)。 - **插入类按钮**(标题「插入旧标题」T-549、封面「插入标题」、「预览」)移到**各自输入框下方的工具条**,与"模板管理"分离。 - 封面模板控件压到一行,省出的纵向空间给标题输入框增高。 ## 方案(改哪个文件、改成什么) ### `app/gui/tabs/generate.py` — 左侧布局重排 标题提示词区(新结构,自上而下): 1. label「标题提示词」 2. **模板控件行**(新增):`[标题模板下拉] [新建] [保存模板] [模板操作▾(另存为/重命名/删除)]`——镜像封面那套,控件用 `title_template_*` 命名,调 T-583 通用 CRUD(传 `title_templates_dir`)。 3. 标题输入框 `title_prompt_edit`(**增高**,吃掉封面压行省出的空间)。 4. **输入框下工具条**:`[插入旧标题] [保存标题提示词]`(`insert_old_title_button` 保留 T-549 行为;「保存标题提示词」= 存当前工作文本到 `title_prompt.txt`,与"保存模板"区分)。 封面提示词区(压缩): 1. label「封面提示词」 2. **模板控件行**(压到一行):`[封面模板下拉] [新建] [保存模板] [模板操作▾]`。 3. 封面输入框 `cover_prompt_edit`。 4. **输入框下工具条**:`[插入标题] [预览]`。 ### 构造参数 / 路径 - `GenerateTab.__init__()` 新增 `title_templates_dir=None`,与现有 `title_prompt_path`、`cover_prompts_dir` 一样支持测试传临时目录。 - 默认值来自 `appconfig.title_templates_dir(self.config)`;创建 `GenerateTab` 时调用 `prompts.ensure_default_prompts(self.title_prompt_path, self.cover_prompts_dir, self.title_templates_dir)`,避免写到真实默认 `data/`。 ### 标题模板控件行为(镜像封面 handler) - 下拉:`refresh_title_templates`/`load_selected_title_template`(选中→载入内容到 `title_prompt_edit`,记 `current_title_template`)。 - 新建 / 保存(存当前模板) / 模板操作(另存为/重命名/删除)——复用 T-583 通用 CRUD,逻辑镜像 `*_cover_template` 现有 handler。 - 「保存标题提示词」(工作文本→`title_prompt.txt`)与「保存模板」(当前模板→`data/prompts/title/<名称>.txt`)是两件事,二者都保留、语义在 tooltip 说清。 - 若当前没有选中标题模板时点击「保存模板」,走“另存为标题提示词模板”逻辑,不覆盖 `title_prompt.txt`。 ### 命名 / 一致性 - 新控件 `objectName` 用 `titleTemplateCombo`/`newTitleTemplateButton`/`saveTitleTemplateButton`/`titleTemplateActionsButton` + `saveTitleTemplateAsAction`/`renameTitleTemplateAction`/`deleteTitleTemplateAction`,供测试定位。 - 「模板操作」下拉/菜单结构与封面一致(另存为/重命名/删除)。 - 为降低用户误解,标题/封面的模板保存按钮文案统一用「保存模板」;如果担心窄栏宽度,至少给按钮加 tooltip「保存当前选中的模板」。`save_title_button` 继续显示「保存标题提示词」或等价中文,tooltip 说明它保存当前工作文本。 - `_set_generate_running(running)` 需要同步禁用新增标题模板控件和 action(下拉、新建、保存模板、模板操作、另存为/重命名/删除),避免生成运行中修改模板状态;插入/保存工作文本禁用口径沿用现有标题按钮。 ### 文档同步 - `docs/routes.md`/②UI 文档/线框图:登记标题模板控件行、插入类按钮下移、封面压行。 - 如果提交 `docs/ui/tab2-ai-generate-T584.svg` 线框图,必须确保它是本任务范围内的 UI 文档资产;否则不要把未确认的 SVG 混入代码提交。 ## 验收要点 - 标题提示词区出现模板控件行(下拉/新建/保存/模板操作),能新建/切换/保存/另存为/重命名/删除标题模板(走 T-583 CRUD),切换模板载入内容到标题输入框。 - 「插入旧标题」移到标题输入框下方工具条、T-549 插入 `{旧标题}` 行为不回归;封面「插入标题」「预览」移到封面输入框下方工具条、行为不回归。 - 封面模板控件压到一行;标题输入框可用高度较改动前增大(建议人工验收记录为主,offscreen 下不写脆弱像素断言;若写布局断言,只断控件结构/拉伸因子,不断绝对高度)。 - 「保存标题提示词」(工作文本)与「保存模板」并存、各自写 `title_prompt.txt` / 模板文件,不混淆。 - 生成仍取编辑框当前文本(不回归);标题/封面模板互不干扰。 - 生成运行中标题模板控件随封面模板控件一起禁用,停止/完成后恢复。 - `GenerateTab(..., title_templates_dir=<临时目录>)` 不会写真实默认 `data/`。 - 既有封面模板 UI 测试不回归。 - 验证命令(unittest,不引入 pytest;GUI offscreen): - `py -3.10 -m unittest tests.test_gui` - `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` ## 边界(不改什么) - 不改 T-583 数据层契约(CRUD/目录/默认播种)。 - 不改 `generate_batch`/生成读取路径/`render_prompt`/AI/cmhub。 - 不改封面模板 CRUD 数据语义;可为文案一致把按钮显示改成「保存模板」,但不改保存/另存/重命名/删除行为。 - 不改标题/封面占位符语义、`title_prompt.txt` 工作文本语义。 - 不改右侧任务表、生成/停止/重置按钮区、③/①/CDP/DB。 ## 执行记录 2026-07-10 Codex: - `app/gui/tabs/generate.py`:`GenerateTab` 增加 `title_templates_dir` 注入,默认走 `appconfig.title_templates_dir(self.config)`;`ensure_default_prompts` 传入标题模板目录,避免测试或新用户初始化写错目录。标题提示词区新增模板下拉/新建/保存模板/模板操作(另存为/重命名/删除),封面模板控件压缩到一行并把保存按钮文案统一为「保存模板」。标题「插入旧标题」「保存标题提示词」移动到输入框下工具条;封面「插入标题」「预览」保留在封面输入框下工具条。生成运行中会禁用标题/封面模板下拉、模板按钮和菜单 action。 - 标题模板行为:启动时仍回显 `title_prompt.txt` 工作文本,不自动用默认模板覆盖;用户选择标题模板时才载入到标题输入框。「保存标题提示词」只写 `title_prompt.txt`,「保存模板」只写当前标题模板,未选中模板时进入另存为。 - `tests/test_gui.py`:覆盖标题模板控件 objectName/菜单、默认标题模板播种、标题模板 CRUD、工作文本与模板保存互不混淆、运行中禁用新增模板控件;同步封面保存按钮新文案。 - `docs/routes.md`、`docs/04-architecture.md`:同步 ② AI生成左侧提示词区结构、标题模板目录和“选择模板才载入,不覆盖工作文本”的约束。 - 当前工作树有无关的默认封面提示词/版本号/任务总表本地改动,未纳入本任务;因此先跑不依赖默认封面文件名的关键 GUI 子集。 - 验证: - `python -m ruff check app tests main.py` 通过。 - `py -3.10 -m compileall app main.py` 通过。 - `git diff --check` 通过。 - `py -3.10 -m unittest tests.test_gui.GuiTests.test_generate_tab_manages_prompt_files_and_preview tests.test_gui.GuiTests.test_generate_tab_disables_reset_while_generation_running` 通过。 2026-07-10 Codex 干净 worktree 验证(`D:\chengma\cmshopee_verify_t584`,HEAD=`da68f92`): - `py -3.10 -m unittest tests.test_gui` 通过,145 tests。 - `python -m ruff check app tests main.py` 通过。 - `py -3.10 -m compileall app main.py` 通过。 - `git diff --check` 通过。 - `py -3.10 -m unittest discover -s tests` 通过,327 tests。