T-584 AI生成提示词区重排

This commit is contained in:
chengma
2026-07-10 11:53:51 +08:00
parent bbd5427748
commit da68f92aa6
5 changed files with 253 additions and 22 deletions
+168 -6
View File
@@ -751,6 +751,7 @@ class GenerateTab(QWidget):
status_callback=None,
title_prompt_path=None,
cover_prompts_dir=None,
title_templates_dir=None,
open_accounts_callback=None,
):
super().__init__(parent)
@@ -765,7 +766,13 @@ class GenerateTab(QWidget):
self.open_accounts_callback = open_accounts_callback
self.title_prompt_path = title_prompt_path or appconfig.title_prompt_path(self.config)
self.cover_prompts_dir = cover_prompts_dir or appconfig.cover_prompts_dir(self.config)
prompts.ensure_default_prompts(self.title_prompt_path, self.cover_prompts_dir)
self.title_templates_dir = title_templates_dir or appconfig.title_templates_dir(self.config)
prompts.ensure_default_prompts(
self.title_prompt_path,
self.cover_prompts_dir,
self.title_templates_dir,
)
self.current_title_template = None
self.current_cover_template = None
self.generate_worker = None
self.generate_thread = None
@@ -781,7 +788,27 @@ class GenerateTab(QWidget):
self.title_prompt_edit.setPlainText(
prompts.load_title_prompt(self.title_prompt_path)
)
self.title_template_combo = QComboBox()
self.title_template_combo.setObjectName("titleTemplateCombo")
self.title_template_combo.setToolTip("选择标题提示词模板并载入到输入框")
self.new_title_template_button = QPushButton("新建")
self.new_title_template_button.setObjectName("newTitleTemplateButton")
self.new_title_template_button.setToolTip("新建一个标题提示词模板")
self.save_title_template_button = QPushButton("保存模板")
self.save_title_template_button.setObjectName("saveTitleTemplateButton")
self.save_title_template_button.setToolTip("保存当前选中的标题提示词模板;未选中模板时会另存为新模板")
self.title_template_actions_button = QPushButton("模板操作")
self.title_template_actions_button.setObjectName("titleTemplateActionsButton")
self.title_template_actions_menu = QMenu(self)
self.save_title_template_as_action = self.title_template_actions_menu.addAction("另存为")
self.save_title_template_as_action.setObjectName("saveTitleTemplateAsAction")
self.rename_title_template_action = self.title_template_actions_menu.addAction("重命名")
self.rename_title_template_action.setObjectName("renameTitleTemplateAction")
self.delete_title_template_action = self.title_template_actions_menu.addAction("删除")
self.delete_title_template_action.setObjectName("deleteTitleTemplateAction")
self.title_template_actions_button.setMenu(self.title_template_actions_menu)
self.save_title_button = QPushButton("保存标题提示词")
self.save_title_button.setToolTip("保存当前标题提示词工作文本,生成时会使用这份内容")
self.insert_old_title_button = QPushButton("插入旧标题")
self.insert_old_title_button.setObjectName("insertOldTitleButton")
self.cover_prompt_edit = QPlainTextEdit()
@@ -790,7 +817,8 @@ class GenerateTab(QWidget):
self.cover_template_combo = QComboBox()
self.cover_template_combo.setObjectName("coverTemplateCombo")
self.new_cover_template_button = QPushButton("新建")
self.save_cover_template_button = QPushButton("保存")
self.save_cover_template_button = QPushButton("保存模板")
self.save_cover_template_button.setToolTip("保存当前选中的封面提示词模板;未选中模板时会另存为新模板")
self.cover_template_actions_button = QPushButton("模板操作")
self.cover_template_actions_button.setObjectName("coverTemplateActionsButton")
self.cover_template_actions_menu = QMenu(self)
@@ -851,19 +879,24 @@ class GenerateTab(QWidget):
left_layout = QVBoxLayout(left_panel)
left_layout.setContentsMargins(0, 0, 12, 0)
left_layout.addWidget(QLabel("标题提示词"))
left_layout.addWidget(self.title_prompt_edit, 1)
title_template_layout = QHBoxLayout()
title_template_layout.addWidget(self.title_template_combo, 1)
title_template_layout.addWidget(self.new_title_template_button)
title_template_layout.addWidget(self.save_title_template_button)
title_template_layout.addWidget(self.title_template_actions_button)
left_layout.addLayout(title_template_layout)
left_layout.addWidget(self.title_prompt_edit, 2)
title_action_layout = QHBoxLayout()
title_action_layout.addWidget(self.save_title_button)
title_action_layout.addWidget(self.insert_old_title_button)
title_action_layout.addWidget(self.save_title_button)
title_action_layout.addStretch(1)
left_layout.addLayout(title_action_layout)
left_layout.addWidget(QLabel("封面提示词"))
left_layout.addWidget(self.cover_template_combo)
cover_template_layout = QHBoxLayout()
cover_template_layout.addWidget(self.cover_template_combo, 1)
cover_template_layout.addWidget(self.new_cover_template_button)
cover_template_layout.addWidget(self.save_cover_template_button)
cover_template_layout.addWidget(self.cover_template_actions_button)
cover_template_layout.addStretch(1)
left_layout.addLayout(cover_template_layout)
left_layout.addWidget(self.cover_prompt_edit, 2)
cover_action_layout = QHBoxLayout()
@@ -981,6 +1014,12 @@ class GenerateTab(QWidget):
self.status_filter.currentIndexChanged.connect(self.refresh_tasks)
self.refresh_button.clicked.connect(self.refresh_tasks)
self.open_image_dir_button.clicked.connect(self.open_image_directory)
self.title_template_combo.currentIndexChanged.connect(self.load_selected_title_template)
self.new_title_template_button.clicked.connect(self.new_title_template)
self.save_title_template_button.clicked.connect(self.save_title_template)
self.save_title_template_as_action.triggered.connect(self.save_title_template_as)
self.rename_title_template_action.triggered.connect(self.rename_title_template)
self.delete_title_template_action.triggered.connect(self.delete_title_template)
self.save_title_button.clicked.connect(self.save_title_prompt)
self.insert_old_title_button.clicked.connect(self.insert_old_title_placeholder)
self.cover_template_combo.currentIndexChanged.connect(self.load_selected_cover_template)
@@ -997,6 +1036,7 @@ class GenerateTab(QWidget):
self.reset_generate_button.clicked.connect(self.reset_generated_result)
self.task_table.doubleClicked.connect(self.show_task_images)
self.refresh_title_templates()
self.refresh_cover_templates()
self.refresh_tasks()
self._show_current_run_log_empty()
@@ -1224,6 +1264,120 @@ class GenerateTab(QWidget):
return
self._set_status("标题提示词已保存")
def refresh_title_templates(self, selected=None):
try:
template_names = prompts.list_title_templates(self.title_templates_dir)
except Exception as exc:
template_names = []
self._show_prompt_error(exc)
current = selected if selected is not None else self.current_title_template
self.title_template_combo.blockSignals(True)
self.title_template_combo.clear()
self.title_template_combo.addItem("选择模板", None)
for name in template_names:
self.title_template_combo.addItem(name, name)
index = self.title_template_combo.findData(current)
if index >= 0:
self.title_template_combo.setCurrentIndex(index)
self.current_title_template = current
else:
self.title_template_combo.setCurrentIndex(0)
self.current_title_template = None
self.title_template_combo.blockSignals(False)
def load_selected_title_template(self, index=None):
name = self.title_template_combo.currentData()
self.current_title_template = name
if name is None:
return
try:
self.title_prompt_edit.setPlainText(
prompts.load_title_template(name, self.title_templates_dir)
)
except Exception as exc:
self._show_prompt_error(exc)
def new_title_template(self, checked=False):
name = self._ask_template_name("新建标题提示词模板")
if not name:
return
try:
prompts.save_title_template(name, "", self.title_templates_dir)
except Exception as exc:
self._show_prompt_error(exc)
return
self.refresh_title_templates(selected=name)
self.title_prompt_edit.setPlainText("")
self._set_status(f"标题提示词模板已新建:{name}")
def save_title_template(self, checked=False):
name = self.current_title_template
if name is None:
self.save_title_template_as()
return
try:
prompts.save_title_template(
name,
self.title_prompt_edit.toPlainText(),
self.title_templates_dir,
)
except Exception as exc:
self._show_prompt_error(exc)
return
self._set_status(f"标题提示词模板已保存:{name}")
def save_title_template_as(self, checked=False):
name = self._ask_template_name("另存标题提示词模板")
if not name:
return
try:
prompts.save_title_template(
name,
self.title_prompt_edit.toPlainText(),
self.title_templates_dir,
)
except Exception as exc:
self._show_prompt_error(exc)
return
self.refresh_title_templates(selected=name)
self._set_status(f"标题提示词模板已另存为:{name}")
def rename_title_template(self, checked=False):
old_name = self.current_title_template
if old_name is None:
self._set_status("没有可重命名的标题提示词模板")
return
new_name = self._ask_template_name("重命名标题提示词模板", text=old_name)
if not new_name or new_name == old_name:
return
try:
prompts.rename_title_template(old_name, new_name, self.title_templates_dir)
except Exception as exc:
self._show_prompt_error(exc)
return
self.refresh_title_templates(selected=new_name)
self._set_status(f"标题提示词模板已重命名:{new_name}")
def delete_title_template(self, checked=False):
name = self.current_title_template
if name is None:
self._set_status("没有可删除的标题提示词模板")
return
choice = QMessageBox.question(
self,
"删除标题提示词模板",
f"确定删除「{name}」吗?",
)
if choice != QMessageBox.Yes:
return
try:
prompts.delete_title_template(name, self.title_templates_dir)
except Exception as exc:
self._show_prompt_error(exc)
return
self.refresh_title_templates()
self._set_status(f"标题提示词模板已删除:{name}")
def refresh_cover_templates(self, selected=None):
try:
template_names = prompts.list_cover_templates(self.cover_prompts_dir)
@@ -1656,7 +1810,15 @@ class GenerateTab(QWidget):
self.shop_filter.setEnabled(not running)
self.item_filter.setEnabled(not running)
self.status_filter.setEnabled(not running)
self.title_template_combo.setEnabled(not running)
self.new_title_template_button.setEnabled(not running)
self.save_title_template_button.setEnabled(not running)
self.title_template_actions_button.setEnabled(not running)
self.save_title_template_as_action.setEnabled(not running)
self.rename_title_template_action.setEnabled(not running)
self.delete_title_template_action.setEnabled(not running)
self.save_title_button.setEnabled(not running)
self.cover_template_combo.setEnabled(not running)
self.new_cover_template_button.setEnabled(not running)
self.save_cover_template_button.setEnabled(not running)
self.cover_template_actions_button.setEnabled(not running)
+2 -2
View File
@@ -417,8 +417,8 @@ data/images/<batch_id>/<slug>/<task_id>_<item_id>_new.<ext> # AI 生成的新
提示词管理:
- **标题提示词**:`data/title_prompt.txt` 是当前工作文本,「保存标题提示词」写入该文件;软件启动时加载该文件回显到输入框(缺失则空)。标题命名模板另存于 `data/prompts/title/*.txt`,只负责把命名模板载入编辑框或保存当前编辑框内容为模板,不改变生成读取路径。T-549 后标题提示词支持 `{旧标题}` 占位符:若提示词含 `{旧标题}`,生成前替换为该任务旧标题且不再自动追加旧标题块;若不含,则保持旧行为自动追加“旧标题:...”块。两种情况都会保留“请只返回新标题,不要解释。”输出约束。
- **封面提示词**:多模板。下拉选模板(读 `data/prompts/cover/*.txt`),图标工具栏 新建/保存/另存为/重命名/删除;重名校验、删除二次确认、删空给默认。
- **标题提示词**:`data/title_prompt.txt` 是当前工作文本,「保存标题提示词」写入该文件;软件启动时加载该文件回显到输入框(缺失则空)。标题命名模板另存于 `data/prompts/title/*.txt`,左侧模板行提供下拉、新建、保存模板、另存为、重命名、删除;模板只负责被用户选中后载入编辑框,或把当前编辑框内容保存为命名模板,不改变生成读取路径,也不在启动时覆盖 `title_prompt.txt`。T-549 后标题提示词支持 `{旧标题}` 占位符:若提示词含 `{旧标题}`,生成前替换为该任务旧标题且不再自动追加旧标题块;若不含,则保持旧行为自动追加“旧标题:...”块。两种情况都会保留“请只返回新标题,不要解释。”输出约束。
- **封面提示词**:多模板。左侧模板行提供下拉(读 `data/prompts/cover/*.txt`)、新建、保存模板、模板操作(另存为/重命名/删除);重名校验、删除二次确认、删空给默认。
- **变量**:标题提示词本阶段只支持 `{旧标题}`,左侧按钮「插入旧标题」在标题提示词光标处插入 `{旧标题}`。封面提示词支持占位符 `{旧标题}`、`{新标题}`、`{商品id}`、`{店铺}`,生成前用该任务真实值替换(`render_prompt`)。「插入标题」= 在封面提示词光标处插入 `{新标题}`;「预览」= 用某条任务的值替换封面变量后展示,确认实际发送给 AI 的内容。
### 6.3 应用更新(③ Tab)
+11 -12
View File
@@ -78,24 +78,23 @@
```
┌ AI生成 ───────────────────────────────────────────────────────┐
│ ┌─左 ~1/4─┐ ┌──────────────── 右 3/4 ──────────────────────┐ │
│ │标题提示词│ │ 批次[本次▼] 店铺[全部▼] 商品ID[____] 状态[全部▼] [筛选] │ │
│ │[ ]│ │ ┌──────────────────────────────────────────┐ │ │
│ │[ ]│ │ │ 店铺名 商品id 旧标题 新标题 标题状态 图片状态 │ │ │
│ │ │ │ │ 女装店 511..639 …T恤 …百搭 已生成 未启用 │ │ │
│ │封面提示词│ │ │ 女装店 511..640 … — 待生成 待生成 │ │ │
│ │[ ]│ │ └──────────────────────────────────────────┘ │ │
│ │[ ]│ │ (双击某行 → 弹窗看 旧封面 | 新封面) │ │
│ │ │ │ 运行日志:逐条记录标题/封面生成步骤与失败原因 │ │
│ └──────────┘ └───────────────────────────────────────────────┘ │
│ 左侧提示词区: │
│ 标题提示词 │
│ 模板[▼] [新建] [保存模板] [模板操作▼] │
│ [标题提示词输入框,较旧版增高] │
│ [插入旧标题] [保存标题提示词] │
│ 封面提示词 │
│ 模板[▼] [新建] [保存模板] [模板操作▼] │
│ [封面提示词输入框] [插入标题] [预览] │
│ 右侧任务区:批次/店铺/商品ID/状态筛选 + 任务表 + AI生成运行日志 │
│ 生成内容[只生成标题▼] 标题30/30 ━━━━━ 生标题用时 18 秒 [▶ 开始生成][■停止][重置生成结果] │
│ 图片0/0 ━━━━━ 生图用时 0 秒 │
└───────────────────────────────────────────────────────────────┘
```
- 左侧(提示词管理,上下两块):
- **标题提示词**:多行输入 + 「保存标题提示词」(写 `data/title_prompt.txt`)+「插入旧标题」(插 `{旧标题}`);启动时自动加载回显。若标题提示词包含 `{旧标题}`,生成前替换为当前任务旧标题且不重复追加旧标题块;不包含时保持旧行为自动追加旧标题。
- **封面提示词**:模板下拉(读 `data/prompts/cover/*.txt`)+ 图标工具栏(新建/保存/另存为/重命名/删除)+ 多行输入 + 「插入标题」(插 `{新标题}`)/「预览」(变量替换后查看)。
- **标题提示词**:模板下拉(读 `data/prompts/title/*.txt`)+「新建 / 保存模板 / 模板操作(另存为、重命名、删除)」+ 多行输入 + 下方工具条「插入旧标题」(插 `{旧标题}`)/「保存标题提示词」(写 `data/title_prompt.txt`)。启动时自动加载 `title_prompt.txt` 回显,不自动用模板覆盖工作文本;用户选择模板时才把模板内容载入输入框。若标题提示词包含 `{旧标题}`,生成前替换为当前任务旧标题且不重复追加旧标题块;不包含时保持旧行为自动追加旧标题。
- **封面提示词**:模板控件压缩到一行(读 `data/prompts/cover/*.txt`,新建/保存模板/另存为/重命名/删除)+ 多行输入 + 下方工具条「插入标题」(插 `{新标题}`)/「预览」(变量替换后查看)。
- 变量:标题提示词本阶段只支持 `{旧标题}`;封面提示词支持 `{旧标题}`/`{新标题}`/`{商品id}`/`{店铺}`,生成前按任务替换。
- 右上:按导入批次 / 店铺 / 商品ID / 状态筛选任务;商品ID输入框按包含匹配 `item_id`,清空表示全部。
- 筛选行提供「打开图片文件夹」按钮,用于只读打开本地图片目录:选中某行时打开该商品所在账号图片文件夹(优先打开已有新/旧封面文件的真实父目录,缺失时回退到规范账号目录);未选行且选择具体批次时打开该批次图片文件夹;未选行且为全部批次时打开图片根目录。目录不存在只中文提示,不自动创建目录,不修改任务状态。
+12 -2
View File
@@ -3,7 +3,7 @@ id: T-584
title: ②左侧提示词区 reorg:标题提示词加模板控件行 + 封面控件压一行 + 插入类按钮下移工具条 + 增高标题输入框
phase: 7
deps: [T-583]
status: TODO
status: DONE
created: 2026-07-10
---
@@ -77,4 +77,14 @@ created: 2026-07-10
## 执行记录
(做完在这里写:改了什么文件、跑了什么验证命令及结果、遇到的阻塞、关键决策。)
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` 通过。
+60
View File
@@ -1792,11 +1792,13 @@ class GuiTests(TempDirMixin, unittest.TestCase):
def test_generate_tab_has_prompt_editors_and_task_table(self):
with self.make_temp_dir() as temp_dir:
title_prompt_path = os.path.join(temp_dir, "title_prompt.txt")
title_templates_dir = os.path.join(temp_dir, "prompts", "title")
cover_prompts_dir = os.path.join(temp_dir, "prompts", "cover")
tab = GenerateTab(
config=self.make_config(temp_dir),
title_prompt_path=title_prompt_path,
cover_prompts_dir=cover_prompts_dir,
title_templates_dir=title_templates_dir,
)
self.addCleanup(tab.close)
@@ -1804,9 +1806,14 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assertIsInstance(tab.cover_prompt_edit, QPlainTextEdit)
self.assertIsInstance(tab.task_table, QTableView)
self.assertIsInstance(tab.generate_mode_combo, QComboBox)
self.assertEqual("titleTemplateCombo", tab.title_template_combo.objectName())
self.assertEqual("newTitleTemplateButton", tab.new_title_template_button.objectName())
self.assertEqual("saveTitleTemplateButton", tab.save_title_template_button.objectName())
self.assertEqual("titleTemplateActionsButton", tab.title_template_actions_button.objectName())
self.assertEqual("标题提示词", tab.title_prompt_edit.placeholderText())
self.assertEqual("封面提示词", tab.cover_prompt_edit.placeholderText())
self.assertEqual("保存标题提示词", tab.save_title_button.text())
self.assertEqual("保存模板", tab.save_title_template_button.text())
self.assertEqual("插入旧标题", tab.insert_old_title_button.text())
self.assertEqual("开始生成", tab.generate_button.text())
self.assertEqual("停止", tab.stop_generate_button.text())
@@ -1840,8 +1847,17 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assertEqual(1, tab.title_progress_bar.maximum())
self.assertEqual(1, tab.cover_progress_bar.maximum())
self.assertIn("蝦皮台灣站", tab.title_prompt_edit.toPlainText())
self.assertEqual("选择模板", tab.title_template_combo.currentText())
self.assertIn("默认", [tab.title_template_combo.itemText(index) for index in range(tab.title_template_combo.count())])
self.assertEqual("模板操作", tab.title_template_actions_button.text())
self.assertIs(tab.title_template_actions_menu, tab.title_template_actions_button.menu())
self.assertEqual(
["另存为", "重命名", "删除"],
[action.text() for action in tab.title_template_actions_menu.actions()],
)
self.assertEqual("papa1", tab.cover_template_combo.currentText())
self.assertIn("商品标题:{新标题}", tab.cover_prompt_edit.toPlainText())
self.assertEqual("保存模板", tab.save_cover_template_button.text())
self.assertEqual("模板操作", tab.cover_template_actions_button.text())
self.assertIs(tab.cover_template_actions_menu, tab.cover_template_actions_button.menu())
self.assertEqual(
@@ -2449,12 +2465,14 @@ class GuiTests(TempDirMixin, unittest.TestCase):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
title_prompt_path = os.path.join(temp_dir, "title_prompt.txt")
title_templates_dir = os.path.join(temp_dir, "prompts", "title")
cover_prompts_dir = os.path.join(temp_dir, "prompts", "cover")
tab = GenerateTab(
config=cfg,
title_prompt_path=title_prompt_path,
cover_prompts_dir=cover_prompts_dir,
title_templates_dir=title_templates_dir,
)
self.addCleanup(tab.close)
@@ -2462,6 +2480,7 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assertEqual("papa1", tab.cover_template_combo.currentText())
self.assertIn("商品标题:{新标题}", tab.cover_prompt_edit.toPlainText())
self.assertTrue(os.path.exists(title_prompt_path))
self.assertTrue(os.path.exists(os.path.join(title_templates_dir, "默认.txt")))
self.assertTrue(os.path.exists(os.path.join(cover_prompts_dir, "papa1.txt")))
self.assert_removed(temp_dir)
@@ -2470,8 +2489,10 @@ class GuiTests(TempDirMixin, unittest.TestCase):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
title_prompt_path = os.path.join(temp_dir, "title_prompt.txt")
title_templates_dir = os.path.join(temp_dir, "prompts", "title")
cover_prompts_dir = os.path.join(temp_dir, "prompts", "cover")
prompts.save_title_prompt("标题启动回显", title_prompt_path)
prompts.save_title_template("标题基础", "模板标题 {旧标题}", title_templates_dir)
prompts.save_cover_template(
"基础",
"把{旧标题}变成{新标题},商品{商品id},店铺{店铺}",
@@ -2502,10 +2523,13 @@ class GuiTests(TempDirMixin, unittest.TestCase):
status_callback=statuses.append,
title_prompt_path=title_prompt_path,
cover_prompts_dir=cover_prompts_dir,
title_templates_dir=title_templates_dir,
)
self.addCleanup(tab.close)
self.assertEqual("标题启动回显", tab.title_prompt_edit.toPlainText())
self.assertEqual("选择模板", tab.title_template_combo.currentText())
self.assertIn("标题基础", prompts.list_title_templates(title_templates_dir))
self.assertEqual("基础", tab.cover_template_combo.currentText())
self.assertIn("{旧标题}", tab.cover_prompt_edit.toPlainText())
@@ -2518,6 +2542,30 @@ class GuiTests(TempDirMixin, unittest.TestCase):
tab.title_prompt_edit.setTextCursor(cursor)
tab.insert_old_title_placeholder()
self.assertEqual("A{旧标题}B", tab.title_prompt_edit.toPlainText())
self.assertEqual("新标题提示词", prompts.load_title_prompt(title_prompt_path))
tab.title_template_combo.setCurrentIndex(tab.title_template_combo.findData("标题基础"))
self.assertEqual("模板标题 {旧标题}", tab.title_prompt_edit.toPlainText())
tab.title_prompt_edit.setPlainText("标题另存内容")
with mock.patch("app.gui.QInputDialog.getText", return_value=("标题另存", True)):
tab.save_title_template_as_action.trigger()
self.assertEqual("标题另存", tab.title_template_combo.currentText())
self.assertEqual(
"标题另存内容",
prompts.load_title_template("标题另存", title_templates_dir),
)
self.assertEqual("新标题提示词", prompts.load_title_prompt(title_prompt_path))
with mock.patch("app.gui.QInputDialog.getText", return_value=("标题改名", True)):
tab.rename_title_template_action.trigger()
self.assertEqual("标题改名", tab.title_template_combo.currentText())
self.assertIn("标题改名", prompts.list_title_templates(title_templates_dir))
tab.title_prompt_edit.setPlainText("标题模板保存")
tab.save_title_template()
self.assertEqual(
"标题模板保存",
prompts.load_title_template("标题改名", title_templates_dir),
)
tab.cover_prompt_edit.setPlainText("另存模板 {新标题}")
with mock.patch("app.gui.QInputDialog.getText", return_value=("另存", True)):
@@ -2548,6 +2596,10 @@ class GuiTests(TempDirMixin, unittest.TestCase):
tab.delete_cover_template_action.trigger()
self.assertNotIn("改名", prompts.list_cover_templates(cover_prompts_dir))
with mock.patch("app.gui.QMessageBox.question", return_value=gui.QMessageBox.Yes):
tab.delete_title_template_action.trigger()
self.assertNotIn("标题改名", prompts.list_title_templates(title_templates_dir))
self.assert_removed(temp_dir)
def test_cover_gallery_lists_candidates_and_selects_current_cover(self):
@@ -3424,6 +3476,14 @@ class GuiTests(TempDirMixin, unittest.TestCase):
tab._set_generate_running(True)
self.assertFalse(tab.reset_generate_button.isEnabled())
self.assertFalse(tab.title_template_combo.isEnabled())
self.assertFalse(tab.new_title_template_button.isEnabled())
self.assertFalse(tab.save_title_template_button.isEnabled())
self.assertFalse(tab.title_template_actions_button.isEnabled())
self.assertFalse(tab.save_title_template_as_action.isEnabled())
self.assertFalse(tab.rename_title_template_action.isEnabled())
self.assertFalse(tab.delete_title_template_action.isEnabled())
self.assertFalse(tab.cover_template_combo.isEnabled())
tab.generate_thread = object()
tab.reset_generated_result()