You need to sign in or sign up before continuing.
SavingsTemplate.vue 7.04 KB
<template>
  <div>
    <!-- 性别 -->
    <PlanFieldRadio
      v-model="form.gender"
      label="性别"
      :options="['男', '女']"
    />

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

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

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

    <!-- 保额 -->
    <PlanFieldAmount
      v-model="form.coverage"
      label="保额"
      placeholder="请输入保额"
      :currency="config.currency"
    />

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

    <!-- 保险期间 -->
    <div class="flex justify-between items-start mb-5">
      <span class="text-sm text-gray-600 mt-1.5">保险期间</span>
      <div class="bg-blue-50 rounded-md px-3 py-1.5">
        <span class="text-sm text-blue-600">{{ config.insurance_period }}</span>
      </div>
    </div>

    <!-- ====== 提取计划功能(储蓄产品专用)====== -->
    <div v-if="config.withdrawal_plan?.enabled" class="mt-6 pt-6 border-t border-gray-200">
      <div class="text-base font-medium text-gray-900 mb-4">提取计划</div>

      <!-- 提取方式选择 -->
      <PlanFieldRadio
        v-model="form.withdrawal_plan.mode"
        label="提取方式"
        :options="config.withdrawal_plan.withdrawal_modes"
      />

      <!-- 开始年龄 -->
      <PlanFieldAgePicker
        v-model="form.withdrawal_plan.start_age"
        label="开始年龄"
        placeholder="请选择开始提取年龄"
      />

      <!-- 提取年期 -->
      <PlanFieldSelect
        v-model="form.withdrawal_plan.withdrawal_period"
        label="提取年期"
        placeholder="请选择提取年期"
        :options="config.withdrawal_plan.withdrawal_periods"
      />

      <!-- 方式1:年龄指定金额 - 额外字段 -->
      <template v-if="form.withdrawal_plan.mode === '年龄指定金额'">
        <!-- 每年提取金额 -->
        <PlanFieldAmount
          v-model="form.withdrawal_plan.annual_amount"
          label="每年提取金额"
          placeholder="请输入金额"
          :currency="form.withdrawal_plan.currency || config.withdrawal_plan.default_currency"
        />

        <!-- 币种 -->
        <div class="mb-5">
          <div class="text-sm text-gray-600 mb-2">币种</div>
          <div class="flex gap-2">
            <button
              v-for="curr in currencyOptions"
              :key="curr.value"
              :class="[
                'px-4 py-2 rounded-lg text-sm border transition-colors',
                (form.withdrawal_plan.currency || config.withdrawal_plan.default_currency) === curr.value
                  ? 'bg-blue-600 text-white border-blue-600'
                  : 'bg-white text-gray-600 border-gray-200'
              ]"
              @tap="selectCurrency(curr.value)"
            >
              {{ curr.label }}
            </button>
          </div>
        </div>

        <!-- 增加率 -->
        <div class="mb-5">
          <div class="text-sm text-gray-600 mb-2">增加率(%</div>
          <nut-input
            v-model="form.withdrawal_plan.increase_rate"
            type="digit"
            placeholder="请输入增加率"
            class="border border-gray-200 rounded-lg"
          />
        </div>
      </template>
    </div>
  </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 - 提取计划配置
   */
  config: {
    type: Object,
    required: true
  }
})

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

/**
 * 表单数据
 * @type {Object}
 */
const form = reactive(props.modelValue || {
  // 初始化提取计划数据
  withdrawal_plan: {
    mode: '年龄指定金额',
    start_age: null,
    withdrawal_period: null,
    annual_amount: null,
    currency: props.config?.withdrawal_plan?.default_currency || 'HKD',
    increase_rate: 0
  }
})

/**
 * 币种选项(用于提取计划)
 * @type {ComputedRef<Array>}
 */
const currencyOptions = computed(() => {
  const CURRENCY_MAP = {
    HKD: { label: '港币', value: 'HKD' },
    USD: { label: '美元', value: 'USD' },
    CNY: { label: '人民币', value: 'CNY' }
  }

  const supportedCurrencies = props.config?.withdrawal_plan?.currencies || ['HKD']
  return supportedCurrencies
    .map(code => CURRENCY_MAP[code])
    .filter(Boolean)
})

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

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

    // 自动填充年龄字段
    form.age = calculatedAge
  }
}

/**
 * 选择币种(用于提取计划)
 * @param {string} currencyCode - 币种代码
 */
const selectCurrency = (currencyCode) => {
  if (form.withdrawal_plan) {
    form.withdrawal_plan.currency = currencyCode
  }
}
</script>

<style lang="less" scoped>
/* 模版样式 */
</style>