自动高度 自定义高度: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 静态检查通过
110 lines
3.7 KiB
Python
110 lines
3.7 KiB
Python
"""构建海报预览、Prompt 与导出共同使用的 renderDocument v2。"""
|
|
from copy import deepcopy
|
|
|
|
from insurance.poster.content_builder import build_poster_content
|
|
|
|
|
|
DEFAULT_SECTIONS = (
|
|
"hero",
|
|
"summary",
|
|
"benefits",
|
|
"features",
|
|
"cta",
|
|
"disclaimer",
|
|
)
|
|
|
|
|
|
def build_render_document(
|
|
*,
|
|
format_spec: dict,
|
|
template: dict | None,
|
|
copy_content: dict,
|
|
case_facts: dict,
|
|
product_rules: dict,
|
|
plan_type: str,
|
|
compliance_revision: str,
|
|
custom_height: int | None = None,
|
|
sections: list[dict] | None = None,
|
|
brand: dict | None = None,
|
|
) -> dict:
|
|
"""按固定优先级组装唯一渲染文档。"""
|
|
template = template or {}
|
|
facts = deepcopy(case_facts or product_rules.get("facts") or {})
|
|
rules = deepcopy(product_rules or {})
|
|
if not rules.get("features") and facts.get("key_benefits"):
|
|
rules["features"] = [
|
|
{"title": item, "summary": ""} if isinstance(item, str) else item
|
|
for item in facts["key_benefits"]
|
|
]
|
|
|
|
content = build_poster_content(
|
|
parsed_data=facts,
|
|
product_rules=rules,
|
|
output_mode=format_spec["outputMode"],
|
|
plan_type=plan_type or "other",
|
|
)
|
|
theme = _build_theme(template.get("colorScheme") or {})
|
|
normalized_sections = _normalize_sections(sections, format_spec["outputMode"], content)
|
|
|
|
requested_output = deepcopy(format_spec["output"])
|
|
export_size = format_spec["exportSize"]
|
|
if custom_height is not None:
|
|
requested_output["height"] = custom_height
|
|
export_size = f"{requested_output['width']}x{custom_height}"
|
|
|
|
return {
|
|
"schemaVersion": 2,
|
|
"revision": 1,
|
|
"formatId": format_spec["id"],
|
|
"outputMode": format_spec["outputMode"],
|
|
"layoutKey": template.get("layoutKey") or (
|
|
"long_complete" if format_spec["outputMode"] == "long" else "single_hero_data"
|
|
),
|
|
"templateId": template.get("id"),
|
|
"layout": deepcopy(format_spec["layout"]),
|
|
"requestedOutput": requested_output,
|
|
"exportSize": export_size,
|
|
"copy": deepcopy(copy_content or {}),
|
|
"facts": facts,
|
|
"summary": content["summary"],
|
|
"features": content["features"],
|
|
"benefits": content["benefit_table"],
|
|
"theme": theme,
|
|
"style": theme,
|
|
"sections": normalized_sections,
|
|
"background": {},
|
|
"brand": deepcopy(brand or {}),
|
|
"fieldProfile": content["field_profile"],
|
|
"warnings": content["warnings"],
|
|
"complianceRevision": compliance_revision or "",
|
|
}
|
|
|
|
|
|
def _build_theme(color_scheme: dict) -> dict:
|
|
return {
|
|
"primary": color_scheme.get("primary") or "#173f35",
|
|
"accent": color_scheme.get("accent") or "#c99a4b",
|
|
"surface": color_scheme.get("surface") or "#f7f4ed",
|
|
"text": color_scheme.get("text") or "#17231f",
|
|
"muted": color_scheme.get("muted") or "#64716d",
|
|
}
|
|
|
|
|
|
def _normalize_sections(sections: list[dict] | None, output_mode: str, content: dict) -> list[dict]:
|
|
current = {
|
|
item.get("id"): item.get("visible", True)
|
|
for item in (sections or [])
|
|
if isinstance(item, dict) and item.get("id") in DEFAULT_SECTIONS
|
|
}
|
|
result = []
|
|
for section_id in DEFAULT_SECTIONS:
|
|
visible = current.get(section_id, True)
|
|
if section_id == "benefits":
|
|
visible = visible and output_mode == "long" and len(content["benefit_table"]) >= 3
|
|
elif section_id == "features":
|
|
visible = visible and bool(content["features"])
|
|
elif section_id == "summary":
|
|
visible = visible and any(content["summary"].values())
|
|
result.append({"id": section_id, "visible": visible})
|
|
return result
|