diff --git a/docs/tasks/T-583.md b/docs/tasks/T-583.md index 502978d..3bd01d6 100644 --- a/docs/tasks/T-583.md +++ b/docs/tasks/T-583.md @@ -1,6 +1,6 @@ --- id: T-583 -title: 标题提示词模板数据层:泛化 prompts 模板 CRUD + 新增 title_templates 目录(加法,不换单文件) +title: 标题提示词模板数据层:泛化 prompts 模板 CRUD + 新增 prompts/title 目录(加法,不换单文件) phase: 7 deps: [] status: TODO @@ -16,9 +16,9 @@ created: 2026-07-10 - `prompts.py` 现有 `list/load/save/rename/delete_cover_template` 五个写死 cover 的函数 + `render_prompt`(共享)+ `ensure_default_prompts`(播种默认封面模板)。 定案(已评审): -1. **加法、不换单文件**:`title_prompt.txt` **保留为"当前工作文本"**(语义不变、不迁移、编辑框仍从它载入),**另加** `title_templates/` 目录放命名模板。纯新增能力,零迁移、零丢失风险。 +1. **加法、不换单文件**:`title_prompt.txt` **保留为"当前工作文本"**(语义不变、不迁移、编辑框仍从它载入),**另加** `data/prompts/title/` 目录放命名模板。纯新增能力,零迁移、零丢失风险。 2. **泛化 CRUD**:把 cover 那五个函数泛化成按目录参数化的通用模板 CRUD,标题/封面共用一套,不复制第二份(防两套分叉)。 -3. **标题默认模板**:拿现有默认标题提示词播一条进 `title_templates/`(不新建 `default_prompts/title` 包)。 +3. **标题默认模板**:拿现有默认标题提示词播一条进 `data/prompts/title/`(不新建 `default_prompts/title` 包)。 本任务只做数据层,无 UI(UI reorg 见 T-584)。 @@ -28,24 +28,33 @@ created: 2026-07-10 - 抽出目录参数化的通用函数(命名实现定,如):`list_templates(directory)`、`load_template(name, directory)`、`save_template(name, text, directory)`、`rename_template(old, new, directory)`、`delete_template(name, directory)`,含现有 `_normalize_name`/`_template_path`/重名保护。 - 现有 `*_cover_template` 保留为**薄封装**(转调通用函数,传 `COVER_PROMPTS_DIR`),保证封面既有调用点零改动、零回归。 - 新增标题模板薄封装或直接让 GUI 传 `title_templates` 目录调用通用函数(择一,UI 任务据此对接)。 +- 通用函数的错误文案使用中性中文,例如「提示词模板名不能为空 / 提示词模板不存在 / 提示词模板已存在」,不要在标题模板路径上暴露“封面提示词模板”。 ### `app/appconfig.py` — 目录路径 -- 新增 `title_templates_dir(config=None)` → `data_path("title_templates", ...)`(与 `cover_prompts_dir` 同款)。 +- 新增 `title_templates_dir(config=None)` → `data_path("prompts", "title", config=config)`,与现有 `cover_prompts_dir(config=None)` 的 `data/prompts/cover/` 形成同层目录。 +- 不把标题模板放到 `data/title_templates/`,避免提示词存储分散。 ### `app/prompts.py` `ensure_default_prompts` — 播种标题默认模板 - 现有逻辑保留(`title_prompt.txt` 缺失时写默认、封面模板缺失时播默认)。 -- 新增:若 `title_templates/` 为空,把**现有默认标题提示词**(`_read_default_prompt_text("title_prompt.txt")` 同源)作为一条模板播入(模板名如「默认」)。不新建 `app/default_prompts/title` 包。 +- 新增第三参数 `title_templates_dir=None`:若为空时播入一条默认标题模板(内容 = `_read_default_prompt_text("title_prompt.txt")`,模板名如「默认」)。不新建 `app/default_prompts/title` 包。 +- 调用方显式传入 `title_templates_dir` 时按该目录播种;未传时必须从 `title_prompt_path` 推导同一个用户数据根下的 `prompts/title/`,避免测试或临时配置只传 `title_prompt_path` / `cover_prompts_dir` 时误写真实默认 `data/`。 +- 已有标题模板时不覆盖;`title_prompt.txt` 为空时仍按旧逻辑写默认工作文本。 ### 数据/边界 - `title_prompt.txt` 语义**不变**:仍是编辑框当前工作文本的持久化,`load/save_title_prompt` 不动。 -- 标题模板与封面模板是**两个独立目录**,占位符(标题 `{旧标题}` 等 vs 封面 `{新标题}` 等)各自语义不变;`render_prompt` 共享不改。 +- 标题模板与封面模板是**两个独立目录**:`data/prompts/title/*.txt` 与 `data/prompts/cover/*.txt`,占位符(标题 `{旧标题}` 等 vs 封面 `{新标题}` 等)各自语义不变;`render_prompt` 共享不改。 + +### 文档同步 +- 更新 `docs/04-architecture.md` 提示词存储说明:`data/title_prompt.txt` 是当前工作标题提示词;`data/prompts/title/*.txt` 是标题模板;`data/prompts/cover/*.txt` 是封面模板。 +- 若 `docs/routes.md` / 设置或打包文档已有提示词目录描述,同步保持 `prompts/title` / `prompts/cover` 口径。 ## 验收要点 - 通用模板 CRUD 存在且被 cover 薄封装复用;`list/load/save/rename/delete_cover_template` 行为不回归(既有封面模板测试全绿)。 -- 新增 `title_templates_dir` 指向 `data/title_templates`;`list_templates` 能对该目录增删查、重名保护生效。 -- `ensure_default_prompts`:`title_templates/` 为空时播入一条默认标题模板(内容 = 现有默认标题提示词);已有模板时不覆盖。 +- 新增 `title_templates_dir` 指向 `data/prompts/title`;`list_templates` 能对该目录增删查、重名保护生效。 +- `ensure_default_prompts`:`prompts/title/` 为空时播入一条默认标题模板(内容 = 现有默认标题提示词);已有模板时不覆盖;传临时 `title_prompt_path` 时不会误写真实默认 `data/`。 - `title_prompt.txt` 及 `load/save_title_prompt` 行为不变(编辑框工作文本不受影响,无迁移、无丢失)。 - 标题/封面模板互不干扰(各自目录)。 +- `docs/04-architecture.md` 已同步提示词存储结构。 - 不改 `generate_batch`/生成读取路径/`render_prompt`。 - 验证命令(unittest,不引入 pytest): - `py -3.10 -m unittest tests.test_prompts tests.test_appconfig`(若无 test_prompts 则新建) @@ -59,6 +68,7 @@ created: 2026-07-10 - 不改 `title_prompt.txt` 语义、不迁移/删除该文件。 - 不复制第二份模板 CRUD;封面走薄封装复用通用实现。 - 不做 GUI(T-584);不新建 `default_prompts/title` 包。 +- 不把标题模板放到 `data/title_templates/`;统一使用 `data/prompts/title/`。 - 不改 CDP/DB/AI 请求/cmhub/Excel。 ## 执行记录 diff --git a/docs/tasks/T-584.md b/docs/tasks/T-584.md index 5bf43f2..9bfd92f 100644 --- a/docs/tasks/T-584.md +++ b/docs/tasks/T-584.md @@ -9,7 +9,7 @@ created: 2026-07-10 ## 问题 / 背景 -②标题提示词区现无模板管理(只有 label + 输入框 + 「保存标题提示词」+「插入旧标题」);封面提示词区已有「下拉框/新建/保存/模板操作(另存为/重命名/删除)」但铺了多行。T-583 已提供标题模板数据层(`title_templates/` + 通用 CRUD + 默认模板播种)。本任务做左侧 UI 重排,让标题拥有与封面对等的模板管理,并腾出纵向空间给标题输入框。 +②标题提示词区现无模板管理(只有 label + 输入框 + 「保存标题提示词」+「插入旧标题」);封面提示词区已有「下拉框/新建/保存/模板操作(另存为/重命名/删除)」但铺了多行。T-583 已提供标题模板数据层(`data/prompts/title/` + 通用 CRUD + 默认模板播种)。本任务做左侧 UI 重排,让标题拥有与封面对等的模板管理,并腾出纵向空间给标题输入框。 定案排布(已评审): - 模板控件放在 **label 下方单独一行**(不贴 label 同行——窄栏塞不下下拉+3按钮)。 @@ -22,34 +22,44 @@ created: 2026-07-10 标题提示词区(新结构,自上而下): 1. label「标题提示词」 -2. **模板控件行**(新增):`[标题模板下拉] [新建] [保存] [模板操作▾(另存为/重命名/删除)]`——镜像封面那套,控件用 `title_template_*` 命名,调 T-583 通用 CRUD(传 `title_templates_dir`)。 +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. **模板控件行**(压到一行):`[封面模板下拉] [新建] [保存] [模板操作▾]`。 +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`)与「保存(模板)」是两件事,二者都保留、语义在 tooltip 说清。 +- 「保存标题提示词」(工作文本→`title_prompt.txt`)与「保存模板」(当前模板→`data/prompts/title/<名称>.txt`)是两件事,二者都保留、语义在 tooltip 说清。 +- 若当前没有选中标题模板时点击「保存模板」,走“另存为标题提示词模板”逻辑,不覆盖 `title_prompt.txt`。 ### 命名 / 一致性 -- 新控件 `objectName` 用 `titleTemplateCombo`/`newTitleTemplateButton`/`saveTitleTemplateButton`/`titleTemplateActionsButton` + 三个 action,供测试定位。 +- 新控件 `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` @@ -61,7 +71,7 @@ created: 2026-07-10 ## 边界(不改什么) - 不改 T-583 数据层契约(CRUD/目录/默认播种)。 - 不改 `generate_batch`/生成读取路径/`render_prompt`/AI/cmhub。 -- 不改封面模板既有 handler 逻辑本身(仅调整其控件所在布局行)。 +- 不改封面模板 CRUD 数据语义;可为文案一致把按钮显示改成「保存模板」,但不改保存/另存/重命名/删除行为。 - 不改标题/封面占位符语义、`title_prompt.txt` 工作文本语义。 - 不改右侧任务表、生成/停止/重置按钮区、③/①/CDP/DB。