自动高度 自定义高度:1920–30000px,默认 4500px 自定义高度会同步影响画布预览、任务快照、renderDocument、历史恢复和最终 PNG。若内容超过指定高度,系统会阻止导出并提示最低所需高度,不会静默裁掉底部内容。 关键修改: [PosterCreativePanel.vue (line 51)](D:/work/code/python/coding/baodanagent/frontend/src/components/poster/workspace/PosterCreativePanel.vue:51) [PosterHtmlCanvas.vue (line 1)](D:/work/code/python/coding/baodanagent/frontend/src/components/poster/long/PosterHtmlCanvas.vue:1) [poster-exporter.ts (line 95)](D:/work/code/python/coding/baodanagent/frontend/src/utils/poster-exporter.ts:95) [format_registry.py (line 17)](D:/work/code/python/coding/baodanagent/api/insurance/poster/format_registry.py:17) [render_validation.py (line 13)](D:/work/code/python/coding/baodanagent/api/insurance/poster/render_validation.py:13) 验证结果:33 项海报测试通过、Vue 类型检查通过、生产构建通过、UI 静态检查通过
121 lines
4.6 KiB
Python
121 lines
4.6 KiB
Python
"""海报 renderDocument v2 与模板兼容规则测试。"""
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT / "api"))
|
|
|
|
|
|
def test_render_document_uses_confirmed_case_facts_and_product_features():
|
|
from insurance.poster.format_registry import resolve_poster_format
|
|
from insurance.poster.render_document_builder import build_render_document
|
|
|
|
document = build_render_document(
|
|
format_spec=resolve_poster_format("single_2_3", output_mode="single"),
|
|
template={
|
|
"id": 9,
|
|
"layoutKey": "single_hero_data",
|
|
"colorScheme": {"primary": "#123456", "accent": "#c99040"},
|
|
},
|
|
copy_content={"headline": "确认后的标题", "body": "正文", "call_to_action": "咨询"},
|
|
case_facts={
|
|
"age": 35,
|
|
"annual_premium": 10000,
|
|
"benefit_table": [{"year": year, "total_surrender": year * 1000} for year in range(1, 8)],
|
|
},
|
|
product_rules={
|
|
"facts": {"age": 60},
|
|
"features": [{"title": f"卖点 {index}"} for index in range(5)],
|
|
},
|
|
plan_type="savings",
|
|
compliance_revision="revision-1",
|
|
)
|
|
|
|
assert document["schemaVersion"] == 2
|
|
assert document["facts"]["age"] == 35
|
|
assert document["summary"]["annual_premium"] == 10000
|
|
assert len(document["features"]) == 3
|
|
assert len(document["benefits"]) <= 1
|
|
assert document["theme"]["primary"] == "#123456"
|
|
assert document["layoutKey"] == "single_hero_data"
|
|
assert document["complianceRevision"] == "revision-1"
|
|
|
|
|
|
def test_render_document_long_mode_keeps_long_content_budget():
|
|
from insurance.poster.format_registry import resolve_poster_format
|
|
from insurance.poster.render_document_builder import build_render_document
|
|
|
|
document = build_render_document(
|
|
format_spec=resolve_poster_format("long_1242_auto", output_mode="long"),
|
|
template={"id": 1, "layoutKey": "long_complete", "colorScheme": {}},
|
|
copy_content={},
|
|
case_facts={"benefit_table": [{"year": year, "total_surrender": year * 1000} for year in range(1, 31)]},
|
|
product_rules={"features": [{"title": str(index)} for index in range(8)]},
|
|
plan_type="savings",
|
|
compliance_revision="",
|
|
)
|
|
|
|
assert document["outputMode"] == "long"
|
|
assert len(document["features"]) == 6
|
|
assert len(document["benefits"]) <= 6
|
|
assert next(item for item in document["sections"] if item["id"] == "benefits")["visible"] is True
|
|
|
|
|
|
def test_render_document_keeps_custom_long_height():
|
|
from insurance.poster.format_registry import resolve_poster_format
|
|
from insurance.poster.render_document_builder import build_render_document
|
|
|
|
document = build_render_document(
|
|
format_spec=resolve_poster_format("long_1242_auto", output_mode="long"),
|
|
template={},
|
|
copy_content={},
|
|
case_facts={},
|
|
product_rules={},
|
|
plan_type="other",
|
|
compliance_revision="",
|
|
custom_height=4500,
|
|
)
|
|
|
|
assert document["requestedOutput"] == {"width": 1242, "height": 4500}
|
|
assert document["exportSize"] == "1242x4500"
|
|
|
|
|
|
def test_template_mode_and_format_compatibility_is_explicit():
|
|
from insurance.models.poster_template_model import PosterTemplate
|
|
|
|
template = PosterTemplate(
|
|
name="单图模板",
|
|
style_description="稳健",
|
|
supported_modes=json.dumps(["single"]),
|
|
supported_formats=json.dumps(["single_2_3"]),
|
|
)
|
|
assert template.supports("single", "single_2_3")
|
|
assert not template.supports("long", "long_1242_auto")
|
|
|
|
|
|
def test_template_admin_rejects_mode_format_mismatch():
|
|
from insurance.admin.ppt_admin_service import _poster_compatibility_error
|
|
|
|
assert _poster_compatibility_error(["single"], ["single_2_3"]) is None
|
|
assert _poster_compatibility_error(["single"], ["long_1242_auto"])
|
|
|
|
|
|
def test_frontend_uses_dedicated_exporter_module():
|
|
page = (ROOT / "frontend/src/pages/PosterPage.vue").read_text(encoding="utf-8")
|
|
exporter = ROOT / "frontend/src/utils/poster-exporter.ts"
|
|
stage = (ROOT / "frontend/src/components/poster/workspace/PosterStage.vue").read_text(encoding="utf-8")
|
|
|
|
assert exporter.exists()
|
|
assert "renderPosterToBlob" in page
|
|
assert ':benefits="renderBenefits"' in stage
|
|
|
|
|
|
def test_render_document_loading_stays_in_poster_worker():
|
|
worker = (ROOT / "api/insurance/generation/celery_tasks.py").read_text(encoding="utf-8")
|
|
ppt_body, poster_body = worker.split("def _execute_poster_generate", maxsplit=1)
|
|
|
|
assert 'snapshot.get("renderDocument")' not in ppt_body
|
|
assert 'snapshot.get("renderDocument")' in poster_body
|
|
assert "record.document_json" in poster_body
|