feat(ai): generate covers without new titles

This commit is contained in:
chengma
2026-07-13 15:22:15 +08:00
parent e2fbae2ee1
commit d42a9c8084
13 changed files with 334 additions and 36 deletions
+99 -4
View File
@@ -3272,6 +3272,21 @@ class GuiTests(TempDirMixin, unittest.TestCase):
apply_attempts=0,
committed=0,
),
SimpleNamespace(
alias="papa",
account_name="papa 店铺",
item_id="1006",
old_title="旧标题6",
new_title="",
new_cover_path="cover-only.jpg",
stage="generated",
status="success",
last_error="",
collect_attempts=1,
generate_attempts=1,
apply_attempts=0,
committed=0,
),
]
model = gui.GenerateTaskTableModel()
model.set_tasks(tasks, [account])
@@ -3290,6 +3305,13 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assertEqual("待生成", model.index(3, 5).data())
self.assertEqual("已生成", model.index(4, 5).data())
model.set_generate_mode("cover")
self.assertEqual("待生成", model.index(1, 5).data())
self.assertEqual("待生成", model.index(3, 5).data())
self.assertEqual("已生成", model.index(4, 5).data())
self.assertEqual("待生成", model.index(5, 4).data())
self.assertEqual("已生成", model.index(5, 5).data())
tab = GenerateTab(config=self.make_config(temp_dir))
self.addCleanup(tab.close)
tab.task_table.resize(600, 240)
@@ -3920,6 +3942,47 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_generate_tab_cover_preview_uses_old_title_when_new_title_is_missing(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
cfg["ai"] = appconfig.ai_config(cfg)
cfg["ai"]["generate_mode"] = "cover"
cfg["ai"]["generate_cover"] = True
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"])
tab = GenerateTab(
config=cfg,
title_prompt_path=os.path.join(temp_dir, "title_prompt.txt"),
cover_prompts_dir=os.path.join(temp_dir, "prompts", "cover"),
title_templates_dir=os.path.join(temp_dir, "prompts", "title"),
)
self.addCleanup(tab.close)
tab.cover_prompt_edit.setPlainText("新:{新标题};旧:{旧标题}")
tab.task_table.selectRow(0)
with mock.patch("app.gui.QMessageBox.information") as information:
tab.preview_cover_prompt()
self.assertEqual("新:旧标题;旧:旧标题", information.call_args[0][2])
self.assert_removed(temp_dir)
def test_cover_gallery_lists_candidates_and_selects_current_cover(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)
@@ -5403,7 +5466,6 @@ class GuiTests(TempDirMixin, unittest.TestCase):
)
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, "手动标题", None, path=cfg["db_path"])
tasks = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])
logs = []
progress = []
@@ -5436,14 +5498,14 @@ class GuiTests(TempDirMixin, unittest.TestCase):
gen_title.assert_not_called()
gen_cover.assert_called_once()
updated = db.list_tasks(batch_id=batch_id, path=cfg["db_path"])[0]
self.assertEqual("手动标题", updated.new_title)
self.assertIsNone(updated.new_title)
self.assertTrue(os.path.exists(updated.new_cover_path))
self.assertEqual(0, progress[-1]["title_total"])
self.assertEqual(1, progress[-1]["cover_total"])
joined_logs = "\n".join(logs)
self.assertIn("本轮生成内容:只生成封面", joined_logs)
self.assertIn("标题0,图片1", joined_logs)
self.assertIn("已有标题,跳过生文", joined_logs)
self.assertIn("没有新标题,本轮使用旧标题作为封面参考", joined_logs)
self.assertIn("[完成] AI 生成完成:标题0/0,图片1/1,失败0", joined_logs)
self.assert_removed(temp_dir)
@@ -5554,9 +5616,10 @@ class GuiTests(TempDirMixin, unittest.TestCase):
)
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, "手动标题", None, path=cfg["db_path"])
tab = GenerateTab(config=cfg)
self.addCleanup(tab.close)
tab.status_filter.setCurrentIndex(tab.status_filter.findData("to_generate"))
self.assertEqual(1, tab.model.rowCount())
class FakeSignal:
def __init__(self):
@@ -6137,6 +6200,38 @@ class GuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_apply_tab_allows_cover_only_result_but_blocks_modes_that_need_title(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_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_cover(task.id, "new-cover.jpg", path=cfg["db_path"])
generated = db.get_task(task.id, path=cfg["db_path"])
tab = ApplyTab(config=cfg)
self.addCleanup(tab.close)
self.assertIsNone(tab._update_content_error([generated], "cover"))
self.assertIn("缺少新标题", tab._update_content_error([generated], "title"))
self.assertIn("缺少新标题", tab._update_content_error([generated], "title_cover"))
self.assert_removed(temp_dir)
def test_apply_worker_applies_success_failure_and_unmatched_serially(self):
with self.make_temp_dir() as temp_dir:
cfg = self.make_config(temp_dir)