SavingsTemplate.vue 10.8 KB
<template>
  <div v-if="config">
    <!-- 性别 -->
    <PlanFieldRadio
      v-model="form.gender"
      label="性别"
      :options="['男', '女']"
      class="mb-5"
    />

    <!-- 出生年月日 -->
    <PlanFieldDatePicker
      v-model="form.birthday"
      label="出生年月日"
      placeholder="请选择日期"
      @change="onBirthdayChange"
      class="mb-5"
    />

    <!-- 年龄(根据出生日期自动计算,可编辑) -->
    <PlanFieldAgePicker
      v-model="form.age"
      label="年龄"
      placeholder="请选择出生日期自动计算"
      class="mb-5"
    />

    <!-- 是否吸烟 -->
    <PlanFieldRadio
      v-model="form.smoker"
      label="是否吸烟"
      :options="['是', '否']"
      class="mb-5"
    />

    <!-- 保额(年缴保费) -->
    <PlanFieldAmount
      v-model="form.coverage"
      label="年缴保费"
      placeholder="请输入年缴保费"
      :currency="config.currency"
      class="mb-5"
    />

    <!-- 缴费年期 -->
    <PlanFieldSelect
      v-model="form.payment_period"
      label="缴费年期"
      placeholder="请选择缴费年期"
      :options="config.payment_periods"
      class="mb-5"
    />

    <!-- 分割线 -->
    <div class="border-t border-gray-200 my-6"></div>

    <!-- 提取计划配置 -->
    <div v-if="config.withdrawal_plan?.enabled" class="withdrawal-plan-section">
      <!-- 第一层:是否希望生成一份容许减少名义金额的提取说明? -->
      <PlanFieldRadio
        v-model="form.withdrawal_enabled"
        label="是否希望生成一份容许减少名义金额的提取说明?"
        :options="['是', '否']"
        class="mb-5"
      />

      <!-- 仅当选择"是"时才显示以下内容 -->
      <template v-if="form.withdrawal_enabled === '是'">
        <h3 class="text-base font-semibold text-gray-900 mb-4">款项提取(容许减少名义金额)</h3>

        <!-- 提取选项:指定提取金额 / 最高固定提取金额 -->
        <PlanFieldRadio
          v-model="form.withdrawal_mode"
          label="提取选项"
          :options="['指定提取金额', '最高固定提取金额']"
          @change="onWithdrawalModeChange"
          class="mb-5"
        />

        <!-- 指定提取金额模式 -->
        <template v-if="form.withdrawal_mode === '指定提取金额'">
          <!-- 按年岁/按保单年度选择 -->
          <PlanFieldRadio
            v-model="form.specified_amount_type"
            label="提取方式"
            :options="['按年岁', '按保单年度']"
            class="mb-5"
          />

          <!-- 按年岁 -->
          <template v-if="form.specified_amount_type === '按年岁'">
            <!-- 由几岁开始 -->
            <PlanFieldAgePicker
              v-model="form.withdrawal_start_age"
              label="由几岁开始"
              placeholder="请输入开始提取年龄"
              class="mb-5"
            />

            <!-- 提取期(年) -->
            <PlanFieldSelect
              v-model="form.withdrawal_period"
              label="提取期(年)"
              placeholder="请选择提取期"
              :options="withdrawalPeriods"
              class="mb-5"
            />

            <!-- 每年递增提取之百分比 -->
            <div class="mb-5">
              <div class="text-sm text-gray-700 mb-2">每年递增提取之百分比(%</div>
              <nut-input
                v-model="form.increase_rate"
                type="digit"
                placeholder="请输入递增百分比"
                class="w-full"
              />
            </div>
          </template>

          <!-- 按保单年度 -->
          <template v-if="form.specified_amount_type === '按保单年度'">
            <!-- 由几岁开始 -->
            <PlanFieldAgePicker
              v-model="form.withdrawal_start_age"
              label="由几岁开始"
              placeholder="请输入开始提取年龄"
              class="mb-5"
            />

            <!-- 提取期(年) -->
            <PlanFieldSelect
              v-model="form.withdrawal_period"
              label="提取期(年)"
              placeholder="请选择提取期"
              :options="withdrawalPeriods"
              class="mb-5"
            />
          </template>
        </template>

        <!-- 最高固定提取金额模式 -->
        <template v-if="form.withdrawal_mode === '最高固定提取金额'">
          <!-- 按年岁:由几岁开始 -->
          <PlanFieldAgePicker
            v-model="form.withdrawal_start_age"
            label="按年岁:由几岁开始"
            placeholder="请输入开始提取年龄"
            class="mb-5"
          />

          <!-- 提取期(年) -->
          <PlanFieldSelect
            v-model="form.withdrawal_period"
            label="提取期(年)"
            placeholder="请选择提取期"
            :options="withdrawalPeriods"
            class="mb-5"
          />
        </template>
      </template>
    </div>
  </div>

  <!-- 配置缺失提示 -->
  <div v-else class="text-center text-gray-500 py-10">
    <p>⚠️ 模版配置未找到</p>
    <p class="text-sm mt-2">请检查产品配置或联系开发人员</p>
  </div>
</template>

<script setup>
/**
 * 储蓄型保险计划书模版
 *
 * @description GS/GC/FA/LV2 等储蓄型保险产品的计划书录入表单
 *              - 支持出生日期自动计算年龄
 *              - 支持提取计划配置(多种提取模式和方式)
 *              - 表单字段:性别、年龄、出生年月日、是否吸烟、保额、缴费年期
 *              - 提取计划:指定提取金额(按年岁/按保单年度)、最高固定提取金额
 *              - 小程序端币种固定(使用配置中的默认币种)
 * @author Claude Code
 * @example
 * <SavingsTemplate
 *   v-model="formData"
 *   :config="templateConfig"
 * />
 */
import { reactive, watch, computed } from 'vue'
import PlanFieldAgePicker from '../PlanFields/AgePicker.vue'
import PlanFieldAmount from '../PlanFields/AmountInput.vue'
import PlanFieldDatePicker from '../PlanFields/DatePicker.vue'
import PlanFieldRadio from '../PlanFields/RadioGroup.vue'
import PlanFieldSelect from '../PlanFields/SelectPicker.vue'

/**
 * 组件属性
 */
const props = defineProps({
  /**
   * 表单数据对象
   * @type {Object}
   */
  modelValue: {
    type: Object,
    default: () => ({})
  },

  /**
   * 模版配置
   * @type {Object}
   * @property {string} currency - 币种代码
   * @property {Array<string>} payment_periods - 缴费年期选项
   * @property {Object} age_range - 年龄范围 { min, max }
   * @property {string} insurance_period - 保险期间
   * @property {Object} withdrawal_plan - 提取计划配置
   * @property {boolean} withdrawal_plan.enabled - 是否启用提取计划
   * @property {Array<string>} withdrawal_plan.currencies - 支持的币种
   * @property {string} withdrawal_plan.default_currency - 默认币种
   * @property {Array<string>} withdrawal_plan.withdrawal_modes - 提取模式
   * @property {Array<string>} withdrawal_plan.withdrawal_periods - 提取年期
   */
  config: {
    type: Object,
    required: true
  }
})

/**
 * 组件事件
 */
const emit = defineEmits([
  /**
   * 更新表单数据事件
   * @event update:modelValue
   * @param {Object} value - 表单数据
   */
  'update:modelValue'
])

/**
 * 表单数据
 * @type {Object}
 */
const form = reactive({
  ...props.modelValue,
  // 默认值
  withdrawal_enabled: props.modelValue.withdrawal_enabled || '否',
  withdrawal_mode: props.modelValue.withdrawal_mode || '指定提取金额',
  specified_amount_type: props.modelValue.specified_amount_type || '按年岁'
})

/**
 * 监听表单数据变化,同步到父组件
 */
watch(
  () => form,
  (newVal) => emit('update:modelValue', newVal),
  { deep: true }
)

/**
 * 默认币种(从配置读取)
 * @type {ComputedRef<string>}
 */
const defaultCurrency = computed(() => {
  return props.config?.withdrawal_plan?.default_currency || 'HKD'
})

/**
 * 提取年期选项(从配置读取)
 * @type {ComputedRef<Array<string>>}
 */
const withdrawalPeriods = computed(() => {
  return props.config?.withdrawal_plan?.withdrawal_periods || [
    '1年',
    '2年',
    '3年',
    '5年',
    '10年',
    '15年',
    '20年',
    '终身'
  ]
})

/**
 * 出生日期变化时自动计算年龄
 * @param {string} birthday - 出生日期(格式:YYYY-MM-DD)
 *
 * @description 用户选择出生日期后,自动计算并填充年龄字段
 *              计算公式:当前年份 - 出生年份
 */
const onBirthdayChange = (birthday) => {
  if (birthday) {
    // 兼容 iOS 的日期格式 (YYYY/MM/DD)
    const dateStr = birthday.replace(/-/g, '/')
    const birthDate = new Date(dateStr)

    if (!Number.isNaN(birthDate.getTime())) {
      const birthYear = birthDate.getFullYear()
      const currentYear = new Date().getFullYear()
      const calculatedAge = currentYear - birthYear

      // 自动填充年龄字段(确保非负)
      form.age = Math.max(0, calculatedAge)
    }
  }
}

/**
 * 提取模式变化时的处理
 * @param {string} mode - 新的提取模式
 *
 * @description 当用户切换提取模式时,清除不相关的字段
 *              - 切换到"指定提取金额":保留字段,等待用户选择子选项
 *              - 切换到"最高固定金额":清除指定金额相关字段
 */
const onWithdrawalModeChange = (mode) => {
  if (mode === '最高固定提取金额') {
    // 最高固定金额模式不需要指定金额的相关字段
    delete form.specified_amount_type
    delete form.annual_amount
    delete form.increase_rate
  } else if (mode === '指定提取金额') {
    // 指定提取金额模式,等待用户选择按年岁或按保单年度
    // 保留现有字段
  }
}

/**
 * 监听指定提取金额方式变化
 * @description 当用户在"按年岁"和"按保单年度"之间切换时,清理不相关字段
 */
watch(
  () => form.specified_amount_type,
  (newType) => {
    // 两种方式都不需要 annual_amount 和 increase_rate(小程序端不需要)
    delete form.annual_amount
    delete form.increase_rate
  }
)

/**
 * 监听提取计划启用状态变化
 * @description 当用户选择"否"时,清除所有提取计划相关字段
 */
watch(
  () => form.withdrawal_enabled,
  (newValue) => {
    if (newValue === '否') {
      // 清除所有提取计划相关字段
      delete form.withdrawal_mode
      delete form.specified_amount_type
      delete form.withdrawal_start_age
      delete form.withdrawal_period
      delete form.annual_amount
      delete form.increase_rate
    }
  }
)
</script>

<style lang="less" scoped>
/* 提取计划区域样式 */
.withdrawal-plan-section {
  /* 可以在这里添加特殊的样式 */
}
</style>