# 海报生成工作台完整重构修复计划 > - **文档版本**: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 根据客户、产品、场景、品牌约束生成 2~4 个真实视觉候选 | | 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. 系统生成 2~4 个不含文字、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` | 生成 2~4 个视觉候选 | | 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 | 年龄不在 0~120 | | 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,允许管理员配置 2~4。每个候选保存: - 完整 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 3:AI 文案、视觉候选和初始画布 **预计工作量**:3.5 人日 **目标**:AI 生成与资料语义匹配的视觉素材,而不是固定背景模板成品。 任务: - [ ] POSTER2-0301 定义创意简报 Schema; - [ ] POSTER2-0302 重构文案 Prompt,只允许引用确认事实; - [ ] POSTER2-0303 增加文案结构化输出校验; - [ ] POSTER2-0304 增加 unsupported claim 检查; - [ ] POSTER2-0305 重构图片 Prompt,禁止文字、数字和 Logo; - [ ] POSTER2-0306 生成 2~4 个视觉候选; - [ ] 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 3:AI 视觉与初始画布 | 3.5 | | Phase 4:画布编辑器 | 5.5 | | Phase 5:多格式导出 | 2.5 | | Phase 6:历史、任务与后台同步 | 2.5 | | Phase 7:测试、灰度和上线 | 3.5 | | **基础合计** | **24.5** | | 建议风险缓冲(约 20%) | 4.5~5.0 | | **计划预算** | **约 29 人日** | 不包含: - 外部模型账号、额度和网络审批等待; - 业务方准备真实脱敏样例; - 法务/合规确认时间; - 新字体商业授权; - SVG、多人协作、视频海报。 ### 17.2 人员建议 单人开发: - 预计 5~6 周; - Phase 4 画布编辑器风险集中; - 必须严格按阶段验收,禁止并行铺开全部功能。 双人开发: - 后端:Phase 0~3、数据、任务、校验和导出接口; - 前端:Phase 2 页面、Phase 4 编辑器、Phase 5 导出; - 预计 3~4 周,集成阶段保留至少 4 人日。 ### 17.3 里程碑 | 里程碑 | 包含阶段 | 可交付结果 | |--------|----------|------------| | M0 基础可用 | Phase 0 | 当前 PNG 流程稳定 | | M1 事实可信 | Phase 1~2 | 自由上传 + 来源审计 + 校验门 | | M2 AI 视觉正确 | Phase 3 | AI 候选图 + 结构化初始画布 | | M3 可编辑交付 | Phase 4~5 | 画布编辑 + 多格式导出 | | M4 生产上线 | Phase 6~7 | 后台闭环 + 灰度 + 回滚 | 每个里程碑完成后再进入下一里程碑,不以“页面已出现”代替端到端验收。 --- ## 十八、风险与应对 | 风险 | 概率 | 影响 | 应对 | |------|:----:|:----:|------| | 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.js、PDF 导出和测试依赖 | | `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 生成视觉素材,不在图片中生成正式文字和数字; - [ ] 文案数字全部绑定已确认事实; - [ ] 生成结果是可编辑画布; - [ ] 画布支持撤销、重做、自动保存和版本恢复; - [ ] 页面刷新和任务完成后可恢复项目; - [ ] 支持 PNG、JPG、PDF 和项目源文件; - [ ] 导出物关联画布、事实和配置版本; - [ ] 任务中心和项目历史职责清晰; - [ ] 后台配置提交时快照可审计; - [ ] 旧海报仍可预览下载; - [ ] 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 和画布可以并行推进;如果基础模型未稳定就直接开发编辑器,极易出现画布、历史、导出和任务各自保存一套数据的问题。