feat: 完成T-302p提示词管理
新增app/prompts.py,支持标题提示词读写、封面模板列表/读取/保存/重命名/删除,以及旧标题、新标题、商品id、店铺变量替换。
Tab②接入标题提示词启动回显和保存,封面模板下拉、新建、保存、另存为、重命名、删除、插入{新标题}与变量预览;本任务仍不调用AI、不写SQLite。
新增tests/test_prompts.py并扩展GUI测试覆盖提示词文件管理和预览;同步任务看板、API、routes、current-state和progress,下一个任务更新为T-303。
This commit is contained in:
+85
-2
@@ -9,11 +9,12 @@ sys.path.insert(0, os.path.dirname(__file__))
|
||||
from _helpers import TempDirMixin
|
||||
|
||||
from app import gui
|
||||
from app import accounts, db
|
||||
from app import accounts, db, prompts
|
||||
|
||||
if gui.QT_IMPORT_ERROR is not None:
|
||||
raise unittest.SkipTest("PySide6 未安装")
|
||||
|
||||
from PySide6.QtGui import QTextCursor
|
||||
from PySide6.QtWidgets import QApplication, QLineEdit, QPlainTextEdit, QTableView
|
||||
|
||||
from app.gui import (
|
||||
@@ -75,7 +76,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:
|
||||
tab = GenerateTab(config=self.make_config(temp_dir))
|
||||
title_prompt_path = os.path.join(temp_dir, "title_prompt.txt")
|
||||
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,
|
||||
)
|
||||
self.addCleanup(tab.close)
|
||||
|
||||
self.assertIsInstance(tab.title_prompt_edit, QPlainTextEdit)
|
||||
@@ -83,11 +90,87 @@ class GuiTests(TempDirMixin, unittest.TestCase):
|
||||
self.assertIsInstance(tab.task_table, QTableView)
|
||||
self.assertEqual("标题提示词", tab.title_prompt_edit.placeholderText())
|
||||
self.assertEqual("封面提示词", tab.cover_prompt_edit.placeholderText())
|
||||
self.assertEqual("保存标题提示词", tab.save_title_button.text())
|
||||
self.assertEqual("默认", tab.cover_template_combo.currentText())
|
||||
self.assertEqual(["店铺", "商品ID", "旧标题", "新标题", "状态"], tab.model.HEADERS)
|
||||
self.assertEqual("任务 0/0 条", tab.summary_label.text())
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_generate_tab_manages_prompt_files_and_preview(self):
|
||||
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")
|
||||
cover_prompts_dir = os.path.join(temp_dir, "prompts", "cover")
|
||||
prompts.save_title_prompt("标题启动回显", title_prompt_path)
|
||||
prompts.save_cover_template(
|
||||
"基础",
|
||||
"把{旧标题}变成{新标题},商品{商品id},店铺{店铺}",
|
||||
cover_prompts_dir,
|
||||
)
|
||||
accounts.create_account("主店", "alias-a", debug_port=9222, config=cfg)
|
||||
batch_id = db.create_batch(["input.xlsx"], path=cfg["db_path"])
|
||||
db.insert_tasks(
|
||||
batch_id,
|
||||
[
|
||||
{
|
||||
"source_file_abs": os.path.join(temp_dir, "input.xlsx"),
|
||||
"source_sheet": "商品",
|
||||
"source_row": 2,
|
||||
"account_name": "Excel主店",
|
||||
"alias": "alias-a",
|
||||
"item_id": "51100639510",
|
||||
}
|
||||
],
|
||||
path=cfg["db_path"],
|
||||
)
|
||||
task = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
|
||||
db.set_collected(task.id, "旧标题", "old.jpg", path=cfg["db_path"])
|
||||
db.set_generated(task.id, "新标题", "new.jpg", path=cfg["db_path"])
|
||||
statuses = []
|
||||
tab = GenerateTab(
|
||||
config=cfg,
|
||||
status_callback=statuses.append,
|
||||
title_prompt_path=title_prompt_path,
|
||||
cover_prompts_dir=cover_prompts_dir,
|
||||
)
|
||||
self.addCleanup(tab.close)
|
||||
|
||||
self.assertEqual("标题启动回显", tab.title_prompt_edit.toPlainText())
|
||||
self.assertEqual("基础", tab.cover_template_combo.currentText())
|
||||
self.assertIn("{旧标题}", tab.cover_prompt_edit.toPlainText())
|
||||
|
||||
tab.title_prompt_edit.setPlainText("新标题提示词")
|
||||
tab.save_title_prompt()
|
||||
self.assertEqual("新标题提示词", prompts.load_title_prompt(title_prompt_path))
|
||||
|
||||
tab.cover_prompt_edit.setPlainText("另存模板 {新标题}")
|
||||
with mock.patch("app.gui.QInputDialog.getText", return_value=("另存", True)):
|
||||
tab.save_cover_template_as()
|
||||
self.assertEqual("另存", tab.cover_template_combo.currentText())
|
||||
self.assertEqual("另存模板 {新标题}", prompts.load_cover_template("另存", cover_prompts_dir))
|
||||
|
||||
with mock.patch("app.gui.QInputDialog.getText", return_value=("改名", True)):
|
||||
tab.rename_cover_template()
|
||||
self.assertEqual("改名", tab.cover_template_combo.currentText())
|
||||
self.assertIn("改名", prompts.list_cover_templates(cover_prompts_dir))
|
||||
|
||||
tab.cover_prompt_edit.setPlainText("预览 {旧标题} {新标题} {商品id} {店铺}")
|
||||
tab.task_table.selectRow(0)
|
||||
with mock.patch("app.gui.QMessageBox.information") as info:
|
||||
tab.preview_cover_prompt()
|
||||
self.assertIn("预览 旧标题 新标题 51100639510 主店", info.call_args[0][2])
|
||||
|
||||
tab.cover_prompt_edit.moveCursor(QTextCursor.End)
|
||||
tab.insert_title_placeholder()
|
||||
self.assertTrue(tab.cover_prompt_edit.toPlainText().endswith("{新标题}"))
|
||||
|
||||
with mock.patch("app.gui.QMessageBox.question", return_value=gui.QMessageBox.Yes):
|
||||
tab.delete_cover_template()
|
||||
self.assertNotIn("改名", prompts.list_cover_templates(cover_prompts_dir))
|
||||
|
||||
self.assert_removed(temp_dir)
|
||||
|
||||
def test_generate_tab_lists_tasks_and_filters_by_shop_status_and_batch(self):
|
||||
with self.make_temp_dir() as temp_dir:
|
||||
cfg = self.make_config(temp_dir)
|
||||
|
||||
Reference in New Issue
Block a user