baodan/docs/海报可编辑与参考图上传专项改造计划.md
2026-07-30 14:21:06 +08:00

495 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 海报单图/长图、文字可编辑与参考图上传精简计划
> - 文档版本v3.0
> - 编制日期2026-07-30
> - 目标:支持单张海报和长图海报,文字可直接修改,并可上传一张参考图
> - 预计工作量68 人日
---
## 一、结论
采用“AI 视觉图片 + HTML 内容模块”的拆分方式,可以达到参考样例的效果,而且比让图片模型一次生成整张长图更可靠。
正确流程是:
```text
计划书 + 产品小册子 + 可选参考图
→ 提取完整计划数据和产品卖点
→ 根据数据决定展示哪些内容模块
→ AI 只生成封面或结尾所需的无字视觉图
→ HTML 渲染标题、正文、数据卡、卖点、图表、Logo 和免责声明
→ 用户点击文字直接修改
→ 导出单张 PNG 或一张长图 PNG
```
不使用 Fabric.js不开发自由拖拽设计器也不做复杂图层系统。
---
## 二、参考样例分析
前两张样例尺寸约为 1536×3072属于 1:2 长图。它们不是一张普通海报简单拉长,而是由多个内容模块组成:
1. 品牌与封面主视觉;
2. 客户/投保人摘要;
3. 年缴保费、缴费期、累计投入、保障期限;
4. 现金价值或利益增长曲线;
5. 产品核心卖点;
6. 可选币种或产品选项;
7. 关键数据汇总;
8. 结尾主张、Logo 和免责声明。
第三张样例是更长的纵向模块列表,本质仍然是多个区块依次拼接。
样例中有三个不能交给图片模型的内容:
- 中文标题和正文:容易错字、乱码;
- 保险数字和图表:容易产生错误数字、错误坐标;
- Logo、图标和免责声明必须使用真实素材和确定性排版。
因此AI 只负责人物、城市、家庭、建筑、风景等视觉图;其他内容全部由 HTML、CSS、真实数据和图表组件生成。
---
## 三、两种输出模式
### 3.1 单张海报
建议尺寸:
- 1080×1440
- 1080×1920
- 1080×1080。
单图最多展示:
```text
封面视觉
标题和一句话说明
34 个关键数据
3 个核心卖点
行动号召
免责声明
```
单图适合朋友圈、私聊和快速宣传,信息必须精简。
### 3.2 长图海报
建议宽度固定为 1080高度根据内容自动计算常见范围为 21606000。
长图可展示:
```text
封面
客户专属计划
投入方案
利益增长图
产品亮点
保障/红利/提取选项
币种
关键数据
结尾
免责声明
```
长图不是让图片模型直接生成一张 1080×6000 的图片。图片模型通常只适合常见比例,直接生成超长图会出现:
- 内容密度失控;
- 中文和数字错误;
- 前后段视觉不连续;
- 无法修改文字;
- 图表和保险数据不可信;
- 超长尺寸不被供应商支持。
长图模式应生成 23 张无字视觉素材,例如:
- 封面主视觉;
- 中间过渡图,可选;
- 结尾主视觉。
其余区块使用 HTML 卡片、CSS 背景和图表组合。长图生成任务可以循环调用图片模型 23 次,而不是要求一次返回整张长图。
---
## 四、当前数据为什么不够
当前海报计划书解析使用:
```python
ExtractionOrchestrator.extract_for_poster()
```
该方法存在两个明确限制:
1. 只读取 PDF 文本前 6000 字符;
2. 只提取以下字段:
```text
age
gender
currency
sum_assured
premium_term
annual_premium
coverage_period
key_benefits
```
这些字段只能支撑:
- 投保年龄;
- 年缴保费;
- 缴费年期;
- 保额;
- 保障期限;
- 几个简短卖点。
它无法支撑:
- 利益增长曲线;
- 保证与非保证价值对比;
- 累计保费;
- 第 10/20/30 年关键数据;
- 回本年度;
- 红利和终期分红;
- 提取计划;
- 身故保障变化;
- 不同产品类型的专项内容。
当前产品小册子解析也只读取前 8000 字符,并只提取:
```text
product_name
features
currency_options
coverage_highlights
```
这会漏掉位于后续页面的红利锁定、保费假期、提取选项、币种转换、受益人安排、投保限制和免责声明。
因此,“提取数据过少”不是感觉问题,而是当前海报解析方法的设计目标本来就是低成本单张海报。
另外还有两个数据真实性隐患:
1. 旧上传表单预置了 35 岁、500,000 保额、5 年缴费、100,000 年缴保费等业务默认值。解析字段缺失时,默认值可能残留并被用户误认为解析结果。所有业务数字应初始化为 `null`,缺失时显示“待确认”,不能预填示例数字。
2. 完整储蓄险解析 Prompt 已提取 `sum_insured/basic_sum_insured`,但当前 `normalize_savings_plan()` 没有将它们写入归一化后的 `policy`。长图使用完整解析前,需要补回 `sumInsured``basicSumInsured`,否则关键数据卡仍可能缺少名义金额。
---
## 五、复用现有完整解析能力
项目的 PPT 模块已经存在更完整的:
```python
ExtractionOrchestrator.extract_plan()
```
它已经支持:
- PDF 全文规则提取;
- 储蓄险、重疾险、IUL 分类;
- 利益演示表逐年数据;
- 保证现金价值;
- 非保证利益、红利和终期分红;
- 总退保价值;
- 身故保障;
- 提取计划;
- 来源页码;
- 数据不完整时的 LLM 回退;
- 归一化数据结构。
海报模块不应继续扩充轻量的 `extract_for_poster()`,而应直接复用完整计划解析:
```text
上传计划书
→ extract_plan()
→ 保存完整结构化数据
→ PosterContentBuilder 根据输出模式挑选字段
→ 单图只取摘要
→ 长图使用摘要 + 关键年度 + 图表序列
```
这样 PPT 和海报共享一份计划书解析结果,不会出现同一份计划书在两个模块中数字不一致。
前端只需要让用户确认计划摘要和长图会使用的关键年度,不需要把几十行利益表全部铺成表单。完整利益表保存用于画图,确认区重点展示:
- 年龄、性别和吸烟状态;
- 币种、保额、年缴保费、缴费年期和保障期限;
- 第 10/20/30 年等关键利益值;
- 保证与非保证口径;
- 数据来源页;
- 缺失项和警告。
---
## 六、长图所需数据
### 6.1 计划书数据
计划书负责提供客户专属数字:
| 分类 | 最少字段 |
|------|----------|
| 客户 | 年龄、性别、吸烟状态(如有) |
| 保单 | 产品名称、币种、基本保额、年缴保费、缴费年期、保障期限 |
| 投入 | 年缴保费、累计总保费 |
| 利益表 | 保单年度、累计保费、保证现金价值、非保证利益、总退保价值、身故保障 |
| 提取 | 提取年度、提取金额、累计提取、提取后价值 |
| 来源 | 每个关键数字对应的 PDF 页码 |
长图不需要把几十行利益表全部显示出来,但画图时需要完整序列。关键数据卡可以选择第 10、20、30 年和期末数据。
### 6.2 产品小册子数据
小册子负责提供产品规则和卖点:
| 分类 | 最少字段 |
|------|----------|
| 产品定位 | 产品名称、产品类型、一句话定位 |
| 核心卖点 | 38 项标题、摘要和来源页 |
| 保障亮点 | 身故、危疾、预支或其他保障 |
| 红利机制 | 保证/非保证、红利锁定、终期分红等 |
| 灵活选项 | 提取、保费假期、币种转换、保单拆分等 |
| 币种 | 支持币种列表 |
| 投保规则 | 年龄、缴费期、保障期等 |
| 风险提示 | 非保证利益、汇率、退保损失等免责声明 |
小册子解析不能再简单截取前 8000 字符。应按关键词选择相关页面,例如:
```text
产品特色
保障
红利
终期分红
提取
保费假期
币种转换
受益人
投保年龄
风险
重要事项
```
从命中的页面中提取结构化内容,并保留来源页码。
---
## 七、长图模块生成规则
不是每份计划都强制展示所有模块。根据数据完整度自动决定:
| 模块 | 出现条件 |
|------|----------|
| 封面 | 始终出现 |
| 客户专属计划 | 年龄、币种、保费等摘要字段齐全 |
| 投入方案 | 年缴保费和缴费年期存在 |
| 利益增长图 | 至少有 3 个有效利益年度 |
| 提取计划 | 存在正式提取数据 |
| 产品亮点 | 小册子至少提取 3 个有效卖点 |
| 币种选择 | 至少有 2 种币种 |
| 关键数据 | 至少有 3 个可确认的关键指标 |
| 结尾与免责声明 | 始终出现 |
规则:
- 缺少数据就隐藏模块,不能让 AI 补数字;
- 数据不足 4 个有效模块时,建议生成单图,不强行拉成长图;
- 保证和非保证数据必须分开展示;
- 图表的每一个点来自利益演示表;
- 所有重要数字保留来源页码用于后台核对;
- 用户修改文字只能改表达,不能直接把已确认数字改成任意值。
---
## 八、HTML 海报结构
### 8.1 单图
```html
<article class="poster poster--single">
<PosterHero />
<PosterSummaryCards />
<PosterFeatureCards />
<PosterCallToAction />
<PosterDisclaimer />
</article>
```
### 8.2 长图
```html
<article class="poster poster--long">
<PosterHero />
<PosterCustomerPlan />
<PosterPremiumSummary />
<PosterBenefitChart />
<PosterFeatureList />
<PosterCurrencyOptions />
<PosterKeyMetrics />
<PosterClosing />
<PosterDisclaimer />
</article>
```
标题、说明和卖点文字使用 HTML可点击直接修改。数据卡和图表绑定结构化数据不允许 AI 在图片中绘制。
利益曲线可以复用现有 ECharts 依赖,导出前将图表转成图片或包含在 HTML 截图中。
Logo 使用后台真实 Logo 文件,图标使用本地 SVG 图标,不由 AI 生成。
---
## 九、参考图
首期支持上传一张参考图:
```text
POST /insurance/poster/reference-image
GET /insurance/poster/reference-image/{imageKey}
DELETE /insurance/poster/reference-image/{imageKey}
```
支持 JPG、PNG、WebP最大 10 MB。
参考图主要影响:
- 封面构图;
- 色彩和光线;
- 人物或场景方向;
- 长图中 23 张视觉图片的统一风格。
参考图不用于:
- 读取或复制其中的错误文字;
- 生成 Logo
- 生成保险数据和图表。
如果供应商不支持参考图,必须明确提示。参考图调用失败时不能静默忽略。
---
## 十、导出方式
### 单图
直接使用 `html-to-image` 将完整海报节点导出为 PNG。
### 长图
对于常见的 1080×21605000 长图,可以直接导出完整 HTML 节点。
对于高度更大的长图,为避免浏览器画布尺寸和内存问题:
1. 分别导出每个 HTML 模块;
2. 后端使用 Pillow 按顺序纵向拼接;
3. 返回一张最终长图 PNG。
这样最终仍是一张图片,但不要求浏览器或图片模型一次处理超高画布。
导出前必须等待:
- AI 视觉图加载完成;
- 中文字体加载完成;
- ECharts 图表渲染完成;
- 文字编辑状态退出。
---
## 十一、最小代码改造
### 后端
| 文件 | 修改 |
|------|------|
| `api/insurance/poster/tasks.py` | 计划书改用完整 `extract_plan()` |
| `api/insurance/poster/manual_parser.py` | 按关键页面提取更丰富的小册子内容 |
| `api/insurance/poster/content_builder.py` | 新增:把计划书和小册子数据变成单图/长图模块 |
| `api/insurance/poster/routes.py` | 参考图和长图导出接口 |
| `api/insurance/poster/image_generator.py` | 只生成无字视觉图 |
| `api/insurance/generation/celery_tasks.py` | 单图生成 1 张视觉图;长图生成 23 张 |
不新增复杂素材中心,不修改 BaoDan 基座。
### 前端
| 文件 | 修改 |
|------|------|
| `frontend/src/composables/usePosterWorkspace.ts` | 增加 `outputMode: single/long` 和参考图状态 |
| `frontend/src/utils/poster-api.ts` | 参考图、内容模块和导出接口 |
| `frontend/src/components/poster/workspace/PosterCreativePanel.vue` | 单图/长图选择和参考图上传 |
| `frontend/src/components/poster/workspace/PosterStage.vue` | 根据模式渲染 HTML 海报 |
| `frontend/src/components/poster/long/*` | 长图的 69 个小模块 |
| `frontend/src/pages/PosterPage.vue` | 文字保存和 PNG 导出 |
继续使用现有:
- `copy_content` 保存可编辑文案;
- `parsed_data` 保存完整解析结果;
- `confirmed_data` 保存人工确认数据;
- `draft_revision` 保存草稿版本;
- ECharts 绘制利益曲线。
---
## 十二、实施顺序与工期
### Phase 1完整数据复用1.52 人日)
- 海报计划书改用 `extract_plan()`
- 保存完整利益演示数据;
- 扩展小册子关键页面提取;
- 增加数据完整度检查。
验收:
- 能获取计划摘要和至少 3 个利益年度;
- 图表数据来自正式利益表;
- 产品卖点来自小册子并带来源页。
### Phase 2单图 HTML 海报11.5 人日)
- AI 只生成无字背景;
- HTML 显示标题、正文、数据卡和卖点;
- 文字可以点击修改;
- 单图 PNG 导出。
### Phase 3长图模板22.5 人日)
- 增加 `single/long` 选择;
- 增加客户计划、投入、图表、卖点、币种、关键数据和结尾模块;
- 根据数据自动隐藏无效模块;
- 长图生成 23 张统一风格的视觉素材;
- 长图 PNG 导出。
### Phase 4参考图与测试11.5 人日)
- 单张参考图上传、预览、更换和删除;
- 参考图传入视觉生成;
- 权限、文件类型和 EXIF 清理;
- 单图/长图端到端测试;
- 旧海报兼容测试。
总计约 68 人日。
---
## 十三、完成标准
- [ ] 用户可以选择单图或长图;
- [ ] 单图支持 1080×1440、1080×1920 和方图;
- [ ] 长图宽度固定、高度按有效模块自动计算;
- [ ] 长图由 HTML 模块组成,不由图片模型一次生成;
- [ ] AI 图片中不包含正式中文、数字、Logo 和图表;
- [ ] 标题和说明文字可以直接点击修改;
- [ ] 利益曲线来自完整计划书利益演示数据;
- [ ] 产品卖点来自小册子并保留来源;
- [ ] 数据不足时隐藏模块,不虚构内容;
- [ ] 用户可以上传一张参考图;
- [ ] 参考图失败不会被静默忽略;
- [ ] 单图和长图都能导出为一张 PNG
- [ ] 旧海报仍能预览和下载;
- [ ] 不开发自由拖拽和复杂图层系统;
- [ ] 不修改 BaoDan 基座代码。