hookehuyr

refactor(plan): 移除年龄字段映射

- 从 PlanFormContainer.vue 的 fieldMapping 中移除 age → customer_age 映射
- 提交计划书时不再包含 customer_age 参数
- 保留 withdrawal_start_age 字段用于提取计划

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
......@@ -227,12 +227,7 @@ const close = async () => {
console.log('[PlanFormContainer] 弹窗已关闭,表单已重置')
}
/**
* 提交表单
* @description 将表单数据和产品信息提交到后端 API
*
* @returns {Promise<boolean>} 是否提交成功
*/
// 提交表单 - 将表单数据和产品信息提交到后端 API
const submit = async () => {
if (!props.product) {
console.error('[PlanFormContainer] 无法提交: 产品数据为空')
......@@ -264,7 +259,6 @@ const submit = async () => {
const fieldMapping = {
customer_name: 'customer_name', // 申请人(已直接使用)
gender: 'customer_gender', // 性别 → customer_gender
age: 'customer_age', // 年龄 → customer_age
birthday: 'customer_birthday', // 出生年月日 → customer_birthday
smoker: 'smoking_status', // 是否吸烟 → smoking_status
coverage: 'annual_premium', // 保额/年缴保费 → annual_premium
......
......@@ -18,23 +18,12 @@
class="mb-5"
/>
<!-- 年龄(主字段,选择后自动计算出生年月日) -->
<PlanFieldAgePicker
v-model="form.age"
label="年龄"
placeholder="请选择年龄"
:required="true"
@change="onAgeChange"
class="mb-5"
/>
<!-- 出生年月日(根据年龄自动计算,可手动调整) -->
<!-- 出生年月日 -->
<PlanFieldDatePicker
v-model="form.birthday"
label="出生年月日"
placeholder="请选择年月日"
:required="true"
@change="onBirthdayChange"
class="mb-5"
/>
......@@ -70,18 +59,17 @@
<!-- 配置缺失提示 -->
<div v-else class="text-center text-gray-500 py-10">
<p>⚠️ 配置未找到</p>
<p>⚠️ 配置未找到</p>
<p class="text-sm mt-2">请检查产品配置或联系开发人员</p>
</div>
</template>
<script setup>
/**
* 重疾保险计划书模
* 重疾保险计划书模
*
* @description MPC/MBC PRO/MBC2 等重疾保险产品的计划书录入表单
* - 支持出生日期自动计算年龄
* - 表单字段:性别、年龄、出生年月日、是否吸烟、保额、缴费年期
* - 表单字段:性别、出生年月日、是否吸烟、保额、缴费年期
* @author Claude Code
* @example
* <CriticalIllnessTemplate
......@@ -92,7 +80,6 @@
import { reactive, watch } from 'vue'
import Taro from '@tarojs/taro'
import PlanFieldName from '../PlanFields/NameInput.vue'
import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue'
import PlanFieldAmount from '../PlanFields/AmountKeyboard.vue'
import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue'
import PlanFieldRadio from '../PlanFields/RadioGroup.vue'
......@@ -112,7 +99,7 @@ const props = defineProps({
},
/**
* 模配置
* 模配置
* @type {Object}
* @property {string} currency - 币种代码
* @property {Array<string>} payment_periods - 缴费年期选项
......@@ -163,8 +150,8 @@ watch(
// 判断是否是重置(从有数据变为空对象)
const isReset = previousModelValue &&
Object.keys(previousModelValue).length > 0 &&
Object.keys(newVal).length === 0
Object.keys(previousModelValue).length > 0 &&
Object.keys(newVal).length === 0
if (isReset) {
// 父组件重置了:清空表单
......@@ -172,6 +159,7 @@ watch(
previousModelValue = newVal
} else {
// 正常更新:合并新字段,不删除已有字段
// 这很重要!因为用户可能刚填写了某些字段,其他字段还没更新
Object.keys(newVal).forEach(key => {
form[key] = newVal[key]
})
......@@ -191,49 +179,6 @@ watch(
)
/**
* 年龄变化时自动计算出生年月日
* @param {number} age - 年龄
*
* @description 用户选择年龄后,自动计算并填充出生日期字段
* 计算公式:当前年份 - 年龄 = 出生年份(默认1月1日)
*/
const onAgeChange = (age) => {
if (age !== undefined && age !== null && age !== '') {
const currentYear = new Date().getFullYear()
const birthYear = currentYear - age
// 格式化为 YYYY-MM-DD,默认使用1月1日
const month = String(1).padStart(2, '0')
const day = String(1).padStart(2, '0')
form.birthday = `${birthYear}-${month}-${day}`
}
}
/**
* 出生日期变化时自动计算年龄
* @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)
}
}
}
/**
* 表单校验
* @returns {boolean} 是否通过校验
*/
......@@ -250,10 +195,6 @@ const validate = () => {
Taro.showToast({ title: '请选择出生年月日', icon: 'none' })
return false
}
if (form.age === undefined || form.age === '') {
Taro.showToast({ title: '请填写年龄', icon: 'none' })
return false
}
if (!form.smoker) {
Taro.showToast({ title: '请选择是否吸烟', icon: 'none' })
return false
......@@ -286,5 +227,5 @@ defineExpose({
</script>
<style lang="less" scoped>
/* 模样式 */
/* 模样式 */
</style>
......
......@@ -18,23 +18,12 @@
class="mb-5"
/>
<!-- 年龄(主字段,选择后自动计算出生年月日) -->
<PlanFieldAgePicker
v-model="form.age"
label="年龄"
placeholder="请选择年龄"
:required="true"
@change="onAgeChange"
class="mb-5"
/>
<!-- 出生年月日(根据年龄自动计算,可手动调整) -->
<!-- 出生年月日 -->
<PlanFieldDatePicker
v-model="form.birthday"
label="出生年月日"
placeholder="请选择年月日"
:required="true"
@change="onBirthdayChange"
class="mb-5"
/>
......@@ -47,11 +36,11 @@
class="mb-5"
/>
<!-- 保额(年缴保费) -->
<!-- 保额 -->
<PlanFieldAmount
v-model="form.coverage"
label="年缴保费"
placeholder="请输入年缴保费"
label="保额"
placeholder="请输入保额"
:currency="config.currency"
:required="true"
class="mb-5"
......@@ -70,18 +59,17 @@
<!-- 配置缺失提示 -->
<div v-else class="text-center text-gray-500 py-10">
<p>⚠️ 配置未找到</p>
<p>⚠️ 配置未找到</p>
<p class="text-sm mt-2">请检查产品配置或联系开发人员</p>
</div>
</template>
<script setup>
/**
* 人寿保险计划书模
* 人寿保险计划书模
*
* @description WIOP3E/WIOP3 等人寿保险产品的计划书录入表单
* - 支持出生日期自动计算年龄
* - 表单字段:性别、年龄、出生年月日、是否吸烟、保额、缴费年期
* - 表单字段:性别、出生年月日、是否吸烟、保额、缴费年期
* @author Claude Code
* @example
* <LifeInsuranceTemplate
......@@ -92,7 +80,6 @@
import { reactive, watch, toRefs } from 'vue'
import Taro from '@tarojs/taro'
import PlanFieldName from '../PlanFields/NameInput.vue'
import PlanFieldAgePicker from '../PlanFields/AgePickerGlobal.vue'
import PlanFieldAmount from '../PlanFields/AmountKeyboard.vue'
import PlanFieldDatePicker from '../PlanFields/DatePickerGlobal.vue'
import PlanFieldRadio from '../PlanFields/RadioGroup.vue'
......@@ -112,7 +99,7 @@ const props = defineProps({
},
/**
* 模配置
* 模配置
* @type {Object}
* @property {string} currency - 币种代码
* @property {Array<string>} payment_periods - 缴费年期选项
......@@ -165,8 +152,8 @@ watch(
// 判断是否是重置(从有数据变为空对象)
const isReset = previousModelValue &&
Object.keys(previousModelValue).length > 0 &&
Object.keys(newVal).length === 0
Object.keys(previousModelValue).length > 0 &&
Object.keys(newVal).length === 0
if (isReset) {
// 父组件重置了:清空表单
......@@ -194,49 +181,6 @@ watch(
)
/**
* 年龄变化时自动计算出生年月日
* @param {number} age - 年龄
*
* @description 用户选择年龄后,自动计算并填充出生日期字段
* 计算公式:当前年份 - 年龄 = 出生年份(默认1月1日)
*/
const onAgeChange = (age) => {
if (age !== undefined && age !== null && age !== '') {
const currentYear = new Date().getFullYear()
const birthYear = currentYear - age
// 格式化为 YYYY-MM-DD,默认使用1月1日
const month = String(1).padStart(2, '0')
const day = String(1).padStart(2, '0')
form.birthday = `${birthYear}-${month}-${day}`
}
}
/**
* 出生日期变化时自动计算年龄
* @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)
}
}
}
/**
* 表单校验
* @returns {boolean} 是否通过校验
*/
......@@ -253,10 +197,6 @@ const validate = () => {
Taro.showToast({ title: '请选择出生年月日', icon: 'none' })
return false
}
if (form.age === undefined || form.age === '') {
Taro.showToast({ title: '请填写年龄', icon: 'none' })
return false
}
if (!form.smoker) {
Taro.showToast({ title: '请选择是否吸烟', icon: 'none' })
return false
......@@ -288,6 +228,6 @@ defineExpose({
})
</script>
<style lang="less">
/* 模样式 */
<style lang="less" scoped>
/* 模样式 */
</style>
......
......@@ -18,23 +18,12 @@
class="mb-5"
/>
<!-- 年龄(主字段,选择后自动计算出生年月日) -->
<PlanFieldAgePicker
v-model="form.age"
label="年龄"
placeholder="请选择年龄"
:required="true"
@change="onAgeChange"
class="mb-5"
/>
<!-- 出生年月日(根据年龄自动计算,可手动调整) -->
<!-- 出生日期 -->
<PlanFieldDatePicker
v-model="form.birthday"
label="出生年月日"
placeholder="请选择年月日"
:required="true"
@change="onBirthdayChange"
class="mb-5"
/>
......@@ -72,10 +61,10 @@
<!-- 提取计划配置 -->
<div v-if="config.withdrawal_plan?.enabled" class="withdrawal-plan-section">
<!-- 第一层:是否希望生成一份许减少名义金额的提取说明? -->
<!-- 第一层:是否希望生成一份许减少名义金额的提取说明? -->
<PlanFieldRadio
v-model="form.withdrawal_enabled"
label="是否希望生成一份许减少名义金额的提取说明?"
label="是否希望生成一份许减少名义金额的提取说明?"
:options="['是', '否']"
:required="true"
class="mb-5"
......@@ -83,7 +72,7 @@
<!-- 仅当选择"是"时才显示以下内容 -->
<template v-if="form.withdrawal_enabled === '是'">
<h3 class="text-base font-semibold text-gray-900 mb-4">款项提取(许减少名义金额)</h3>
<h3 class="text-base font-semibold text-gray-900 mb-4">款项提取(许减少名义金额)</h3>
<!-- 提取选项:指定提取金额 / 最高固定提取金额 -->
<PlanFieldRadio
......@@ -192,19 +181,17 @@
<!-- 配置缺失提示 -->
<div v-else class="text-center text-gray-500 py-10">
<p>⚠️ 配置未找到</p>
<p>⚠️ 配置未找到</p>
<p class="text-sm mt-2">请检查产品配置或联系开发人员</p>
</div>
</template>
<script setup>
/**
* 储蓄型保险计划书模
* 储蓄型保险计划书模
*
* @description GS/GC/FA/LV2 等储蓄型保险产品的计划书录入表单
* - 支持出生日期自动计算年龄
* - 支持提取计划配置(多种提取模式和方式)
* - 表单字段:性别、年龄、出生年月日、是否吸烟、保额、缴费年期
* - 表单字段:性别、出生年月日、是否吸烟、保额、缴费年期
* - 提取计划:指定提取金额(按年岁/按保单年度)、最高固定提取金额
* - 小程序端币种固定(使用配置中的默认币种)
* @author Claude Code
......@@ -237,7 +224,7 @@ const props = defineProps({
},
/**
* 模配置
* 模配置
* @type {Object}
* @property {string} currency - 币种代码
* @property {Array<string>} payment_periods - 缴费年期选项
......@@ -275,7 +262,9 @@ const emit = defineEmits([
* ⚠️ 重要:处理父组件重置表单的情况
* 问题:reactive() 只在初始化时赋值,父组件重置时子组件不会自动更新
*
* 解决方案:使用 watch 监听,但只在引用变化时才清空并复制
* 解决方案:使用 watch 监听,但只在重置时(空对象)才清空
* - 判断重置的标准:从有数据变为空对象
* - 用户输入时的更新:只合并新字段,不删除已有字段
*/
const form = reactive({})
......@@ -310,8 +299,8 @@ watch(
// 判断是否是重置(从有数据变为空对象)
const isReset = previousModelValue &&
Object.keys(previousModelValue).length > 0 &&
Object.keys(newVal).length === 0
Object.keys(previousModelValue).length > 0 &&
Object.keys(newVal).length === 0
if (isReset) {
// 父组件重置了:清空表单
......@@ -367,49 +356,6 @@ const withdrawalPeriods = computed(() => {
})
/**
* 年龄变化时自动计算出生年月日
* @param {number} age - 年龄
*
* @description 用户选择年龄后,自动计算并填充出生日期字段
* 计算公式:当前年份 - 年龄 = 出生年份(默认1月1日)
*/
const onAgeChange = (age) => {
if (age !== undefined && age !== null && age !== '') {
const currentYear = new Date().getFullYear()
const birthYear = currentYear - age
// 格式化为 YYYY-MM-DD,默认使用1月1日
const month = String(1).padStart(2, '0')
const day = String(1).padStart(2, '0')
form.birthday = `${birthYear}-${month}-${day}`
}
}
/**
* 出生日期变化时自动计算年龄
* @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 - 新的提取模式
*
......@@ -479,10 +425,6 @@ const validate = () => {
Taro.showToast({ title: '请选择出生年月日', icon: 'none' })
return false
}
if (form.age === undefined || form.age === '') {
Taro.showToast({ title: '请填写年龄', icon: 'none' })
return false
}
if (!form.smoker) {
Taro.showToast({ title: '请选择是否吸烟', icon: 'none' })
return false
......