feat(suite): confirm planned generation cost

This commit is contained in:
chengma
2026-07-17 11:59:07 +08:00
parent 1ef5721a20
commit d5d991e844
6 changed files with 440 additions and 39 deletions
+131 -3
View File
@@ -3076,12 +3076,14 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
self.assertIn("主店(alias-a)", confirmations[0][1])
self.assertIn("商品ID:51100639510", confirmations[0][1])
self.assertIn("可用商品原图:1张", confirmations[0][1])
self.assertIn("每张上传图分别作为主图生成:是", confirmations[0][1])
self.assertIn("逐图主图:已开启", confirmations[0][1])
self.assertIn("白底图只使用第一张原图", confirmations[0][1])
self.assertIn("图片比例:1:1", confirmations[0][1])
self.assertIn("生成总数:", confirmations[0][1])
self.assertIn("消耗 cmhub 点数", confirmations[0][1])
self.assertIn("本次生成总数:", confirmations[0][1])
self.assertIn("暂时无法取得预计扣点", confirmations[0][1])
self.assertEqual("确认生成", confirmations[0][2]["confirm_text"])
self.assertEqual("返回修改", confirmations[0][2]["cancel_text"])
self.assertTrue(confirmations[0][2]["default_cancel"])
failed_job = image_studio.create_job(
project.id,
@@ -3118,6 +3120,132 @@ class ProductSuiteGuiTests(TempDirMixin, unittest.TestCase):
self.assert_removed(temp_dir)
def test_generation_confirmation_uses_planned_specs_for_cached_image_price(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
config["ai"] = {
"cmhub": {
"base_url": "https://cmhub.example.com",
"image_alias": "image-standard",
}
}
appconfig.save_cmhub_config({"api_key": "test-key"}, path=config["cmhub_config_path"])
project, _assets = self._create_project_with_assets(temp_dir, config, 3)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
self.addCleanup(cmhub_models.clear_model_catalog_cache)
state = tab._displayed_state
state.account_alias = "alias-a"
state.item_id = project.item_id
state.project_id = project.id
state.project_binding_state = project.binding_state
state.prompt = "轻便耐用,适合日常使用"
state.settings["per_image_primary"] = True
tab._load_state(state)
cmhub_models.cache_model_catalog(
"https://cmhub.example.com",
[
{
"alias": "image-standard",
"operation_type": "image",
"requires_image": True,
"pricing_status": "priced",
"prices": [{"points_cost": 2}],
}
],
)
confirmations = []
tab._confirm = lambda title, message, **kwargs: confirmations.append(
(title, message, kwargs)
) and False
self.assertFalse(tab.start_generation(state))
self.assertEqual(1, len(confirmations))
message = confirmations[0][1]
self.assertIn("逐图主图:已开启", message)
self.assertIn("白底图:1张", message)
self.assertIn("场景图:6张", message)
self.assertIn("卖点图:6张", message)
self.assertIn("本次生成总数:13张", message)
self.assertIn("预计单张扣点:2 点", message)
self.assertIn("预计总扣点:26 点", message)
self.assertEqual([], image_studio.list_jobs(project.id, path=config["db_path"]))
self.assert_removed(temp_dir)
def test_generation_confirmation_explains_non_per_image_primary(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
project, assets = self._create_project_with_assets(temp_dir, config, 2)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
state = tab._displayed_state
state.account_alias = "alias-a"
state.item_id = project.item_id
state.project_id = project.id
state.project_binding_state = project.binding_state
state.settings["per_image_primary"] = False
specs = product_suite.build_job_specs(
assets,
"商品卖点",
state.settings,
state.item_id,
template_text=prompts.load_product_suite_prompt(tab.product_suite_prompt_path),
)
message = tab._generation_confirmation_message(
state,
assets,
specs,
)
self.assertIn("逐图主图:未开启", message)
self.assertIn("所有分类都只使用第一张可用原图生成", message)
self.assertIn("本次生成总数:5张", message)
self.assert_removed(temp_dir)
def test_generation_confirmation_rejects_plan_changed_while_reading_price(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)
project, assets = self._create_project_with_assets(temp_dir, config, 1)
tab = ProductSuiteTab(config=config, db_path=config["db_path"])
self.addCleanup(tab.close)
state = tab._displayed_state
state.account_alias = "alias-a"
state.item_id = project.item_id
state.project_id = project.id
state.project_binding_state = project.binding_state
state.prompt = "原卖点"
tab._load_state(state)
template_text = prompts.load_product_suite_prompt(tab.product_suite_prompt_path)
specs = product_suite.build_job_specs(
assets,
state.prompt,
state.settings,
state.item_id,
template_text=template_text,
)
snapshot = tab._generation_plan_snapshot(state, assets, specs, template_text)
state.prompt = "已修改卖点"
with mock.patch.object(tab, "_confirm") as confirm:
started = tab._confirm_generation_price_request(
state,
assets,
specs,
"round-key",
snapshot,
None,
)
self.assertFalse(started)
confirm.assert_not_called()
self.assertIsNone(state.worker)
self.assert_removed(temp_dir)
def test_successful_history_requires_decision_before_new_generation(self):
with self.make_temp_dir() as temp_dir:
config = self._config(temp_dir)