baodan/docs/PPT与海报功能完整解决方案.md

31 KiB
Raw Blame History

建议书PPT+ 海报功能 完整解决方案(终版)

更新时间2026-07-23 状态:需求已确认,可进入实施阶段

Context

当前系统已有完整的 PPT 生成管线PDF 上传 → AI 解析 → 归一化 → 渲染 PPTX但保司/产品/模板数据仍以 JSON 文件 + 数据库种子形式存在,管理后台缺少对这些数据的 CRUD 界面。同时系统完全没有海报功能。

本次需求涉及两大模块:

  1. PPT 功能增强:前端适配、历史记录、保司/产品/模板的后台可配置化
  2. 海报功能(全新):保司小册子管理、计划书上传解析、文案生成(模板/AI 双模式)、海报模板、导出

核心约束:不修改当前可正常运行的功能,所有改动以增量方式添加。


一、已确认决策清单

# 项目 决策 备注
1 移动端适配 响应式适配,同一套代码 复用现有 responsive.css + useMobile()
2 海报渲染引擎 纯 AI 生图GPT image 模型) 已有 OpenAI API Key
3 文案生成 LLM 复用现有 DeepSeek/MiniMax/Gemini 多供应商 + 自动降级
4 历史记录保存 管理员可删除,保存期限可配置 后台提供配置项
5 AI 文案审批 用户自行确认即可 无需额外审批流程
6 风格自由度 支持自定义参考图 + 配色 管理员上传参考图 + 选择配色方案
7 product_type 保持 savings/ci/iul 三种 预留 VARCHAR 扩展
8 产品字段 先用现有字段 + 按需扩展 不做大规模字段新增
9 场景化维度 自由标签 管理员自定义标签,不限固定维度
10 模板产品关联 模板独立于产品 AI 根据产品数据自动适配
11 导出尺寸 支持自定义,预设 4 种 1080x1920 / 900x500 / 1080x1080 / 800x1200

二、现状分析

2.1 PPT 功能现状

子功能 当前状态 需求目标 差距
前端适配 PptPage.vue 4 步向导已存在Element Plus + responsive.css 有基础响应式 移动端全流程无障碍、骨架屏、手势支持 需补充骨架屏、触屏优化、进度反馈
历史记录 PptSession 仅存当前会话 按用户留存完整历史 需新建表 + API + 前端页面
保司配置 PptCompany 模型已存在,数据由 migration_014 从 JSON 种子导入 后台可增删改查 需新增 admin CRUD 接口 + 前端管理页
产品配置 PptProduct 模型已存在,同上 后台可增删改查 + 海报所需扩展字段 需扩展字段 + admin CRUD + 前端管理页
模板配置 PptTemplate 模型已存在,同上 场景化模板管理 需扩展字段(场景标签、预览图、适用范围)

2.2 海报功能现状

完全不存在,需从零建设。可复用:

  • PPT 模块的 LLM 客户端(ppt/llm_client.py)用于 AI 文案生成
  • PPT 模块的 PDF 解析能力(ppt/extraction.py)用于计划书解析
  • 现有认证/权限/审计中间件
  • 现有文件上传模式

三、数据库设计(新增 5 张表 + 扩展 3 张表)

3.1 扩展现有表:insurance_ppt_companies

新增字段(不改已有字段):

字段 类型 说明
logo_url VARCHAR(500) 公司 Logo 图片地址
status SMALLINT DEFAULT 1 1=启用, 0=停用
sort_order INTEGER DEFAULT 0 排序权重

3.2 扩展现有表:insurance_ppt_products

新增字段:

字段 类型 说明
product_code VARCHAR(50) 产品编码(供外部引用)
product_type VARCHAR(20) 产品类型savings/ci/iulVARCHAR 预留扩展)
coverage_period VARCHAR(50) 保障期限
payment_period VARCHAR(50) 缴费期限
insured_age_range VARCHAR(50) 投保年龄范围
waiting_period VARCHAR(50) 等待期
highlights TEXT JSON产品亮点/卖点列表
extra_fields TEXT JSON扩展字段灵活承载非结构化字段
status SMALLINT DEFAULT 1 启用/停用
sort_order INTEGER DEFAULT 0 排序
updated_at TIMESTAMP 更新时间
海报相关
manual_file_url VARCHAR(500) 产品小册子 PDF 地址
manual_parse_status VARCHAR(20) DEFAULT 'none' none/parsing/parsed/reviewed
manual_parsed_rules TEXT JSON解析出的产品规则库
manual_reviewed_by VARCHAR(50) 核对人
manual_reviewed_at TIMESTAMP 核对时间

manual_parsed_rules 建议内部结构:

{
  "product_name": "xxx保障计划",
  "features": [
    {"code": "income_stream", "title": "无忧选", "summary": "缴清保费后可定期领取非保证入息"},
    {"code": "bonus_lock", "title": "终期红利锁定", "summary": "第5个保单周年日起可锁定终期红利"}
  ],
  "currency_options": ["USD", "HKD", "RMB"]
}

3.3 扩展现有表:insurance_ppt_templates

新增字段:

字段 类型 说明
name VARCHAR(100) 模板名称(当前只有 id缺人类可读名
scenario_tag VARCHAR(50) 场景标签(自由标签,字典可配置)
preview_image VARCHAR(500) 预览图地址
applicable_company_ids TEXT JSON 数组,适用保司 ID 列表(空=全部)
applicable_product_ids TEXT JSON 数组,适用产品 ID 列表(空=全部)
status SMALLINT DEFAULT 1 启用/停用

3.4 新建表:insurance_ppt_history

CREATE TABLE insurance_ppt_history (
    id BIGSERIAL PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    session_id VARCHAR(50),           -- 关联 PptSession
    action_type VARCHAR(20) NOT NULL, -- create/edit/preview/export/download
    company_id VARCHAR(50),
    product_id VARCHAR(50),
    template_id VARCHAR(50),
    content_snapshot TEXT,            -- JSON 快照(历史详情用,避免关联数据变更后失真)
    file_url VARCHAR(500),
    ip VARCHAR(50),
    user_agent VARCHAR(500),
    created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_ppt_history_user ON insurance_ppt_history(user_id, created_at DESC);

3.5 新建表:poster_case_uploads

CREATE TABLE poster_case_uploads (
    id BIGSERIAL PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    product_id VARCHAR(50) NOT NULL,
    source_file_url VARCHAR(500) NOT NULL,
    parse_status VARCHAR(20) DEFAULT 'pending', -- pending/parsed/failed
    parsed_data TEXT,          -- JSON系统自动解析结果
    confirmed_data TEXT,       -- JSON人工核对后最终结果
    confirmed_by VARCHAR(50),
    confirmed_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT NOW()
);

parsed_data / confirmed_data 建议字段:

{
  "age": 35,
  "gender": "男",
  "smoker": false,
  "currency": "USD",
  "sum_assured": 500000,
  "premium_term": 5,
  "annual_premium": 100000,
  "first_year_premium_after_discount": 92000,
  "levy_rate": 12.95,
  "cash_value_table": [
    {"year": 10, "guaranteed": 0, "non_guaranteed": 0}
  ],
  "death_benefit_table": [
    {"year": 10, "amount": 0}
  ]
}

3.6 新建表:poster_templatesAI 生图方案)

注意:由于采用纯 AI 生图方案,模板不再存储 HTML 结构,改为存储 AI 生图所需的风格描述、参考图和配色方案。

CREATE TABLE poster_templates (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    scenario_tag VARCHAR(50),         -- 自由标签
    style_description TEXT NOT NULL,  -- AI 生图的风格描述 prompt 片段
    color_scheme TEXT,                -- JSON配色方案 {"primary": "#1a1a2e", "accent": "#667eea", ...}
    reference_image VARCHAR(500),     -- 参考图地址AI 参考风格生成)
    preview_image VARCHAR(500),       -- 预览图(供管理员/用户选择时展示)
    status SMALLINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

3.7 新建表:poster_copy_templates

CREATE TABLE poster_copy_templates (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    scenario_tag VARCHAR(50),
    content TEXT NOT NULL,           -- 文案模板,含 {{变量}} 占位符
    variables TEXT,                  -- JSON变量列表及说明
    status SMALLINT DEFAULT 1,
    created_at TIMESTAMP DEFAULT NOW()
);

3.8 新建表:poster_records

CREATE TABLE poster_records (
    id BIGSERIAL PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    product_id VARCHAR(50),
    case_upload_id BIGINT,
    template_id BIGINT,
    copy_mode VARCHAR(20),           -- template/ai
    copy_content TEXT,               -- JSON最终文案含用户编辑后版本
    ai_raw_content TEXT,             -- AI 原始文案(合规留痕,仅 AI 模式)
    export_url VARCHAR(500),
    export_format VARCHAR(10),       -- png/jpg
    export_size VARCHAR(20),         -- e.g. "1080x1920"
    reference_image_used VARCHAR(500), -- 使用的参考图(合规留痕)
    prompt_used TEXT,                -- 完整 prompt合规留痕
    created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_poster_records_user ON poster_records(user_id, created_at DESC);

3.9 新建配置表:system_settings(历史记录保存期限配置)

CREATE TABLE system_settings (
    id BIGSERIAL PRIMARY KEY,
    key VARCHAR(100) UNIQUE NOT NULL,
    value TEXT NOT NULL,
    description VARCHAR(500),
    updated_by VARCHAR(50),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- 种子数据
INSERT INTO system_settings (key, value, description) VALUES
('ppt_history_retention_days', '365', 'PPT 历史记录保留天数0=永久保留)'),
('poster_history_retention_days', '365', '海报历史记录保留天数0=永久保留)');

四、后端 API 设计

4.1 路由注册(纯增量,不改已有路由)

api/insurance/routes.pyregister_insurance_routes() 函数中追加:

# 管理后台 PPT/海报配置管理
from insurance.admin.ppt_admin_routes import ppt_admin_bp
app.register_blueprint(ppt_admin_bp, url_prefix="/insurance/admin/ppt")

# 海报功能
from insurance.poster.routes import poster_bp
app.register_blueprint(poster_bp, url_prefix="/insurance/poster")

4.2 管理后台 API/insurance/admin/ppt/

所有接口需 permission_required("config_manage")

保司管理

方法 路径 说明
GET /companies 列表(支持 status 筛选、keyword 搜索、分页)
POST /companies 新增保司
PUT /companies/{id} 编辑保司
PUT /companies/{id}/status 启用/停用(软删除)

产品管理

方法 路径 说明
GET /products 列表(支持 company_id、status、plan_type 筛选)
POST /products 新增产品
PUT /products/{id} 编辑产品
PUT /products/{id}/status 启用/停用
POST /products/{id}/manual/upload 上传产品小册子 PDF
POST /products/{id}/manual/parse 触发小册子 AI 解析
PUT /products/{id}/manual/review 人工核对并确认规则 → reviewed

PPT 模板管理

方法 路径 说明
GET /templates 列表
POST /templates 新增
PUT /templates/{id} 编辑
PUT /templates/{id}/status 启用/停用

海报模板管理

方法 路径 说明
GET /poster-templates 列表
POST /poster-templates 新增(含参考图上传)
PUT /poster-templates/{id} 编辑
PUT /poster-templates/{id}/status 启用/停用

文案模板管理

方法 路径 说明
GET /copy-templates 列表
POST /copy-templates 新增
PUT /copy-templates/{id} 编辑
DELETE /copy-templates/{id} 删除

历史记录管理

方法 路径 说明
GET /history 管理员查看全部 PPT+海报历史(支持 user_id/company_id/type 筛选)
GET /history/export 导出 CSV
DELETE /history/{id} 软删除(仅管理员)

系统配置

方法 路径 说明
GET /settings 获取系统配置(含历史保留天数)
PUT /settings 更新系统配置

4.3 PPT 历史记录 API追加到现有 /insurance/ppt/

在现有 ppt/routes.py 文件末尾追加路由函数,不改动已有代码:

方法 路径 说明
GET /ppt/history 当前用户的历史记录列表(分页、筛选)
GET /ppt/history/{id} 查看单条历史详情(含快照)
POST /ppt/history/{id}/re-download 重新下载

4.4 海报功能 API/insurance/poster/

所有接口需 @jwt_required

流程 API

方法 路径 说明
GET /products 获取已 reviewed 的产品列表(供选择)
POST /case-upload 上传计划书 PDF → 触发解析
GET /case-upload/{id} 获取解析结果
PUT /case-upload/{id}/confirm 人工核对/修正解析数据
GET /templates 获取可用海报模板列表
GET /copy-templates 获取可用文案模板列表
POST /generate-copy 生成文案(支持 template/ai 模式)
POST /generate 生成海报图片(调用 GPT image 模型)
GET /download/{record_id} 下载导出文件

记录 API

方法 路径 说明
GET /records 当前用户的海报生成记录
GET /records/{id} 记录详情

五、海报生成技术方案(纯 AI 生图)

5.1 整体流程

选择产品 → 上传计划书 → AI 解析 + 人工核对 → 选模板/参考图 → 选文案模式 → 组装 Prompt → 调用 GPT Image API → 返回海报图片 → 下载

5.2 Prompt 组装策略

生成海报时,系统组装以下信息为一个完整 prompt

【系统指令】
你是一位专业的保险营销海报设计师。请根据以下信息生成一张 {width}x{height} 的保险营销海报。

【风格要求】
{poster_template.style_description}
配色方案:{poster_template.color_scheme}
参考风格:(附上 reference_image如有

【产品信息】
产品名称:{product.display_name}
所属公司:{company.display_name}
产品亮点:{product.manual_parsed_rules.features}

【客户数据】
年龄:{case_upload.confirmed_data.age}
保费:{case_upload.confirmed_data.annual_premium}
保障期限:{case_upload.confirmed_data.coverage_period}
...

【营销文案】
{generated_copy}

【输出要求】
- 尺寸:{width}x{height} 像素
- 包含公司 Logo 位置(如可获取)
- 文字清晰可读,中文为主
- 符合保险行业专业风格

5.3 GPT Image API 调用

# poster/image_generator.py
import openai
import base64
import os

class PosterImageGenerator:
    """海报图片生成器,调用 GPT image 模型。"""

    def __init__(self):
        self.client = openai.OpenAI(
            api_key=os.getenv("OPENAI_API_KEY"),
        )

    def generate(self, prompt: str, size: str = "1024x1792") -> bytes:
        """
        调用 GPT image 模型生成海报图片。

        参数:
            prompt: 组装后的完整 prompt
            size: 图片尺寸,支持 "1024x1024" / "1024x1792" / "1792x1024"

        返回:
            PNG 图片的 bytes
        """
        response = self.client.images.generate(
            model="gpt-image-1",
            prompt=prompt,
            n=1,
            size=size,
        )
        # 解码 base64 图片
        image_base64 = response.data[0].b64_json
        return base64.b64decode(image_base64)

5.4 尺寸映射

用户选择的尺寸 → GPT image API 支持的尺寸:

用户选择 API 尺寸 说明
1080x1920竖版海报 1024x1792 最接近的 API 支持尺寸
900x500横版海报 1792x1024 最接近的 API 支持尺寸
1080x1080正方形 1024x1024 精确匹配
800x1200通用竖版 1024x1792 最接近的 API 支持尺寸
自定义 按比例选择最近尺寸 AI 图片生成后前端可裁剪/缩放

5.5 参考图处理

管理员上传的参考图(poster_templates.reference_image)在生成时:

  1. 将参考图作为 image 参数传入 GPT image API 的 edit 端点
  2. 或在 prompt 中描述参考图的风格特征(如果 API 不支持多图输入)

5.6 降级方案

如果 OpenAI image API 调用失败(网络/额度/限流):

  • 降级为 模板模式文案 + 基础排版图(使用 Pillow 生成简单的文字+色块海报)
  • 记录错误日志,提示用户重试

六、文案生成方案(双模式)

6.1 模板模式

  1. poster_copy_templates 选择文案模板
  2. case_upload.confirmed_data + product.manual_parsed_rules 填充 {{变量}} 占位符
  3. 不调用外部 API纯本地字符串替换
  4. 支持的变量示例:{{product_name}}{{annual_premium}}{{feature_1_title}}{{feature_1_summary}}

6.2 AI 模式

复用现有 ppt/llm_client.py 的多供应商 LLM 客户端:

# poster/copy_generator.py
from insurance.ppt.llm_client import llm_client

async def generate_ai_copy(product_rules: dict, customer_data: dict, style: str) -> dict:
    """
    调用 LLM 生成营销文案。

    返回:
        {"headline": "...", "body": "...", "call_to_action": "..."}
    """
    system_prompt = """你是一位专业的保险营销文案撰写人。
根据以下产品信息和客户数据,生成一张保险营销海报的文案。

要求:
1. 标题headline简短有力8字以内
2. 正文body突出产品亮点与客户需求的匹配50-100字
3. 行动号召call_to_action引导客户咨询15字以内
4. 风格:{style}
5. 必须基于真实数据,不得虚构收益数字

以 JSON 格式返回。"""

    user_prompt = f"""
产品信息:{json.dumps(product_rules, ensure_ascii=False)}
客户数据:{json.dumps(customer_data, ensure_ascii=False)}"""

    result = await llm_client.structured_output(
        system_prompt, user_prompt,
        schema={
            "type": "object",
            "properties": {
                "headline": {"type": "string"},
                "body": {"type": "string"},
                "call_to_action": {"type": "string"},
            },
            "required": ["headline", "body", "call_to_action"],
        }
    )
    return result

七、PDF 解析复用策略

7.1 计划书解析

复用 ppt/extraction.pyExtractionOrchestrator,新增精简 prompt

# 在 extraction.py 中新增方法
async def extract_for_poster(self, filepath: str) -> dict:
    """提取海报所需的关键字段(精简 prompt降低 LLM 成本)。"""
    # 使用更短的 prompt只提取
    # age, gender, currency, sum_assured, premium_term,
    # annual_premium, coverage_period, key_benefits
    ...

7.2 保司小册子解析

新增专门的解析 prompt

# poster/manual_parser.py
MANUAL_PARSE_PROMPT = """请从以下保险产品手册中提取产品规则和卖点信息。

输出 JSON 格式:
{
  "product_name": "产品名称",
  "features": [
    {"code": "唯一编码", "title": "卖点标题", "summary": "一句话描述"}
  ],
  "currency_options": ["USD", "HKD"],
  "coverage_highlights": ["保障亮点1", "保障亮点2"]
}
"""

八、权限设计

复用现有 5 级角色体系,不新增角色:

操作 super_admin admin manager sales client
PPT 生成
PPT 历史(自己)
海报生成
海报历史(自己)
保司/产品/模板管理
全部历史查看 本部门 仅自己
历史删除
系统配置(保留天数)

管理接口统一使用 permission_required("config_manage"),与现有 LLM 配置、通知渠道等管理接口权限一致。


九、前端设计

9.1 路由新增

// 用户端(需 auth
{ path: '/ppt/history', component: PptHistoryPage }       // PPT 历史记录
{ path: '/poster', component: PosterPage }                 // 海报生成向导
{ path: '/poster/history', component: PosterHistoryPage }  // 海报历史记录

// 管理端(需 auth + admin + config_manage 权限)
{ path: '/admin/ppt/companies', component: PptCompaniesAdmin }
{ path: '/admin/ppt/products', component: PptProductsAdmin }
{ path: '/admin/ppt/templates', component: PptTemplatesAdmin }
{ path: '/admin/ppt/poster-templates', component: PosterTemplatesAdmin }
{ path: '/admin/ppt/copy-templates', component: CopyTemplatesAdmin }
{ path: '/admin/ppt/history', component: PptHistoryAdmin }
{ path: '/admin/ppt/settings', component: PptSettingsAdmin }

9.2 侧边栏更新App.vue

功能菜单:
  - 智能问答(已有,不变)
  - 建议书生成(已有,不变)
  - 建议书历史(新增)
  - 海报生成(新增)
  - 海报历史(新增)

系统管理:
  - ...(已有项全部不变)
  - PPT/海报配置(新增折叠子菜单):
    - 保司管理
    - 产品管理
    - PPT 模板管理
    - 海报模板管理
    - 文案模板管理
    - 生成历史
    - 系统设置

9.3 PPT 前端优化(需求 1.1,增量修改现有组件)

骨架屏:在 PptUpload/PptParsing/PptGenerate 组件中添加 <el-skeleton> 包裹,数据加载完成前显示骨架屏。

移动端触屏优化

  • PptUpload拖拽区域增加 min-height: 120px,点击区域扩大
  • PptGenerate样式卡片确保 min-width: 140px
  • 所有按钮增加 min-height: 44pxiOS 推荐触屏最小尺寸)
  • 表单输入框增加 font-size: 16px(防止 iOS 自动缩放)

导出进度反馈:在 PptResult.vue 的下载按钮处增加 <el-progress> 条。

断点:继续使用现有 useMobile() composable768px 断点)。

9.4 PPT 历史记录页面

新建 PptHistoryPage.vue

  • 表格列:时间、保司、产品、操作类型、文件、操作(查看/重新下载)
  • 筛选栏:保司下拉、操作类型下拉、日期范围
  • 分页:复用 el-pagination
  • 点击"查看"弹出 el-dialog 展示 content_snapshot 的格式化视图

9.5 海报生成页面

新建 PosterPage.vue,采用与 PptPage 相同的 el-steps 向导模式:

Step 1 - 选择产品:展示已 reviewed 的产品卡片列表(按保司分组),未 reviewed 的产品灰显不可选。

Step 2 - 上传计划书

  • 拖拽上传 PDF
  • 解析进度(复用 PptParsing 的进度 UI 模式)
  • 解析结果表单:逐字段展示,置信度低的字段高亮,用户可编辑修正
  • 确认按钮

Step 3 - 选择模板 + 文案

  • 海报模板选择:卡片网格,含预览图和风格描述
  • 配色方案展示(从模板继承,可手动调整)
  • 文案模式切换:
    • 模板模式:选择文案模板 → 实时预览填充结果
    • AI 模式:点击"生成文案" → 展示 AI 生成的文案headline/body/call_to_action→ 可编辑
  • 参考图上传(可选,用户可上传自己的参考图覆盖模板默认图)

Step 4 - 预览与导出

  • 点击"生成海报" → 显示加载状态AI 生图需要 10-30 秒)
  • 海报图片预览
  • 尺寸选择下拉
  • 下载按钮

9.6 管理后台页面

每个管理页面遵循现有 admin 页面模式(表格 + 弹窗编辑):

  • PptCompaniesAdmin:表格 + 搜索/状态筛选 + 新增/编辑弹窗(含 Logo 上传)
  • PptProductsAdmin:表格 + 保司/类型/状态筛选 + 编辑弹窗(含小册子上传区域、规则核对表单)
  • PptTemplatesAdmin:表格 + 编辑弹窗(名称、场景标签、预览图上传、适用范围多选)
  • PosterTemplatesAdmin:表格 + 编辑弹窗(风格描述、配色方案编辑器、参考图上传、预览图)
  • CopyTemplatesAdmin:表格 + 编辑弹窗(文案内容编辑、变量说明、场景标签)
  • PptHistoryAdmin:只读表格 + 筛选 + 导出 CSV + 删除按钮
  • PptSettingsAdmin:简单表单,配置历史记录保留天数

十、文件结构

后端新增文件

api/insurance/
├── db/
│   ├── migrate_015.py                 # 新表创建 + 现有表扩展
│   └── migrate_016.py                 # 种子数据(系统配置默认值)
├── models/
│   ├── ppt_history.py                 # PptHistory 模型
│   ├── poster_case_upload.py          # PosterCaseUpload 模型
│   ├── poster_template_model.py       # PosterTemplate 模型
│   ├── poster_copy_template.py        # PosterCopyTemplate 模型
│   ├── poster_record.py               # PosterRecord 模型
│   └── system_setting.py              # SystemSetting 模型
├── admin/
│   ├── ppt_admin_routes.py            # PPT/海报管理后台路由(新建)
│   └── ppt_admin_service.py           # PPT/海报管理后台服务(新建)
├── poster/
│   ├── __init__.py                    # 包初始化
│   ├── routes.py                      # 海报功能路由
│   ├── service.py                     # 海报业务逻辑
│   ├── copy_generator.py             # 文案生成(模板 + AI 双模式)
│   ├── image_generator.py            # GPT image API 调用
│   └── manual_parser.py              # 保司小册子解析 prompt
└── ppt/
    └── routes.py                      # 末尾追加历史记录路由(不改已有代码)

前端新增文件

frontend/src/
├── pages/
│   ├── PptHistoryPage.vue             # PPT 历史记录
│   ├── PosterPage.vue                 # 海报生成向导
│   ├── PosterHistoryPage.vue          # 海报历史记录
│   └── admin/
│       ├── PptCompaniesAdmin.vue      # 保司管理
│       ├── PptProductsAdmin.vue       # 产品管理
│       ├── PptTemplatesAdmin.vue      # PPT 模板管理
│       ├── PosterTemplatesAdmin.vue   # 海报模板管理
│       ├── CopyTemplatesAdmin.vue     # 文案模板管理
│       ├── PosterHistoryAdmin.vue     # 生成历史管理
│       └── PptSettingsAdmin.vue       # 系统设置
├── components/poster/
│   ├── PosterStepProduct.vue          # Step1: 选择产品
│   ├── PosterStepUpload.vue           # Step2: 上传计划书
│   ├── PosterStepTemplate.vue         # Step3: 选模板+文案
│   └── PosterStepPreview.vue          # Step4: 预览导出
├── utils/
│   ├── poster-api.ts                  # 海报 API 封装
│   └── ppt-admin-api.ts              # PPT 管理 API 封装

十一、迁移脚本migrate_015

"""迁移 015: PPT/海报功能扩展。"""
def migrate():
    from insurance.db.compat import db
    from sqlalchemy import text

    # 1. 扩展 insurance_ppt_companies
    for col in ["logo_url VARCHAR(500)", "status SMALLINT DEFAULT 1", "sort_order INTEGER DEFAULT 0"]:
        try:
            db.session.execute(text(f"ALTER TABLE insurance_ppt_companies ADD COLUMN {col}"))
        except Exception:
            pass  # 已存在则跳过
    # 现有数据默认启用
    db.session.execute(text("UPDATE insurance_ppt_companies SET status = 1 WHERE status IS NULL"))

    # 2. 扩展 insurance_ppt_products15+ 字段)
    ...

    # 3. 扩展 insurance_ppt_templates6 字段)
    ...

    # 4. 创建 insurance_ppt_history
    ...

    # 5. 创建 poster_case_uploads
    ...

    # 6. 创建 poster_templatesAI 生图方案)
    ...

    # 7. 创建 poster_copy_templates
    ...

    # 8. 创建 poster_records
    ...

    # 9. 创建 system_settings
    ...

    db.session.commit()

所有 ALTER TABLE 使用 try/except 包裹,保证幂等。


十二、实施计划(分 4 个阶段)

阶段 1数据库 + 后台管理(优先级最高)

后端

  • migrate_015创建新表 + 扩展旧表
  • 5 个新 SQLAlchemy 模型 + 1 个 SystemSetting 模型
  • admin CRUD 接口ppt_admin_routes.py + ppt_admin_service.py

前端

  • 7 个管理页面(保司/产品/PPT模板/海报模板/文案模板/历史/设置)
  • 侧边栏更新
  • API 封装ppt-admin-api.ts

验证:后台能正常增删改查保司、产品、模板数据;现有 PPT 生成功能不受影响。

阶段 2PPT 前端优化 + 历史记录

后端

  • PptHistory 模型
  • 在 ppt/routes.py 末尾追加历史记录路由
  • 在 PPT 生成/下载流程中自动记录历史

前端

  • PptPage 各子组件骨架屏、触屏优化、导出进度
  • PptHistoryPage.vue

验证PPT 生成流程正常,历史记录自动写入并可查询。

阶段 3海报核心功能

后端

  • PosterCaseUpload 模型 + 计划书上传/解析/确认 API
  • copy_generator.py文案生成模板模式 + AI 模式)
  • image_generator.pyGPT image API 调用)
  • manual_parser.py小册子解析 prompt
  • 海报生成完整流程 API

前端

  • PosterPage.vue 4 步向导
  • 4 个 Step 子组件

验证:完整海报生成流程可用(选产品 → 上传计划书 → 核对 → 选模板 → 生成文案 → 生成海报 → 下载)。

阶段 4海报历史 + 管理 + 合规

后端

  • PosterRecord 模型 + 记录 API
  • 历史删除 + 保留天数配置
  • AI 文案留痕ai_raw_content + copy_content 双版本)

前端

  • PosterHistoryPage.vue
  • PosterHistoryAdmin.vue
  • PptSettingsAdmin.vue

验证:全链路测试通过,合规留痕完整。


十三、风险与缓解

风险 影响 缓解措施
GPT image API 限流/费用高 海报生成不可用或成本超预期 降级为 Pillow 基础排版图;记录调用量监控
AI 生图文字渲染不清晰 海报中文/数字模糊 Prompt 中强调"文字清晰可读";可后期叠加文字层
PDF 解析精度不够 计划书数据错误 人工核对表单兜底,标记低置信度字段
现有 PPT 功能被破坏 用户无法生成 PPT 所有改动纯增量,不修改已有路由/模型字段定义
海报模板/参考图不足 初期无可用模板 先做 2-3 个基础模板,后续迭代
AI 文案合规风险 营销内容违规 双版本留痕ai_raw_content + 最终版)+ 人工编辑确认
OpenAI API Key 过期/额度不足 海报生成中断 前端显示明确错误提示 + 重试按钮;后台显示额度监控

十四、后续可扩展方向

  • 增加 medical/annuity/life 产品类型(只需新增 extraction prompt + normalizer
  • 海报批量生成(多客户一次导出)
  • 海报分享链接(生成带水印的预览图 + 专属链接)
  • 模板市场(管理员上传模板后其他用户可选用)
  • PPT 历史记录的"一键重新生成"功能