baodan/docs/海报生成工作台完整重构修复计划.md
wsb1224 29657d31e4 所有阶段 3-5 的任务全部完成。最终盘点:
全部改动文件总览
后端(8 个文件)
文件	操作
api/insurance/models/ppt_session.py	修改 — 新增 5 个字段
api/insurance/db/migrate_025.py	新建 — 数据库迁移
api/insurance/ppt/renderer.py	修改 — 新增 parse_slides(),deck 返回
api/insurance/ppt/quality_checker.py	新建 — 质量检查
api/insurance/ppt/routes.py	修改 — 新增 5 个接口
api/insurance/generation/celery_tasks.py	修改 — 集成预览+质检+版本化,新增 regenerate 任务
api/insurance/generation/task_service.py	修改 — 注册 regenerate 任务
前端(8 个文件)
文件	操作
frontend/src/utils/ppt-api.ts	修改 — 新增类型和 API 方法
frontend/src/pages/components/ppt/PptSlideCanvas.vue	新建 — Canvas 渲染器
frontend/src/pages/components/ppt/PptResult.vue	重写 — 三栏工作台 + 版本历史
frontend/src/pages/components/ppt/PptUpload.vue	重写 — 双栏 Hero 布局
frontend/src/pages/components/ppt/PptParsing.vue	重写 — 五阶段进度
frontend/src/pages/components/ppt/PptDataReview.vue	修改 — 主题色更新
frontend/src/pages/PptPage.vue	修改 — 步骤描述 + 主题色
frontend/src/pages/PptHistoryPage.vue	重写 — 卡片式布局
新增后端接口
方法	路径	功能
GET	/ppt/preview/:id	获取幻灯片 JSON + 质量报告 + 版本历史
PUT	/ppt/preview/:id/slide/:index	更新编辑内容 + 显隐
PUT	/ppt/preview/:id/quality-confirm	人工质量确认
POST	/ppt/preview/:id/regenerate	基于编辑生成新版本
2026-07-29 22:14:02 +08:00

1898 lines
65 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.

# 海报生成工作台完整重构修复计划
> - **文档版本**v1.0
> - **编制日期**2026-07-29
> - **适用范围**`api/insurance/poster/`、`api/insurance/generation/`、`frontend/src/pages/Poster*`、`frontend/src/components/poster/`
> - **实施状态**:待开发
> - **优先级**P0/P1
> - **预计工作量**:约 24.5 人日,建议预留 20% 风险缓冲
---
## 一、文档目的
本计划用于把现有“选择后台产品和模板、生成文案、输出单张 PNG”的海报功能重构为完整的保险营销内容生产工作台
```text
创建项目
→ 选择后台产品或上传产品小册子
→ 上传客户计划书和参考素材
→ 异步解析
→ 数据底表 / 来源审计 / QA 校验
→ 人工确认
→ AI 生成视觉方案和文案
→ 生成可编辑画布
→ 人工编辑与版本保存
→ PNG / JPG / PDF / 项目源文件导出
→ 任务、历史、配置版本和审计记录同步到后台
```
本文是海报模块二期重构的执行基线。当本文与以下旧文档的“海报”部分冲突时,以本文为准;旧文档中的 PPT 整改内容继续有效:
- `PPT与海报功能完整解决方案.md`
- `PPT与海报功能开发任务清单.md`
- `PPT与海报功能问题整改计划.md`
---
## 二、目标、边界与关键假设
### 2.1 建设目标
| 编号 | 目标 | 成功标准 |
|------|------|----------|
| G-01 | 用户可自由提供本次创作资料 | 计划书 PDF、产品小册子 PDF、参考图片均可直接上传 |
| G-02 | 后台产品库不再是唯一入口 | 用户可从产品库选择,也可仅在当前项目使用临时小册子 |
| G-03 | AI 生成与内容相符的视觉素材 | AI 根据客户、产品、场景、品牌约束生成 24 个真实视觉候选 |
| G-04 | 文字和数字不烘焙进 AI 图片 | 标题、卖点、数字、图表、Logo、免责声明均为独立画布图层 |
| G-05 | 生成前完成真实数据校验 | 每个关键事实可追溯到文件、页码和原文;错误项阻断生成 |
| G-06 | 生成结果可继续编辑 | 支持选择、移动、缩放、改字、换图、图层、撤销重做和自动保存 |
| G-07 | 支持多格式交付 | 首期支持 PNG、JPG、PDF、项目源文件 |
| G-08 | 全链路与后台同步 | 项目、素材、校验、任务、画布版本、导出物和配置快照可恢复、可审计 |
| G-09 | 保持 BaoDan 升级安全 | 自研实现全部位于 `api/insurance/` 和独立 `frontend/` 项目 |
### 2.2 不在本期范围
以下能力不进入首期 P0/P1避免海报编辑器无限扩张
- 多人同时在线协作编辑;
- 类 Photoshop 的像素级蒙版、钢笔和滤镜系统;
- 视频海报、GIF、动画海报
- 任意第三方字体商城;
- 用户自定义脚本或 HTML
- 社交平台自动发布;
- SVG 正式交付;完成兼容性验证后作为 P2
- 手机端进行精细拖拽排版。
### 2.3 默认产品假设
| 决策 | 默认方案 | 原因 |
|------|----------|------|
| 编辑器主要设备 | 桌面端和大屏平板 | 精细排版不适合手机单手操作 |
| 手机端范围 | 上传、校验、任务查看、预览、基础文字/图片替换 | 保证移动业务连续性,不承诺精细排版 |
| 画布技术 | Fabric.js | 具备文本编辑、对象模型、图层、JSON 序列化和图片导出能力 |
| AI 图片职责 | 生成背景、人物、场景、装饰素材 | 避免 AI 中文和保险数字错误 |
| 画布职责 | 组合图片、文字、数字、图表、Logo、免责声明 | 保证可编辑、可审计、可重复导出 |
| 数据主对象 | 继续使用 `PosterRecord` | 已具备工作区、版本和任务字段,避免新建重复项目表 |
| 任务系统 | 继续使用 `GenerationTask` + BaoDan Celery | 不重复建设队列和状态系统 |
| 首期导出 | PNG、JPG、PDF、项目 JSON | 覆盖朋友圈、私聊、打印和继续编辑 |
---
## 三、当前基线与必须修复的问题
### 3.1 已有能力
| 能力 | 现状 | 处理策略 |
|------|------|----------|
| 计划书 PDF 上传 | 已实现真实 multipart 上传 | 保留并迁移到项目素材模型 |
| PDF 基础安全检查 | 已检查大小、魔数、加密和页数 | 保留并扩展到所有项目素材 |
| 异步解析 | 已接入 Celery 和任务状态 | 保留,统一为项目级解析任务 |
| 人工修正解析结果 | 前端已有表单 | 重构为事实表和来源审计 |
| AI 文案 | 已支持模板/AI 双模式 | 保留,限制只能引用已确认事实 |
| AI 图片 | 已调用图片模型 | 改为“视觉素材生成”,不直接生成带字成品 |
| 工作区恢复 | 已支持 URL 恢复部分状态 | 扩展为完整项目恢复 |
| 统一任务中心 | 已有 `GenerationTask` | 增加海报细分操作类型和任务快照 |
| 海报历史 | 已有分页、预览和下载 | 重构为项目历史和导出物列表 |
| 后台模板和模型设置 | 已使用数据库配置 | 增加版本号和任务提交时快照 |
### 3.2 P0 阻断问题
| 编号 | 问题 | 影响 | 修复阶段 |
|------|------|------|----------|
| POSTER2-P0-01 | Worker 保存到 `outputs/posters`,下载接口只允许 `uploads/posters` | 生成成功仍可能无法预览或下载 | Phase 0 |
| POSTER2-P0-02 | 用户不能上传产品小册子 | 新产品、临时资料无法开始创作 | Phase 2 |
| POSTER2-P0-03 | `confirmedData` 缺少后端 Schema 和业务校验 | 错误保险数字可进入生成 | Phase 2 |
| POSTER2-P0-04 | 生成结果不可编辑 | 无法满足修正文案、版式和图片要求 | Phase 4 |
| POSTER2-P0-05 | 只有 PNG 导出 | 无法满足打印、图片质量和继续编辑 | Phase 5 |
### 3.3 P1 主要问题
| 编号 | 问题 | 影响 | 修复阶段 |
|------|------|------|----------|
| POSTER2-P1-01 | AI 图片仍受固定背景模板思维支配 | 与客户、产品和场景的语义匹配不足 | Phase 3 |
| POSTER2-P1-02 | 前后端尺寸值不一致 | 横版、方图可能回退为竖版 | Phase 0 |
| POSTER2-P1-03 | 生成失败时工作区和任务状态可能不一致 | 页面可能永久停留在生成中 | Phase 0 |
| POSTER2-P1-04 | 参考图以 URL/字符串传递 | 无真实上传、权限和生命周期管理 | Phase 2 |
| POSTER2-P1-05 | 生成前绿色核对项不是实际校验 | 制造虚假合规感 | Phase 2 |
| POSTER2-P1-06 | 任务中心和历史记录职责重叠 | 用户无法区分“运行任务”和“可继续编辑项目” | Phase 6 |
| POSTER2-P1-07 | 后台配置没有提交时版本快照 | 无法证明成品使用了哪一版配置 | Phase 1、6 |
| POSTER2-P1-08 | 重新生成会覆盖用户心智中的当前结果 | 缺少候选方案和版本回退 | Phase 3、4 |
---
## 四、目标产品流程与信息架构
### 4.1 页面结构
```text
/poster
├── 新建项目
├── 最近项目
└── 运行中的任务摘要
/poster/:projectId
├── 1. 项目资料
├── 2. 数据校验
├── 3. 创意方案
├── 4. 画布编辑
└── 5. 导出发布
/poster/:projectId/editor
└── 全屏画布编辑器
/poster/history
├── 进行中
├── 已完成
├── 已归档
└── 项目版本 / 导出物
/tasks?artifact_type=poster
└── 只展示解析、AI 生成、合成、导出等运行任务
```
### 4.2 五阶段业务流程
#### 阶段 1项目资料
用户可以任选一种产品资料来源:
1. 从后台已审核产品库选择;
2. 上传本次使用的产品小册子 PDF
3. 选择后台产品后,再上传补充小册子覆盖本次项目。
本阶段素材区域包括:
- 客户计划书 PDF必需
- 产品小册子 PDF选择后台产品时可选否则必需
- 参考图片:可选,最多 6 张;
- Logo/品牌素材:默认从后台保司配置读取,可临时覆盖;
- PDF 密码:仅用于本次解密,不落库。
每个素材显示:
- 原始文件名;
- 文件类型和大小;
- 页数或图片尺寸;
- 上传时间;
- 解析状态;
- 来源:后台库 / 用户上传 / AI 生成;
- 替换、删除和重新解析操作。
#### 阶段 2数据校验
本阶段使用三个标签页:
| 标签页 | 内容 | 目的 |
|--------|------|------|
| 数据底表 | 规范化字段、解析值、确认值、单位 | 集中编辑事实 |
| 来源审计 | 文件、页码、原文片段、置信度 | 证明数据来自哪里 |
| QA 校验 | 错误、警告、通过项 | 决定是否允许生成 |
状态规则:
```text
unreviewed → passed
→ warning → accepted
→ error → fixed → passed
```
- 存在 `error`:禁止进入创意方案;
- 存在 `warning`:用户必须逐项接受或修正;
- 所有必填事实 `passed/accepted`:记录确认人和时间,允许生成;
- 源文件替换或重新解析:原确认版本失效,必须重新校验。
#### 阶段 3创意方案
用户填写或选择视觉简报:
- 使用场景:朋友圈、客户私聊、讲座邀请、产品提案、长图说明;
- 目标客群:年龄、家庭阶段、职业、关注点;
- 核心主题:保障、增值、传承、教育、退休等;
- 情绪方向:稳健、温暖、高端、现代、自然;
- 视觉主体:人物、家庭、住宅、城市、自然、抽象金融意象;
- 摄影/插画风格;
- 品牌颜色;
- 禁用元素;
- 参考图片;
- 输出尺寸和画布类型。
生成过程:
1. 系统从已确认事实生成受约束文案;
2. 系统生成 24 个不含文字、Logo 和数字的视觉候选;
3. 候选图展示生成理由、风格标签和使用的简报;
4. 用户选中一个候选,或只重新生成某个候选;
5. 系统使用版式预设生成初始画布 JSON。
#### 阶段 4画布编辑
全屏工作台布局:
```text
┌──────────────── 顶部工具栏 ────────────────┐
│ 返回 / 保存状态 / 撤销 / 重做 / 缩放 / 预览 / 导出 │
├──────────┬──────────────────────┬───────────┤
│ 页面与素材 │ 可编辑画布 │ 图层与属性 │
│ AI 候选图 │ │ 数据来源 │
│ 品牌素材 │ │ QA 状态 │
└──────────┴──────────────────────┴───────────┘
```
首期必须支持:
- 文字直接编辑;
- 字体、字号、行高、字间距、颜色、对齐;
- 图片替换、裁剪、缩放、定位;
- 矩形、线条、背景色;
- 数据卡、图标、Logo、免责声明
- 图层显示、隐藏、锁定、排序;
- 多选、对齐、吸附和安全区;
- 撤销、重做;
- 自动保存;
- 版本历史和恢复;
- 单独重新生成选中的 AI 图片;
- 根据事实数据重新生成文案;
- 事实字段变更后标记关联图层“数据已过期”。
#### 阶段 5导出发布
导出面板提供:
| 格式 | 用途 | 首期要求 |
|------|------|----------|
| PNG | 朋友圈、企微、网页 | 支持 1x/2x透明背景按画布能力决定 |
| JPG | 体积较小的图片分发 | 可选质量 80/90/100 |
| PDF | 打印、客户存档 | 单页海报或多页长图分页 |
| 项目 JSON | 继续编辑、备份迁移 | 包含画布 Schema 版本,不嵌入密钥和临时 URL |
每个导出物记录:
- 使用的画布版本;
- 使用的事实确认版本;
- 配置快照版本;
- 文件格式、尺寸、大小和 MIME
- 导出人和导出时间;
- 下载次数;
- 是否为正式交付版。
---
## 五、总体技术架构
### 5.1 架构原则
1. `PosterRecord` 继续作为项目/工作区根对象,不重命名数据库表;
2. `GenerationTask` 继续作为一次异步执行记录;
3. 文件统一保存到 `INSURANCE_STORAGE_ROOT`
4. 数据库保存对象键,不保存依赖工作目录的绝对路径;
5. AI 生成图片与确定性文字排版分离;
6. 画布 JSON 是可编辑成品的唯一事实来源;
7. PNG/JPG/PDF 是画布某一版本的不可变导出物;
8. 所有模型、Prompt、品牌和模板配置在任务提交时生成快照。
### 5.2 数据流
```mermaid
flowchart LR
U["用户上传 / 后台产品库"] --> A["项目素材"]
A --> P["Celery 解析任务"]
P --> F["事实与来源证据"]
F --> V["规则校验 + 人工确认"]
V -->|通过| B["创意简报"]
B --> C["文案生成"]
B --> I["AI 视觉候选"]
C --> K["初始画布构建"]
I --> K
K --> E["Fabric.js 编辑器"]
E --> S["画布版本保存"]
S --> X["PNG / JPG / PDF / 项目文件"]
X --> H["项目历史和后台审计"]
```
### 5.3 AI 与画布职责边界
| 内容 | AI 图片模型 | LLM | 画布引擎 |
|------|:-----------:|:---:|:--------:|
| 人物、家庭、建筑、自然场景 | ✅ | | 组合 |
| 装饰纹理、氛围背景 | ✅ | | 组合 |
| 标题和正文文案 | | ✅ | ✅ 可编辑 |
| 保费、保额、缴费期等数字 | | 只能引用事实 | ✅ 可编辑 |
| 图表 | | 生成结构建议 | ✅ 确定性绘制 |
| Logo | 禁止生成 | | ✅ 使用真实素材 |
| 免责声明 | 禁止生成 | 规则选择 | ✅ 固定图层 |
---
## 六、数据库与迁移设计
### 6.1 迁移策略
- 新迁移编号从 `migrate_026.py` 开始;
- 不删除现有字段和表;
-`PosterRecord` 自动视为一个项目;
- 旧 PNG 作为历史导出物回填;
-`PosterCaseUpload` 保留兼容读取;
- 新流程稳定两个版本后再评估旧字段清理;
- 所有迁移必须幂等并支持 PostgreSQL/MySQL 的现有兼容策略。
### 6.2 扩展 `poster_records`
继续作为海报项目根对象,新增字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `validation_status` | VARCHAR(20) | pending/running/blocked/warning/passed |
| `validation_summary_json` | TEXT | 错误、警告、通过数量和确认版本 |
| `creative_brief_json` | TEXT | 用户创意简报 |
| `selected_visual_asset_id` | BIGINT | 选中的 AI 视觉素材 |
| `canvas_schema_version` | VARCHAR(20) | 画布 Schema 版本 |
| `current_canvas_version` | INTEGER | 当前画布版本号 |
| `config_snapshot_json` | TEXT | 模型、Prompt、模板、品牌配置快照 |
| `fact_revision` | INTEGER | 事实数据版本 |
| `confirmed_fact_revision` | INTEGER | 最近确认的事实版本 |
| `updated_at` | TIMESTAMP | 项目最后更新时间 |
保留但调整语义:
- `template_id`:从固定背景模板改为版式/品牌预设;
- `copy_content`:当前文案图层内容;
- `export_url/export_format`:兼容旧接口,指向最近正式导出物;
- `workflow_step`:改用 `sources/validation/creative/editor/export`
- `draft_revision/generated_revision`:继续用于乐观锁和生成版本判断。
### 6.3 新建 `poster_project_assets`
用途统一保存本项目所有输入、AI 候选和品牌素材。
| 字段 | 类型 | 约束/说明 |
|------|------|-----------|
| `id` | BIGINT | 主键 |
| `project_id` | BIGINT | INDEX关联 `poster_records.id` |
| `user_id` | VARCHAR(64) | INDEX所有权校验 |
| `asset_type` | VARCHAR(30) | case_pdf/product_manual/reference/brand/generated_visual |
| `source_type` | VARCHAR(20) | upload/library/generated |
| `source_ref_id` | VARCHAR(64) | 后台产品或保司素材 ID |
| `file_key` | VARCHAR(500) | storage 对象键 |
| `original_name` | VARCHAR(200) | 原始文件名 |
| `mime_type` | VARCHAR(80) | MIME |
| `file_size` | BIGINT | 字节 |
| `sha256` | VARCHAR(64) | 去重和审计 |
| `page_count` | INTEGER | PDF 页数 |
| `width` / `height` | INTEGER | 图片尺寸 |
| `parse_status` | VARCHAR(20) | pending/queued/parsing/parsed/failed |
| `parse_task_id` | VARCHAR(36) | 关联 `GenerationTask` |
| `metadata_json` | TEXT | EXIF 清理、候选理由、模型信息等 |
| `created_at` | TIMESTAMP | 创建时间 |
| `deleted_at` | TIMESTAMP | 软删除 |
索引:
- `INDEX(project_id, asset_type)`
- `INDEX(user_id, created_at)`
- `INDEX(sha256)`
### 6.4 新建 `poster_fact_items`
用途:保存结构化事实、来源证据和人工确认结果。
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | BIGINT | 主键 |
| `project_id` | BIGINT | INDEX |
| `fact_revision` | INTEGER | 所属事实版本 |
| `fact_path` | VARCHAR(120) | 如 `customer.age`、`policy.annual_premium` |
| `label` | VARCHAR(100) | 用户可读字段名 |
| `value_json` | TEXT | 系统解析值 |
| `confirmed_value_json` | TEXT | 人工确认值 |
| `unit` | VARCHAR(30) | USD、HKD、年、岁等 |
| `source_asset_id` | BIGINT | 来源素材 |
| `source_page` | INTEGER | PDF 页码 |
| `source_quote` | TEXT | 原文片段,限制长度 |
| `confidence` | DECIMAL(5,4) | 解析置信度 |
| `validation_status` | VARCHAR(20) | unreviewed/passed/warning/error/accepted |
| `validation_code` | VARCHAR(50) | 结构化规则码 |
| `validation_message` | VARCHAR(500) | 用户可读说明 |
| `confirmed_by` | VARCHAR(64) | 确认人 |
| `confirmed_at` | TIMESTAMP | 确认时间 |
| `created_at` / `updated_at` | TIMESTAMP | 时间字段 |
唯一约束:
- `UNIQUE(project_id, fact_revision, fact_path)`
### 6.5 新建 `poster_canvas_versions`
用途:保存可编辑画布版本,支持自动保存、版本恢复和审计。
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | BIGINT | 主键 |
| `project_id` | BIGINT | INDEX |
| `version` | INTEGER | 项目内递增版本 |
| `canvas_schema_version` | VARCHAR(20) | 如 `1.0` |
| `canvas_json` | TEXT | Fabric 画布文档 |
| `preview_file_key` | VARCHAR(500) | 低分辨率预览 |
| `fact_revision` | INTEGER | 使用的事实版本 |
| `config_snapshot_json` | TEXT | 使用的配置快照 |
| `source_task_id` | VARCHAR(36) | 初始合成任务 ID |
| `change_summary` | VARCHAR(500) | 自动保存/人工保存/恢复等 |
| `created_by` | VARCHAR(64) | 操作人 |
| `created_at` | TIMESTAMP | 创建时间 |
唯一约束:
- `UNIQUE(project_id, version)`
版本策略:
- 自动保存更新当前草稿,不为每次按键创建永久版本;
- 用户点击“保存版本”、生成初稿、导出正式版时创建永久版本;
- 每个项目默认保留最近 30 个永久版本;
- 被导出物引用的版本不得自动清理。
### 6.6 新建 `poster_export_artifacts`
用途:保存同一画布版本的多格式导出物。
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | BIGINT | 主键 |
| `project_id` | BIGINT | INDEX |
| `canvas_version_id` | BIGINT | 关联画布版本 |
| `task_id` | VARCHAR(36) | 导出任务,可为空 |
| `format` | VARCHAR(20) | png/jpg/pdf/project_json |
| `file_key` | VARCHAR(500) | storage 对象键 |
| `mime_type` | VARCHAR(80) | MIME |
| `width` / `height` | INTEGER | 像素尺寸 |
| `dpi` | INTEGER | PDF/打印参数 |
| `file_size` | BIGINT | 文件大小 |
| `status` | VARCHAR(20) | queued/ready/failed |
| `is_official` | BOOLEAN | 是否正式交付版本 |
| `download_count` | INTEGER | 下载次数 |
| `created_by` | VARCHAR(64) | 导出人 |
| `created_at` | TIMESTAMP | 创建时间 |
### 6.7 扩展 `insurance_generation_tasks`
修改:
- `operation``VARCHAR(10)` 扩展到 `VARCHAR(30)`
- 支持以下操作值:
- `parse_sources`
- `validate_facts`
- `generate_copy`
- `generate_visuals`
- `compose_canvas`
- `export_artifact`
- `input_snapshot_json` 必须包含配置版本和输入修订号;
- `output_json` 保存生成素材 ID、画布版本或导出物 ID
- 失败时同步更新项目或素材状态;
- 增加结构化 `error_code`,禁止只保存异常字符串。
### 6.8 旧数据回填
迁移 026 完成:
1. 为现有 `poster_records` 填充:
- `validation_status='passed'`,并标记 `legacy=true`
- `canvas_schema_version=NULL`
- `current_canvas_version=0`
2. 将现有 `case_upload_id` 对应文件注册为 `case_pdf` 素材;
3. 将现有 `reference_image_used` 注册为参考素材;文件不存在时只记录迁移警告;
4. 将现有 `export_url` 注册为 `poster_export_artifacts`
5. 旧项目仍可预览和下载,但只有点击“转换为可编辑项目”后才生成画布;
6. 回填过程输出成功、跳过、文件缺失和异常数量。
---
## 七、后端 API 设计
### 7.1 兼容策略
- 保留现有 `/poster/products`、`/poster/records`、`/poster/download/{id}`
- 新页面优先调用工作区接口;
- 旧生成向导通过功能开关保留一个发布周期;
- 新接口统一返回:
```json
{
"code": 0,
"message": "success",
"data": {}
}
```
### 7.2 项目接口
| 方法 | URL | 用途 |
|------|-----|------|
| POST | `/insurance/poster/workspaces` | 创建空项目 |
| GET | `/insurance/poster/workspaces` | 查询本人项目 |
| GET | `/insurance/poster/workspaces/{id}` | 获取完整项目摘要 |
| PATCH | `/insurance/poster/workspaces/{id}/draft` | 自动保存步骤、简报和草稿 |
| PUT | `/insurance/poster/workspaces/{id}/rename` | 重命名 |
| POST | `/insurance/poster/workspaces/{id}/copy` | 复制项目 |
| PUT | `/insurance/poster/workspaces/{id}/archive` | 归档 |
| PUT | `/insurance/poster/workspaces/{id}/unarchive` | 取消归档 |
创建项目请求示例:
```json
{
"title": "宏挚传承保障计划|客户 A",
"useMaskedData": true
}
```
### 7.3 素材接口
| 方法 | URL | 用途 |
|------|-----|------|
| POST | `/poster/workspaces/{id}/assets` | 上传 PDF/图片 |
| GET | `/poster/workspaces/{id}/assets` | 素材列表 |
| DELETE | `/poster/workspaces/{id}/assets/{assetId}` | 软删除素材 |
| POST | `/poster/workspaces/{id}/products/attach` | 关联后台产品 |
| POST | `/poster/workspaces/{id}/parse` | 投递项目解析任务 |
| POST | `/poster/workspaces/{id}/assets/{assetId}/retry` | 重试单个素材解析 |
上传表单字段:
| 字段 | 必填 | 说明 |
|------|:----:|------|
| `assetType` | 是 | case_pdf/product_manual/reference/brand |
| `file` | 是 | 文件 |
| `password` | 否 | PDF 密码,不保存 |
| `replaceAssetId` | 否 | 替换指定素材 |
### 7.4 事实与校验接口
| 方法 | URL | 用途 |
|------|-----|------|
| GET | `/poster/workspaces/{id}/facts` | 获取当前事实版本 |
| PATCH | `/poster/workspaces/{id}/facts/{factId}` | 修改单个事实 |
| PUT | `/poster/workspaces/{id}/facts` | 批量保存事实 |
| POST | `/poster/workspaces/{id}/validate` | 执行服务端校验 |
| POST | `/poster/workspaces/{id}/warnings/{factId}/accept` | 接受警告 |
| POST | `/poster/workspaces/{id}/validation/confirm` | 确认当前事实版本 |
| GET | `/poster/workspaces/{id}/source-audit` | 获取来源审计视图 |
确认接口必须检查:
- 请求事实版本等于项目当前版本;
-`error`
- 所有必填事实存在来源或有人工补录原因;
- 所有 `warning` 已处理;
- 请求用户拥有项目;
- 确认动作写审计日志。
### 7.5 创意与 AI 接口
| 方法 | URL | 用途 |
|------|-----|------|
| PUT | `/poster/workspaces/{id}/creative-brief` | 保存创意简报 |
| POST | `/poster/workspaces/{id}/copy/generate` | 生成受约束文案 |
| POST | `/poster/workspaces/{id}/visuals/generate` | 生成 24 个视觉候选 |
| GET | `/poster/workspaces/{id}/visuals` | 获取候选素材 |
| POST | `/poster/workspaces/{id}/visuals/{assetId}/select` | 选中候选 |
| POST | `/poster/workspaces/{id}/visuals/{assetId}/regenerate` | 重新生成指定候选 |
| POST | `/poster/workspaces/{id}/canvas/compose` | 生成初始画布 |
所有生成接口必须:
- 校验 `validation_status='passed'`
- 固化事实版本、配置版本和画布输入版本;
- 使用幂等键;
- 3 秒内返回任务 ID
- 不等待图片模型完成;
- 可通过统一任务接口恢复状态。
### 7.6 画布接口
| 方法 | URL | 用途 |
|------|-----|------|
| GET | `/poster/workspaces/{id}/canvas` | 获取当前画布 |
| PATCH | `/poster/workspaces/{id}/canvas` | 自动保存草稿,带乐观锁 |
| POST | `/poster/workspaces/{id}/canvas/versions` | 创建永久版本 |
| GET | `/poster/workspaces/{id}/canvas/versions` | 版本列表 |
| POST | `/poster/workspaces/{id}/canvas/versions/{version}/restore` | 恢复版本 |
| POST | `/poster/workspaces/{id}/canvas/preview` | 上传低清预览 |
自动保存请求:
```json
{
"expectedRevision": 12,
"canvasSchemaVersion": "1.0",
"canvas": {
"width": 1080,
"height": 1920,
"objects": []
}
}
```
版本冲突返回明确错误和服务器最新版本,不静默覆盖。
### 7.7 导出接口
| 方法 | URL | 用途 |
|------|-----|------|
| POST | `/poster/workspaces/{id}/exports` | 创建导出物记录或导出任务 |
| GET | `/poster/workspaces/{id}/exports` | 导出物列表 |
| GET | `/poster/exports/{artifactId}/download` | 鉴权下载 |
| PUT | `/poster/exports/{artifactId}/official` | 标记正式交付版本 |
| DELETE | `/poster/exports/{artifactId}` | 删除非正式导出物 |
首期采用浏览器高分辨率画布导出,再通过鉴权接口上传成品:
1. 前端加载已保存画布版本;
2. 在隐藏高分辨率画布渲染;
3. PNG/JPG 使用 `toBlob`
4. PDF 将高分辨率画布按页面尺寸嵌入 PDF
5. 上传到后端;
6. 后端校验项目所有权、格式、MIME、大小和画布版本
7. 文件写入统一 storage
8. 创建不可变导出物记录。
后续若需要服务端批量导出,再增加独立渲染 Worker不在首期重复建设。
---
## 八、后端模块改造
### 8.1 建议目录
```text
api/insurance/poster/
├── routes.py # 兼容旧接口
├── service.py # 兼容旧业务
├── project_routes.py # 项目、素材、画布、导出
├── project_service.py # 项目聚合服务
├── asset_service.py # 文件与素材生命周期
├── extraction_service.py # 多资料解析编排
├── fact_schema.py # Pydantic/Schema
├── validation_service.py # 事实与业务规则校验
├── source_audit_service.py # 来源证据
├── creative_service.py # 创意简报和文案约束
├── visual_generator.py # AI 视觉候选
├── canvas_builder.py # 确定性初始画布 JSON
├── export_service.py # 导出物接收、校验和存储
├── storage_service.py # 项目文件路径安全封装
└── schemas/
├── canvas_v1.py
├── creative_brief.py
└── insurance_facts.py
```
说明:
- 不一次性拆分现有所有函数;
-`routes.py/service.py` 保持兼容;
- 新逻辑放独立文件;
- 迁移完成后逐个旧接口转调新服务;
- 不修改 BaoDan 核心模块。
### 8.2 解析编排
解析任务输入:
- 项目 ID
- case PDF 素材 ID
- product manual 素材 ID 或后台产品快照;
- 当前事实版本;
- 模型配置快照。
解析任务输出:
- 标准事实列表;
- 每个事实的来源文件、页码、原文和置信度;
- 未识别字段;
- 冲突字段;
- 解析错误。
PDF 文本必须作为“不可信数据”传给模型,防止文档中的提示注入覆盖系统指令。
### 8.3 事实 Schema
首期核心事实:
```text
customer.age
customer.gender
customer.smoking_status
policy.product_name
policy.company_name
policy.currency
policy.sum_assured
policy.annual_premium
policy.payment_period
policy.coverage_period
policy.total_basic_premium
policy.cash_value.*
policy.death_benefit.*
product.features[]
product.exclusions[]
product.disclaimer
```
不同险种通过 Schema 配置决定必填字段,不强行让所有险种共用完全相同的字段。
### 8.4 校验规则
| 规则码 | 类型 | 规则 |
|--------|------|------|
| REQUIRED_FIELD_MISSING | error | 必填字段缺失 |
| SOURCE_EVIDENCE_MISSING | error | 关键数字无文件、页码或人工补录说明 |
| PRODUCT_NAME_CONFLICT | error | 计划书与产品册产品名无法匹配 |
| CURRENCY_CONFLICT | error | 同一关键金额存在不同币种 |
| PAYMENT_PERIOD_CONFLICT | error | 缴费期在资料间冲突 |
| PREMIUM_OUT_OF_RANGE | warning/error | 保费超出合理数值范围 |
| AGE_OUT_OF_RANGE | error | 年龄不在 0120 |
| LOW_CONFIDENCE | warning | 置信度低于阈值 |
| MANUAL_OVERRIDE | warning | 用户值与解析值不同 |
| DISCLAIMER_MISSING | error | 无可用免责声明 |
| FACT_REVISION_STALE | error | 校验/生成使用过期事实版本 |
业务规则由后台配置阈值,但规则代码和安全下限保留在服务端。
### 8.5 配置快照
每次 `generate_copy`、`generate_visuals`、`compose_canvas`、`export_artifact` 提交时保存:
- 文案模型 provider/model
- 图片模型 provider/model
- Prompt 模板 ID、版本和内容哈希
- 版式预设 ID、版本和内容哈希
- 保司品牌配置;
- Logo 素材 ID 和哈希;
- 配色方案;
- 免责声明版本;
- 校验规则版本;
- fallback 是否允许;
- 提交时间。
任务执行期间后台设置变化,不影响已提交任务。
---
## 九、前端重构计划
### 9.1 路由
```text
/poster PosterHomePage
/poster/:projectId PosterProjectPage
/poster/:projectId/editor PosterEditorPage
/poster/history PosterProjectsPage
/tasks TasksPage继续复用
```
### 9.2 页面和组件
```text
frontend/src/
├── pages/
│ ├── PosterHomePage.vue
│ ├── PosterProjectPage.vue
│ ├── PosterEditorPage.vue
│ └── PosterProjectsPage.vue
├── components/poster/
│ ├── sources/
│ │ ├── PosterSourceStep.vue
│ │ ├── ProductSourcePicker.vue
│ │ ├── ProjectAssetUploader.vue
│ │ └── AssetStatusCard.vue
│ ├── validation/
│ │ ├── PosterValidationStep.vue
│ │ ├── FactTable.vue
│ │ ├── SourceAuditPanel.vue
│ │ └── ValidationIssues.vue
│ ├── creative/
│ │ ├── PosterCreativeStep.vue
│ │ ├── CreativeBriefForm.vue
│ │ ├── VisualCandidateGrid.vue
│ │ └── CopyReviewPanel.vue
│ ├── editor/
│ │ ├── PosterCanvas.vue
│ │ ├── EditorToolbar.vue
│ │ ├── AssetLibraryPanel.vue
│ │ ├── LayerPanel.vue
│ │ ├── PropertyPanel.vue
│ │ ├── DataBindingPanel.vue
│ │ └── VersionHistoryDrawer.vue
│ └── export/
│ ├── PosterExportStep.vue
│ ├── ExportSettings.vue
│ └── ExportArtifactList.vue
├── composables/
│ ├── usePosterProject.ts
│ ├── usePosterCanvas.ts
│ ├── usePosterAutosave.ts
│ ├── usePosterTasks.ts
│ └── useUndoRedo.ts
├── types/
│ ├── poster-project.ts
│ ├── poster-canvas.ts
│ └── poster-validation.ts
└── utils/
└── poster-api.ts
```
### 9.3 渐进迁移
1. 保留当前 `PosterPage.vue` 和四个 `PosterStep*` 组件;
2. 增加 `POSTER_WORKBENCH_V2_ENABLED`
3. 测试账号进入 V2
4. V2 稳定后 `/poster` 指向新首页;
5. 旧项目继续用旧详情查看;
6. 提供“转换为可编辑项目”;
7. 一个发布周期后移除旧创建入口;
8. 最后再删除确定不再引用的旧组件。
### 9.4 画布文档 Schema
画布对象除 Fabric 原生字段外,增加业务元数据:
```json
{
"schemaVersion": "1.0",
"width": 1080,
"height": 1920,
"layoutPresetId": 12,
"objects": [
{
"id": "headline",
"type": "textbox",
"role": "headline",
"text": "真正的安全感,是未雨绸缪的从容",
"dataBinding": null,
"locked": false
},
{
"id": "premium-value",
"type": "textbox",
"role": "fact",
"dataBinding": {
"factPath": "policy.annual_premium",
"factRevision": 3,
"format": "currency"
}
}
]
}
```
业务要求:
- 每个对象必须有稳定 `id`
- 关键数字图层必须有 `dataBinding`
- Logo、免责声明和事实图层可配置最小字号和锁定规则
- 加载时检测事实版本是否过期;
- 画布 JSON 不保存 Blob URL
- 图片对象只保存后端素材 ID 和鉴权加载地址。
### 9.5 自动保存
- 用户停止操作 1.5 秒后保存;
- 最长每 10 秒保存一次;
- 路由离开前刷新未提交保存;
- 使用 `expectedRevision` 乐观锁;
- 网络失败保留本地待提交队列;
- 恢复网络后重试;
- 版本冲突不自动覆盖,显示“使用服务器版本 / 另存副本”;
- 页面顶部始终显示:保存中、已保存、离线、保存失败。
### 9.6 撤销与版本
- 前端撤销栈:最近 100 次操作;
- 重载页面后撤销栈不保证保留;
- 永久版本:生成初稿、用户手动保存、正式导出、恢复旧版时创建;
- 恢复旧版本会创建新版本,不重写历史;
- AI 局部重生成前自动创建版本。
### 9.7 响应式和可访问性
桌面端:
- 完整三栏编辑器;
- 快捷键:
- `Ctrl/Cmd+Z` 撤销;
- `Ctrl/Cmd+Shift+Z` 重做;
- `Ctrl/Cmd+S` 保存版本;
- `Delete` 删除;
- 方向键微调;
- `Shift+方向键` 大步移动。
手机端:
- 五阶段流程可查看;
- 支持上传、校验、选择视觉方案;
- 编辑器进入简化模式,只允许改字、换图、切换预设;
- 提示“精细排版请使用桌面端”,但不阻断查看和导出。
无障碍要求:
- 所有按钮有文字或 `aria-label`
- 画布对象在图层面板中可用键盘选择;
- 焦点样式可见;
- 状态变化通过 `aria-live` 播报;
- 错误不只使用颜色表达;
- 文字与背景对比度满足 WCAG AA
- 放大到 200% 时校验和导出流程可操作。
---
## 十、AI 生成方案
### 10.1 文案生成
输入仅包括:
- 已确认事实;
- 产品卖点;
- 使用场景;
- 目标客群;
- 品牌语气;
- 文案长度约束;
- 免责声明。
输出使用结构化 Schema
```json
{
"headline": "",
"subheadline": "",
"sellingPoints": [
{
"title": "",
"description": "",
"factRefs": ["policy.payment_period"]
}
],
"cta": "",
"disclaimer": "",
"unsupportedClaims": []
}
```
规则:
- 关键数字必须附 `factRefs`
- 找不到事实时不得编造;
- `unsupportedClaims` 非空时阻断进入正式画布;
- 文案更改事实数字时立即标记错误;
- AI 原始响应保留审计,但前端默认展示规范化结果。
### 10.2 视觉生成
Prompt 只描述:
- 场景、人物、环境和情绪;
- 画面构图和安全留白;
- 摄影/插画风格;
- 品牌颜色倾向;
- 输出比例;
- 禁止元素。
必须加入负向约束:
```text
不要生成任何文字、字母、数字、Logo、品牌标识、表格、图表、水印
不要生成可被误认为真实保险合同或官方证明的文件;
为后续文字排版保留明确安全区域。
```
候选数默认 3允许管理员配置 24。每个候选保存
- 完整 Prompt
- provider/model
- seed 或供应商返回标识;
- 参考素材;
- 配置快照;
- 生成耗时和费用元数据;
- 失败代码;
- 是否 fallback。
### 10.3 初始画布构建
`canvas_builder.py` 根据:
- 输出尺寸;
- 版式预设;
- 已确认文案;
- 已确认事实;
- 选中视觉素材;
- Logo 和品牌配置;
- 免责声明;
生成确定性的画布 JSON。相同输入和版式预设应得到相同的元素位置避免每次重新生成版式随机漂移。
### 10.4 局部重新生成
| 操作 | 影响范围 |
|------|----------|
| 重新生成视觉图 | 只创建新的图片素材,不改文字和数据 |
| 重新生成标题 | 只更新标题候选,用户确认后替换 |
| 重新生成卖点 | 只更新选中卖点卡 |
| 更换版式预设 | 重排图层,原画布自动保存为版本 |
| 事实数据变更 | 标记绑定图层过期,不自动覆盖人工排版 |
---
## 十一、后台配置与同步
### 11.1 后台配置分类
| 配置 | 后台来源 | 前端用途 |
|------|----------|----------|
| 文案模型 | `SystemSetting` | AI 文案 |
| 图片模型 | `SystemSetting` | AI 视觉素材 |
| Prompt 模板 | 现有设置扩展 | 文案、视觉和 QA |
| 海报模板 | `PosterTemplate` | 改为版式/品牌预设 |
| 文案模板 | `PosterCopyTemplate` | 快速文案和降级路径 |
| 保司品牌 | `PptCompany` + Logo 表 | Logo、品牌色、名称 |
| 产品资料 | `PptProduct` | 后台审核产品快捷选择 |
| 校验规则 | 系统设置/规则文件 | 字段、阈值和阻断规则 |
| 导出默认值 | 系统设置 | 默认格式、质量和 DPI |
### 11.2 `PosterTemplate` 重解释
现有模板不再表示“一张成品背景图”,而表示:
- 版式类别;
- 安全区;
- 文字层级;
- 数据卡样式;
- Logo 和免责声明位置;
- 推荐场景;
- 品牌色;
- AI 视觉 Prompt 片段;
- 负向 Prompt
- 画布比例。
`reference_image` 只作为风格参考,不直接作为最终背景。
### 11.3 配置版本策略
- 每次管理员保存配置,版本号加一;
- 项目页显示“当前项目使用 v3后台最新 v4”
- 用户选择:
- 继续使用项目快照;
- 同步最新配置;
- 同步最新配置只更新简报和预设,不静默覆盖画布;
- 新任务永远使用提交时快照;
- 历史项目可查看当时配置,但不显示密钥。
### 11.4 任务中心和历史记录职责
任务中心:
- 展示正在运行或最近完成的操作;
- 解析、生成视觉、合成、导出各是一条任务;
- 支持取消可取消任务、重试和查看错误;
- 完成后跳转对应项目。
项目历史:
- 展示可继续编辑的项目;
- 显示资料、校验状态、当前画布、版本和导出物;
- 支持复制、归档、恢复、继续编辑;
- 不重复承担任务进度明细。
---
## 十二、安全、隐私与合规
### 12.1 文件安全
- PDF扩展名、MIME、魔数、大小、页数、加密、损坏检查
- 图片:仅允许 PNG/JPG/WebP使用 Pillow 解码并重编码;
- 删除 EXIF 和地理位置;
- 默认限制:
- 单个 PDF 50 MB
- 单个图片 15 MB
- 单项目 PDF 合计 100 MB
- 参考图最多 6 张;
- 使用 SHA-256 审计;
- 所有下载通过鉴权接口;
- 路径校验使用 `os.path.commonpath`
- API 和 Worker 共享同一持久化 volume。
### 12.2 权限
- 普通用户只能访问本人项目、素材、任务、版本和导出物;
- 主管是否可查看团队项目复用现有数据权限;
- 管理员默认只能看配置,不自动获得客户原始 PDF 权限;
- 需要查看业务数据时必须经过现有角色权限和审计;
- 素材 ID、画布 ID、导出物 ID 均执行所有权校验。
### 12.3 隐私
- PDF 密码不落库、不写日志;
- Prompt 默认脱敏;
- 模型请求根据 `useMaskedData` 替换客户和产品敏感名称;
- 日志不保存完整保费、保额和客户姓名;
- 参考人物照片上传前提示用户确认授权;
- 数据保留期限到期后删除源文件、临时图和未引用候选;
- 正式导出物和审计记录按后台策略保留。
### 12.4 合规
- 生成前强制校验;
- AI 文案只能引用已确认事实;
- Logo 使用真实素材,不允许图片模型生成;
- 免责声明是受保护图层;
- 正式导出前再次检查事实版本;
- 事实已变化时禁止导出旧画布为“正式版”;
- 每份正式导出物关联确认人、确认时间和配置快照;
- fallback 成品必须明确标记生成方式,不伪装成 AI 成功。
---
## 十三、分阶段实施计划
### Phase 0紧急闭环修复与回归基线
**预计工作量**1.5 人日
**目标**:先修复当前功能的确定性故障,建立后续重构基线。
任务:
- [ ] POSTER2-0001 修复输出目录和下载白名单不一致;
- [ ] POSTER2-0002 抽取统一 `PosterStorageService`
- [ ] POSTER2-0003 修复前后端尺寸枚举和映射;
- [ ] POSTER2-0004 生成异常时同步 `PosterRecord``GenerationTask`
- [ ] POSTER2-0005 轮询连续失败时显示可恢复错误;
- [ ] POSTER2-0006 增加竖版、横版、方图生成回归测试;
- [ ] POSTER2-0007 增加“生成成功后可预览和下载”集成测试;
- [ ] POSTER2-0008 准备脱敏计划书、小册子和预期事实样例;
- [ ] POSTER2-0009 记录现有接口和数据库快照。
完成标准:
- 三种尺寸均生成正确方向;
- Worker 生成文件可由 API 下载;
- 容器重启后文件仍存在;
- 生成失败不会永久显示进行中;
- 同一组样例可重复执行。
### Phase 1项目数据模型、迁移和基础 API
**预计工作量**2.5 人日
**目标**:建立项目素材、事实、画布版本和导出物的数据基础。
任务:
- [ ] POSTER2-0101 编写 `migrate_026.py`
- [ ] POSTER2-0102 扩展 `PosterRecord`
- [ ] POSTER2-0103 新增四个 SQLAlchemy 模型;
- [ ] POSTER2-0104 扩展 `GenerationTask.operation`
- [ ] POSTER2-0105 添加索引和唯一约束;
- [ ] POSTER2-0106 实现旧记录回填;
- [ ] POSTER2-0107 实现创建空项目 API
- [ ] POSTER2-0108 扩展工作区详情和自动保存;
- [ ] POSTER2-0109 实现配置快照服务;
- [ ] POSTER2-0110 增加迁移幂等、空库和旧数据测试。
完成标准:
- 空数据库迁移一次成功;
- 迁移重复运行无副作用;
- 旧记录仍可查询和下载;
- 可以在上传前创建项目;
- 项目草稿支持乐观锁;
- 任务可保存大于 10 字符的操作类型。
### Phase 2自由上传、解析、来源审计和校验门
**预计工作量**3 人日
**目标**:用户可上传两类 PDF且错误数据不能进入生成。
任务:
- [ ] POSTER2-0201 实现项目素材上传 API
- [ ] POSTER2-0202 支持计划书和小册子独立上传/替换;
- [ ] POSTER2-0203 支持后台产品关联;
- [ ] POSTER2-0204 支持参考图片和临时 Logo 上传;
- [ ] POSTER2-0205 图片重编码、EXIF 清理和安全限制;
- [ ] POSTER2-0206 项目级解析任务;
- [ ] POSTER2-0207 标准事实 Schema
- [ ] POSTER2-0208 事实来源文件、页码和原文记录;
- [ ] POSTER2-0209 校验规则引擎;
- [ ] POSTER2-0210 错误阻断、警告接受和确认接口;
- [ ] POSTER2-0211 前端项目资料页;
- [ ] POSTER2-0212 前端数据底表、来源审计和 QA
- [ ] POSTER2-0213 替换源文件后确认失效;
- [ ] POSTER2-0214 上传、解析和校验自动化测试。
完成标准:
- 不选择后台产品也可上传两份 PDF
- 每个关键数字可定位到文件和页码;
- 任一错误项存在时无法生成;
- 警告必须显式接受;
- 确认记录包含用户、时间和事实版本;
- 替换资料后旧确认自动失效。
### Phase 3AI 文案、视觉候选和初始画布
**预计工作量**3.5 人日
**目标**AI 生成与资料语义匹配的视觉素材,而不是固定背景模板成品。
任务:
- [ ] POSTER2-0301 定义创意简报 Schema
- [ ] POSTER2-0302 重构文案 Prompt只允许引用确认事实
- [ ] POSTER2-0303 增加文案结构化输出校验;
- [ ] POSTER2-0304 增加 unsupported claim 检查;
- [ ] POSTER2-0305 重构图片 Prompt禁止文字、数字和 Logo
- [ ] POSTER2-0306 生成 24 个视觉候选;
- [ ] POSTER2-0307 候选图记录 Prompt、模型、参考图和费用元数据
- [ ] POSTER2-0308 支持选择和局部重新生成;
- [ ] POSTER2-0309 将 `PosterTemplate` 改造为版式/品牌预设;
- [ ] POSTER2-0310 实现 `canvas_builder.py`
- [ ] POSTER2-0311 创建初始画布版本;
- [ ] POSTER2-0312 前端创意简报和候选选择页面;
- [ ] POSTER2-0313 AI 失败、限流和 fallback 契约测试。
完成标准:
- AI 候选图不包含可见文字和伪造 Logo
- 视觉候选明确对应客户、产品和场景简报;
- 用户可单独重生成一张候选;
- 重新生成图片不改变已确认事实;
- 文案中的数字全部有事实引用;
- 可从选中候选生成初始画布 JSON。
### Phase 4可编辑画布
**预计工作量**5.5 人日
**目标**:生成结果可以在浏览器内进行专业、可恢复编辑。
任务:
- [ ] POSTER2-0401 Fabric.js 技术验证:中文字体、长图、序列化和 2x 导出;
- [ ] POSTER2-0402 定义 Canvas Schema v1
- [ ] POSTER2-0403 实现画布加载和保存;
- [ ] POSTER2-0404 实现文字编辑;
- [ ] POSTER2-0405 实现图片替换和裁剪;
- [ ] POSTER2-0406 实现基础形状和背景;
- [ ] POSTER2-0407 实现数据卡、图标、Logo、免责声明组件
- [ ] POSTER2-0408 实现图层面板;
- [ ] POSTER2-0409 实现属性面板;
- [ ] POSTER2-0410 实现多选、对齐、吸附和安全区;
- [ ] POSTER2-0411 实现撤销、重做和快捷键;
- [ ] POSTER2-0412 实现自动保存和离线待提交;
- [ ] POSTER2-0413 实现版本创建、列表和恢复;
- [ ] POSTER2-0414 实现事实绑定和过期提醒;
- [ ] POSTER2-0415 实现局部 AI 图片替换;
- [ ] POSTER2-0416 实现桌面/平板布局和手机简化模式;
- [ ] POSTER2-0417 画布 Schema、版本冲突和恢复测试。
完成标准:
- 用户可以修改示例海报全部文字;
- 用户可以移动、缩放、替换图片和调整图层;
- 刷新页面后画布恢复;
- 撤销、重做至少覆盖最近 100 次操作;
- 两个标签页同时修改时不会静默覆盖;
- 关键数字图层可追溯到事实;
- 恢复旧版本不会删除新版本。
### Phase 5多格式导出
**预计工作量**2.5 人日
**目标**:输出可管理、可追溯的多格式交付物。
任务:
- [ ] POSTER2-0501 高分辨率隐藏画布渲染;
- [ ] POSTER2-0502 PNG 1x/2x 导出;
- [ ] POSTER2-0503 JPG 质量选项;
- [ ] POSTER2-0504 PDF 页面尺寸和分页;
- [ ] POSTER2-0505 项目 JSON 导出与导入校验;
- [ ] POSTER2-0506 导出物上传、MIME 和所有权校验;
- [ ] POSTER2-0507 导出物列表和鉴权下载;
- [ ] POSTER2-0508 正式交付版标记;
- [ ] POSTER2-0509 字体缺失和图片跨域检查;
- [ ] POSTER2-0510 各格式视觉快照测试。
完成标准:
- 同一画布可生成 PNG、JPG、PDF 和项目 JSON
- 四种文件均可重新下载;
- 导出物与画布版本、事实版本和配置快照关联;
- 导出前发现事实过期时禁止标记正式版;
- 图片尺寸、方向和文件 MIME 正确;
- 导入项目 JSON 后版式不明显漂移。
### Phase 6项目历史、任务中心和后台同步
**预计工作量**2.5 人日
**目标**:所有内容与后台形成可恢复、可审计闭环。
任务:
- [ ] POSTER2-0601 重构海报历史为项目列表;
- [ ] POSTER2-0602 增加项目继续编辑、复制、归档和恢复;
- [ ] POSTER2-0603 项目详情展示素材、校验、版本和导出物;
- [ ] POSTER2-0604 任务中心展示细分操作;
- [ ] POSTER2-0605 任务完成跳转项目;
- [ ] POSTER2-0606 后台模板增加版式 Schema 和版本;
- [ ] POSTER2-0607 后台 Prompt、品牌和校验规则版本化
- [ ] POSTER2-0608 前端配置版本差异提示;
- [ ] POSTER2-0609 同步最新配置但不覆盖画布;
- [ ] POSTER2-0610 旧项目“转换为可编辑项目”;
- [ ] POSTER2-0611 数据权限和审计日志测试。
完成标准:
- 用户离开页面后任务继续运行;
- 从历史项目可以恢复到上次步骤;
- 任务中心不再承担项目历史职责;
- 后台配置变化不会改变已提交任务;
- 用户可以看见项目配置版本与最新版本差异;
- 普通用户不能访问他人项目和导出物。
### Phase 7安全、性能、灰度和上线
**预计工作量**3.5 人日
**目标**:达到生产上线标准。
任务:
- [ ] POSTER2-0701 上传安全和资源限制测试;
- [ ] POSTER2-0702 PDF Prompt 注入测试;
- [ ] POSTER2-0703 跨用户访问测试;
- [ ] POSTER2-0704 Prompt、日志和错误脱敏
- [ ] POSTER2-0705 数据清理和保留策略;
- [ ] POSTER2-0706 项目、任务、存储、模型 readiness
- [ ] POSTER2-0707 关键指标和结构化日志;
- [ ] POSTER2-0708 前端性能和大画布测试;
- [ ] POSTER2-0709 无障碍和键盘流程测试;
- [ ] POSTER2-0710 迁移演练;
- [ ] POSTER2-0711 灰度开关和回滚演练;
- [ ] POSTER2-0712 更新需求、API、测试、部署和变更日志
- [ ] POSTER2-0713 业务方使用真实脱敏案例验收。
完成标准:
- P0/P1 自动化用例全部通过;
- 无跨用户数据访问;
- 日志不含 PDF 密码、密钥和完整客户敏感数据;
- 迁移可重复执行;
- 关闭 V2 开关可回到旧流程;
- 旧项目和新项目均可查询;
- 回滚演练成功。
---
## 十四、测试计划
### 14.1 单元测试
后端:
- 文件类型、大小、页数和路径安全;
- 事实 Schema
- 各险种必填字段;
- 来源证据;
- 数值、币种和缴费期交叉校验;
- warning 接受和 error 阻断;
- 配置快照;
- AI 结构化响应;
- Canvas Schema
- storage 对象键;
- 旧数据回填;
- 幂等键和任务状态同步。
前端:
- 项目状态恢复;
- 素材上传状态;
- 校验门;
- 创意简报;
- 画布对象序列化;
- 撤销重做;
- 自动保存;
- 乐观锁冲突;
- 导出参数。
建议补充:
- Vitest
- Vue Test Utils
- Canvas 相关函数尽量抽成无 DOM 的纯函数。
### 14.2 API 集成测试
| 场景 | 预期 |
|------|------|
| 只上传计划书,不选产品也不传小册子 | 阻断并提示缺少产品资料 |
| 选择后台产品 + 上传计划书 | 可解析 |
| 上传计划书 + 小册子 | 可解析 |
| 跨用户读取项目 | 404/无权限 |
| 修改事实后未重新确认就生成 | 拒绝 |
| warning 未接受 | 拒绝 |
| 重复点击生成 | 返回同一活跃任务 |
| Worker 失败 | 项目和任务均为 failed |
| 旧项目下载 | 保持可用 |
| 导出不存在的画布版本 | 拒绝 |
### 14.3 端到端测试
主路径:
```text
创建项目
→ 上传两份 PDF
→ 等待解析
→ 修正低置信度字段
→ 查看来源页码
→ 确认
→ 填写创意简报
→ 生成 3 个视觉候选
→ 选择候选
→ 进入画布
→ 修改标题和图片
→ 保存版本
→ 导出 PNG、JPG、PDF
→ 离开页面
→ 从历史恢复
→ 再次下载
```
异常路径:
- 加密 PDF 密码错误;
- PDF 损坏;
- 产品名冲突;
- 币种冲突;
- 图片模型超时;
- 文案模型返回非 JSON
- 上传中断;
- 页面刷新;
- 两个标签页并发编辑;
- storage 暂时不可用;
- 字体加载失败;
- 超长标题;
- 100 个画布对象;
- 800×12000 长图。
### 14.4 视觉回归
固定三套脱敏基准:
1. 高端传承竖版;
2. 产品利益长图;
3. 朋友圈方图。
对以下内容进行截图差异检查:
- 初始画布;
- 编辑后画布;
- 1x PNG
- 2x PNG
- PDF 首屏;
- 恢复版本后的画布。
字体渲染允许小范围像素差异,但不能出现:
- 文字截断;
- 数字错位;
- 图片拉伸;
- Logo 变形;
- 免责声明缺失;
- 横竖版方向错误。
### 14.5 性能标准
| 指标 | 目标 |
|------|------|
| 创建项目 | P95 < 1 |
| 上传接口返回 | 保存和投递任务后 P95 < 3 |
| 项目详情 | P95 < 1.5 |
| 自动保存 | P95 < 1 |
| 画布首次可操作 | 桌面宽带 < 3 不含大图后台加载 |
| 画布拖拽 | 常见 50 个对象保持接近 60 FPS |
| 导出 1080×1920 PNG | 常见设备 < 10 |
| 任务状态刷新 | 2 秒轮询错误后指数退避 |
AI 解析和生成耗时不设置绝对秒数 SLA但必须持续显示状态允许离开页面并可恢复
---
## 十五、监控与可观测性
### 15.1 指标
- 项目创建成功率
- PDF 上传/解析成功率
- 平均解析耗时
- 必填字段缺失率
- 低置信度字段比例
- 生成前校验阻断率
- 文案生成成功率
- 图片生成成功率
- fallback 使用率
- 平均每项目候选图数量
- 画布保存失败率
- 版本冲突率
- PNG/JPG/PDF 导出成功率
- 文件下载失败率
- 单项目模型费用
### 15.2 结构化日志字段
```text
request_id
user_id_masked
project_id
asset_id
task_id
operation
fact_revision
canvas_version
config_version
provider
model
status
error_code
latency_ms
fallback_reason
```
禁止记录
- API Key
- PDF 密码
- 完整客户姓名
- 完整身份证件
- 未脱敏的保费/保额组合
- 完整 PDF 原文
- Base64 图片
### 15.3 健康检查
readiness 应检查
- 数据库
- Redis
- Celery Worker 心跳
- storage 可读写
- 至少一个可用文案模型
- 至少一个可用图片模型或明确允许 fallback
- 至少一个启用版式预设
- 必需字体是否存在
- 磁盘剩余空间
---
## 十六、发布、灰度与回滚
### 16.1 功能开关
```text
POSTER_WORKBENCH_V2_ENABLED
POSTER_USER_MANUAL_UPLOAD_ENABLED
POSTER_AI_VISUAL_CANDIDATES_ENABLED
POSTER_CANVAS_EDITOR_ENABLED
POSTER_MULTI_EXPORT_ENABLED
POSTER_LEGACY_CREATE_ENABLED
```
### 16.2 上线顺序
1. 部署 Phase 0 修复
2. 部署迁移 026 和新 API但不开新入口
3. 管理员测试自由上传和校验
4. 开放 AI 视觉候选
5. 开放画布编辑器
6. 开放多格式导出
7. 5% 销售用户灰度
8. 25% 用户
9. 全量
10. 保留旧创建入口一个发布周期
11. 关闭旧创建入口
### 16.3 上线前检查
- [ ] 数据库和 storage 备份
- [ ] 导出迁移历史
- [ ] 在生产数据副本执行迁移 026
- [ ] 统计旧海报记录文件存在率和回填结果
- [ ] 验证旧海报预览下载
- [ ] 验证 API/Worker 共享 volume
- [ ] 验证字体
- [ ] 验证模型连接
- [ ] 准备灰度账号
- [ ] 准备回滚版本
- [ ] 完成 P0/P1 回归
### 16.4 回滚原则
- 优先关闭 V2 功能开关不执行破坏性数据库回滚
- 新表和新增字段保留
- 旧接口和旧记录继续工作
- 新项目在回滚期间保持只读和可下载
- storage 不删除新文件
- 代码回滚不回滚已确认事实和审计记录
- 修复后重新开启 V2
### 16.5 回滚触发条件
- 出现跨用户项目或文件访问
- 事实校验失效仍可生成
- 正式导出缺少关键数字或免责声明
- 新迁移导致旧项目不可读
- 文件下载失败率持续高于 5%
- 任务重复计费
- 画布自动保存持续失败
- 导出物与画布版本不一致
- 模型密钥或客户敏感信息泄露
---
## 十七、工作量、人员和里程碑
### 17.1 工作量
| 阶段 | 人日 |
|------|:----:|
| Phase 0紧急闭环 | 1.5 |
| Phase 1数据模型与 API | 2.5 |
| Phase 2上传解析与校验 | 3.0 |
| Phase 3AI 视觉与初始画布 | 3.5 |
| Phase 4画布编辑器 | 5.5 |
| Phase 5多格式导出 | 2.5 |
| Phase 6历史任务与后台同步 | 2.5 |
| Phase 7测试灰度和上线 | 3.5 |
| **基础合计** | **24.5** |
| 建议风险缓冲 20% | 4.55.0 |
| **计划预算** | **约 29 人日** |
不包含
- 外部模型账号额度和网络审批等待
- 业务方准备真实脱敏样例
- 法务/合规确认时间
- 新字体商业授权
- SVG多人协作视频海报
### 17.2 人员建议
单人开发
- 预计 56
- Phase 4 画布编辑器风险集中
- 必须严格按阶段验收禁止并行铺开全部功能
双人开发
- 后端Phase 03数据任务校验和导出接口
- 前端Phase 2 页面Phase 4 编辑器Phase 5 导出
- 预计 34 集成阶段保留至少 4 人日
### 17.3 里程碑
| 里程碑 | 包含阶段 | 可交付结果 |
|--------|----------|------------|
| M0 基础可用 | Phase 0 | 当前 PNG 流程稳定 |
| M1 事实可信 | Phase 12 | 自由上传 + 来源审计 + 校验门 |
| M2 AI 视觉正确 | Phase 3 | AI 候选图 + 结构化初始画布 |
| M3 可编辑交付 | Phase 45 | 画布编辑 + 多格式导出 |
| M4 生产上线 | Phase 67 | 后台闭环 + 灰度 + 回滚 |
每个里程碑完成后再进入下一里程碑不以页面已出现代替端到端验收
---
## 十八、风险与应对
| 风险 | 概率 | 影响 | 应对 |
|------|:----:|:----:|------|
| Fabric.js 中文字体和长图导出差异 | | | Phase 4 第一项先做技术验证不通过则切换 SVG/HTML 方案 |
| 图片模型生成文字或伪 Logo | | | 负向 Prompt结果人工选择Logo 独立图层 |
| PDF 解析事实不稳定 | | | Schema来源证据置信度人工确认和阻断规则 |
| 画布 JSON 版本升级困难 | | | 明确 Schema 版本和迁移函数不直接暴露 Fabric 原始格式为永久契约 |
| 大图导致浏览器内存高 | | | 素材缩略图按需加载隐藏高分辨率画布只在导出时创建 |
| 自动保存覆盖冲突 | | | 乐观锁本地待提交冲突另存副本 |
| 模型费用增加 | | | 候选数上限幂等局部重生成费用指标 |
| 配置修改影响排队任务 | | | 提交时配置快照 |
| 旧项目无法转为可编辑 | | | 保持旧下载转换时用旧图作为锁定背景并叠加可编辑文字 |
| 手机端画布难用 | | | 手机只做简化编辑桌面完成精细排版 |
| PDF 导出字体缺失 | | | 预加载授权字体导出前字体检查失败阻断而非静默替换 |
| 参考照片存在隐私风险 | | | 上传提示授权EXIF 清理保留期限权限和审计 |
---
## 十九、文件级修改清单
### 19.1 后端新增
| 文件 | 用途 |
|------|------|
| `api/insurance/db/migrate_026.py` | 新表字段索引和旧数据回填 |
| `api/insurance/models/poster_project_asset.py` | 项目素材 |
| `api/insurance/models/poster_fact_item.py` | 事实与来源 |
| `api/insurance/models/poster_canvas_version.py` | 画布版本 |
| `api/insurance/models/poster_export_artifact.py` | 导出物 |
| `api/insurance/poster/project_routes.py` | 新工作区接口 |
| `api/insurance/poster/project_service.py` | 项目聚合服务 |
| `api/insurance/poster/asset_service.py` | 素材生命周期 |
| `api/insurance/poster/extraction_service.py` | 项目解析编排 |
| `api/insurance/poster/validation_service.py` | 规则校验 |
| `api/insurance/poster/source_audit_service.py` | 来源审计 |
| `api/insurance/poster/creative_service.py` | 创意简报和文案 |
| `api/insurance/poster/visual_generator.py` | AI 视觉候选 |
| `api/insurance/poster/canvas_builder.py` | 初始画布 |
| `api/insurance/poster/export_service.py` | 导出物 |
| `api/insurance/poster/storage_service.py` | 安全文件访问 |
| `api/insurance/poster/schemas/*` | 事实简报和画布 Schema |
### 19.2 后端修改
| 文件 | 修改 |
|------|------|
| `api/insurance/models/poster_record.py` | 项目校验画布配置快照字段 |
| `api/insurance/models/generation_task.py` | 操作类型和任务输出 |
| `api/insurance/poster/routes.py` | 旧接口兼容和下载转调 |
| `api/insurance/poster/service.py` | 旧流程转调新项目服务 |
| `api/insurance/poster/image_generator.py` | 视觉素材 Prompt 和尺寸统一 |
| `api/insurance/poster/copy_generator.py` | 事实引用和结构化输出 |
| `api/insurance/poster/tasks.py` | 项目解析任务 |
| `api/insurance/generation/celery_tasks.py` | 新任务操作状态同步和错误码 |
| `api/insurance/generation/routes.py` | 工作区详情和任务恢复 |
| `api/insurance/routes.py` | 注册新 Blueprint |
| `api/insurance/config.py` | 文件和功能开关 |
| `api/insurance/models/__init__.py` | 注册模型 |
| `api/insurance/requirements.txt` | 仅增加实际使用的导出/校验依赖 |
| `docker-compose.dify.yml` | API/Worker storage 和开关 |
### 19.3 前端新增和修改
| 文件 | 修改 |
|------|------|
| `frontend/package.json` | Fabric.jsPDF 导出和测试依赖 |
| `frontend/src/router/*` | 新项目和编辑器路由 |
| `frontend/src/pages/PosterPage.vue` | 切换到 V2 首页/兼容入口 |
| `frontend/src/pages/PosterHistoryPage.vue` | 改为项目历史 |
| `frontend/src/utils/poster-api.ts` | 项目素材校验画布和导出 API |
| `frontend/src/composables/useWorkspace.ts` | 完整项目状态恢复 |
| `frontend/src/components/GenerationTaskDock.vue` | 海报细分任务和跳转 |
| `frontend/src/pages/admin/PosterTemplatesAdmin.vue` | 版式预设版本和 Prompt |
| `frontend/src/pages/admin/PptSettingsAdmin.vue` | 校验导出和配置版本 |
| `frontend/src/pages/PosterEditorPage.vue` | 全屏编辑器 |
| `frontend/src/components/poster/**` | 新五阶段组件 |
### 19.4 测试
建议新增
```text
tests/poster_storage_test.py
tests/poster_project_migration_test.py
tests/poster_asset_api_test.py
tests/poster_fact_validation_test.py
tests/poster_source_audit_test.py
tests/poster_visual_generation_test.py
tests/poster_canvas_api_test.py
tests/poster_export_test.py
tests/poster_permissions_test.py
tests/poster_task_lifecycle_test.py
frontend/src/**/__tests__/*
frontend/e2e/poster-workbench.spec.ts
```
---
## 二十、文档同步清单
实施过程中必须同步
| 文档 | 更新内容 |
|------|----------|
| `保险智能客服系统_需求文档.md` | 海报项目校验画布导出业务规则 |
| `保险智能客服系统_API接口文档.md` | 新接口错误码请求响应 |
| `保险智能客服系统_测试用例.md` | P0/P1 和端到端用例 |
| `PPT与海报功能开发任务清单.md` | 增加二期任务编号和状态 |
| `部署文档_完整版.md` | 依赖字体storage开关和 Worker |
| `API_curl示例.md` | 项目素材校验生成和导出示例 |
| `CHANGELOG.md` | 每个发布阶段的新增修复和变更 |
| `docs/README.md` | 本计划索引 |
---
## 二十一、完成定义
只有全部满足以下条件海报工作台二期才可标记为完成
- [ ] 用户可直接上传计划书和产品小册子
- [ ] 用户也可选择后台审核产品
- [ ] 参考图和 Logo 通过真实文件上传管理
- [ ] 所有关键事实有来源或人工补录说明
- [ ] 错误数据无法进入生成
- [ ] 警告已显式处理
- [ ] AI 生成视觉素材不在图片中生成正式文字和数字
- [ ] 文案数字全部绑定已确认事实
- [ ] 生成结果是可编辑画布
- [ ] 画布支持撤销重做自动保存和版本恢复
- [ ] 页面刷新和任务完成后可恢复项目
- [ ] 支持 PNGJPGPDF 和项目源文件
- [ ] 导出物关联画布事实和配置版本
- [ ] 任务中心和项目历史职责清晰
- [ ] 后台配置提交时快照可审计
- [ ] 旧海报仍可预览下载
- [ ] API/Worker 共享持久化 storage
- [ ] 普通用户不能访问他人数据
- [ ] P0/P1 自动化测试全部通过
- [ ] 迁移灰度和回滚演练完成
- [ ] 相关需求API测试部署和变更日志已同步
---
## 二十二、开发启动前待确认项
以下决策不阻塞计划编写但必须在对应 Phase 开发前确认
| 编号 | 决策 | 推荐默认值 | 最晚确认阶段 |
|------|------|------------|--------------|
| D-01 | 手机是否要求完整画布编辑 | 手机使用简化编辑 | Phase 4 |
| D-02 | 首期 PDF 是否接受栅格化单页 | 接受保证视觉一致 | Phase 5 |
| D-03 | 项目源文件是否允许用户重新导入 | 允许但严格校验 Schema | Phase 5 |
| D-04 | 用户上传小册子是否可进入公共产品库 | 仅显式提交审核后进入 | Phase 2 |
| D-05 | 每次默认生成几个视觉候选 | 3 | Phase 3 |
| D-06 | AI 图片失败是否允许 fallback | 默认允许但必须清晰标记 | Phase 3 |
| D-07 | 正式导出是否必须二次人工确认 | 建议必须 | Phase 5 |
| D-08 | 项目和原始 PDF 默认保留时间 | 沿用后台当前保留策略 | Phase 7 |
| D-09 | 首期支持哪些授权中文字体 | 至少 2 套品牌字体 | Phase 4 |
| D-10 | SVG 是否进入首发 | 不进入作为 P2 | Phase 5 |
---
## 二十三、建议的第一批实施内容
第一批开发只做 Phase 0 Phase 1不立即进入画布编辑器
```text
修复下载目录
→ 修复尺寸映射
→ 修复失败状态同步
→ 建立回归样例
→ 创建迁移 026
→ 建立项目素材、事实、画布版本、导出物模型
→ 创建空项目和工作区 API
→ 完成旧数据回填测试
```
完成这一批后数据库和文件模型稳定后续上传校验AI 和画布可以并行推进如果基础模型未稳定就直接开发编辑器极易出现画布历史导出和任务各自保存一套数据的问题