plan-form-schema-usage.md 9.1 KB

计划书表单 Schema 使用文档

1. 文档目标

用于说明计划书表单的 Schema 配置规范、字段类型、联动规则与提交映射,便于后续新增或扩展不同保险类型时快速落地。

2. 核心思路

  • 统一由 Schema 描述字段渲染、校验与联动
  • 统一由 submit_mapping 处理字段到 API 字段的映射与金额转换
  • 模板组件只负责“渲染与校验”,不再硬编码字段逻辑

3. Schema 结构

// Schema 基础结构
const form_schema = {
    // 基础字段
    base_fields: [
        {
            id: 'customer_name',
            key: 'customer_name',
            type: 'name',
            label: '申请人',
            placeholder: '请输入申请人',
            required: true
        }
    ],
    // 提取计划字段(可选)
    withdrawal_fields: [],
    // 联动清空规则(可选)
    reset_map: {}
}

4. 字段类型说明

type 组件 说明
name NameInput 姓名输入
radio RadioGroup 单选
date DatePickerGlobal 日期选择
amount AmountKeyboard 金额键盘输入(内部存分)
age AgePickerGlobal 年龄选择
select SelectPickerGlobal 下拉选择
payment_period PaymentPeriodRadio 缴费年期
percentage NutInput 百分比输入

5. 字段属性说明

// 字段属性示例
{
    id: 'coverage',
    key: 'coverage',
    type: 'amount',
    label: '年缴保费',
    placeholder: '请输入年缴保费',
    input_label: '请输入年缴保费金额',
    required: true,
    // 可从配置读取币种
    currency_from: 'currency',
    // 控制显示条件
    show_when: [{ field: 'withdrawal_mode', equals: '指定提取金额' }],
    // 默认值
    default: '否',
    // 标题分组
    section_title: '款项提取(允许减少名义金额)'
}

6. 联动规则与清空逻辑

// 提取模式切换后,按规则清空脏字段
const reset_map = {
    withdrawal_mode: {
        '最高固定提取金额': ['annual_withdrawal_amount', 'annual_increase_percentage', 'withdrawal_start_age', 'withdrawal_period'],
        '指定提取金额': ['withdrawal_start_age', 'withdrawal_period']
    }
}

7. 提交字段映射

// submit_mapping 示例(金额字段统一从分转元)
const submit_mapping = {
    annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' },
    annual_withdrawal_amount: { api_field: 'annual_withdrawal_amount', transform: 'fen_to_yuan' },
    withdrawal_mode: { api_field: 'withdrawal_option' }
}

8. 解析输出结构

解析脚本输出 JSON 用于生成 plan-templates 配置,字段结构与 form_schemasubmit_mapping 对齐:

{
    product_name: '宏挚传承保障计划',
    product_type: 'savings',
    form_sn: 'savings-hong-zhi-chuan-cheng-abcdef12',
    currency: 'USD',
    payment_periods: ['整付', '3年', '5年'],
    age_range: { min: 0, max: 75 },
    insurance_period: '终身',
    is_savings: true,
    withdrawal_modes: ['年龄指定金额', '最高固定金额'],
    withdrawal_periods: ['1年', '3年', '5年', '10年'],
    form_schema: { base_fields: [], withdrawal_fields: [], reset_map: {} },
    submit_mapping: { annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' } },
    source_file: '产品说明书.pdf',
    warnings: []
}

字段约束与可选项:

  • 必填:product_nameproduct_typecurrencypayment_periodsage_rangeinsurance_period
  • 可选:form_snis_savingswithdrawal_modeswithdrawal_periodsform_schemasubmit_mappingsource_filewarnings
  • form_sn 若未传入,按规则自动生成稳定值
  • payment_periods 必须为非空数组
  • age_range.minage_range.max
  • 储蓄产品需提供 withdrawal_modeswithdrawal_periods

9. 使用示例

<!-- 储蓄型模板使用示例 -->
<template>
    <SavingsTemplate v-model="form_data" :config="template_config" />
</template>

<script setup>
// 表单数据
const form_data = ref({})

// 模板配置(通常来自 plan-templates.js)
const template_config = {
    currency: 'USD',
    payment_periods: ['整付', '5 年'],
    withdrawal_plan: {
        enabled: true,
        default_currency: 'USD',
        withdrawal_periods: ['1年', '2年', '终身']
    },
    form_schema: {},
    submit_mapping: {}
}
</script>

9.1 人寿/重疾模板使用示例

<template>
    <LifeInsuranceTemplate v-model="form_data" :config="template_config" />
</template>

<script setup>
const form_data = ref({})

const template_config = {
    currency: 'USD',
    payment_periods: ['整付(0-75 岁)', '5 年(0-70 岁)'],
    form_schema: protectionFormSchema,
    submit_mapping: baseSubmitMapping
}
</script>

10. 新增保险类型流程

  1. src/config/plan-templates.js 新增产品项(配置 form_sn)
  2. 为该产品选择已有模板组件或新增模板组件
  3. 定义 form_schemasubmit_mapping
  4. 在模板组件内使用 Schema 渲染(仅需接入通用逻辑)
  5. 验证校验与提交映射

11. 新增产品配置示例

// 示例:新增储蓄类产品配置
'savings-new': {
    name: '示例储蓄产品',
    component: 'SavingsTemplate',
    category: 'savings',
    config: {
        currency: 'USD',
        payment_periods: ['整付', '5 年'],
        withdrawal_plan: {
            enabled: true,
            default_currency: 'USD',
            withdrawal_periods: ['1年', '2年', '终身']
        },
        form_schema: savingsFormSchema,
        submit_mapping: savingsSubmitMapping
    }
}
// 示例:新增人寿/重疾类产品配置
'life-insurance-new': {
    name: '示例人寿产品',
    component: 'LifeInsuranceTemplate',
    config: {
        currency: 'USD',
        payment_periods: ['整付(0-75 岁)'],
        form_schema: protectionFormSchema,
        submit_mapping: baseSubmitMapping
    }
}

12. 常见扩展点

  • 新字段:仅在 form_schema 增加字段并补充 submit_mapping
  • 新联动:在 show_when 与 reset_map 中定义条件
  • 新模板:复用现有字段组件,保持 schema 结构一致

13. 计划书模块入口与配置地图

13.1 页面入口

  • 产品详情:src/pages/product-detail/index.vue(按钮打开计划书弹窗)
  • 产品中心:src/pages/product-center/index.vue(列表内“计划书”按钮)
  • 搜索页:src/pages/search/index.vue(搜索结果卡片“计划书”按钮)
  • 计划书列表:src/pages/plan/index.vue(查看/删除计划书)
  • 提交结果页:src/pages/plan-submit-result/index.vue

13.2 组件与模板

  • 弹窗容器:src/components/plan/PlanPopupNew.vue
  • 计划书容器:src/components/plan/PlanFormContainer.vue
  • 模板组件:
    • src/components/plan/PlanTemplates/LifeInsuranceTemplate.vue
    • src/components/plan/PlanTemplates/CriticalIllnessTemplate.vue
    • src/components/plan/PlanTemplates/SavingsTemplate.vue
  • 字段组件:src/components/plan/PlanFields/*

13.3 配置与数据处理

  • 模板映射:src/config/plan-templates.js
  • 字段定义与映射:src/config/plan-fields.js
  • 字段转换函数:src/utils/planFieldTransformers.js
  • 字段转换入口:src/composables/useFieldValueTransform.js
  • 字段联动规则:src/composables/useFieldDependencies.js
  • 字段校验工具:src/utils/planFieldValidation.js
  • 订单状态常量:src/config/constants/orderStatus.js

13.4 API 入口

  • 计划书 API:src/api/plan.js
    • 新增:addAPI
    • 列表:listAPI
    • 删除:deleteAPI
    • 查看:viewAPI

13.5 技术书/附件预览关联

  • 产品详情附件列表:src/pages/product-detail/index.vue
  • 文件预览能力:src/composables/useFileOperation.js

14. 计划书模块使用流程

  1. 产品详情/产品中心/搜索页获取产品对象(至少包含 idform_sn,可选 plan_config
  2. 打开 PlanFormContainer 并传入 product
  3. PlanFormContainer 根据 form_snplan-templates 选择模板并合并 plan_config
  4. 模板组件基于 form_schema 渲染字段,调用自身 validate 完成校验
  5. 提交时使用 submit_mapping 生成请求参数,并通过 addAPI 提交
  6. 提交完成后通过 usePlanSubmit 跳转到提交结果页
  7. 在计划书列表中用 listAPI 拉取数据,使用 viewAPI 标记为已查看

15. 计划书容器使用示例

<template>
    <PlanFormContainer
        v-model:visible="show_plan_popup"
        :product="selected_product"
        @close="show_plan_popup = false"
        @submit="handle_plan_submit"
    />
</template>

<script setup>
import { ref } from 'vue'
import PlanFormContainer from '@/components/plan/PlanFormContainer.vue'
import { usePlanSubmit } from '@/composables/usePlanSubmit'

const show_plan_popup = ref(false)
const selected_product = ref(null)

const { handlePlanSubmit: handle_plan_submit } = usePlanSubmit({
    getPopupState: () => show_plan_popup.value,
    setPopupState: (state) => { show_plan_popup.value = state },
    pageName: 'Plan Entry'
})
</script>