feat(ebiz): 新增受益人信息同步功能

- 新增 `disableSyncApplicant` 属性控制是否允许同步投保人信息
- 当勾选“同投保人”时,禁用相关字段的编辑功能
- 实现 `syncToApplicant` 方法用于同步投保人数据至当前用户信息
- 监听 `applicant` 变化并在启用同步时自动更新用户信息
- 修改多个字段(如姓名、证件号、出生日期等)的只读逻辑依赖于 `asAppntAddress` 状态
- 更新客户选择器组件以支持 `readonly` 状态并防止重复触发
- 调整部分 UI 组件结构和事件绑定方式提升一致性与可维护性
This commit is contained in:
hz
2025-11-25 17:41:09 +08:00
parent 7eab4e6a18
commit c05132649e
4 changed files with 120 additions and 88 deletions

View File

@@ -16,7 +16,7 @@
right-icon="arrow"
@click="toSelect('7')"
/>
<div class="relative border-bt fs14 p10 flex align-center">
<div v-if="this.disableSyncApplicant" class="relative border-bt fs14 p10 flex align-center">
<van-checkbox v-model="userInfo.asAppntAddress" :disabled="Insured" @change="asAppntAddress">
同投保人
</van-checkbox>
@@ -25,7 +25,7 @@
v-model="userInfo.name"
v-validate="'required|salename'"
:parentShowPicker.sync="customerShowPicker"
:readonly="isInsured && nameLimit"
:readonly="userInfo.asAppntAddress"
label="姓名"
name="姓名"
required
@@ -48,7 +48,7 @@
<van-field
v-model="userInfo.idNo"
v-validate="'required'"
:readonly="isInsured && idNoLimit"
:readonly="userInfo.asAppntAddress"
clearable
label="证件号码"
maxlength="18"
@@ -61,7 +61,7 @@
ref="birthday"
v-validate="'required'"
:flag="true"
:readonly="isInsured && birthdayLimit"
:readonly="userInfo.asAppntAddress"
:value.sync="userInfo.birthday"
label="出生日期"
name="出生日期"
@@ -74,7 +74,8 @@
v-validate="'required'"
:defaultDate="new Date()"
:flag="true"
:readonly="isInsured"
:max-date="new Date()"
:readonly="userInfo.asAppntAddress"
:value.sync="userInfo.certificateValidate"
label="证件起始日期"
name="证件起始日期"
@@ -86,7 +87,7 @@
ref="certiexpiredate"
:defaultDate="new Date()"
:flag="certiexpiredateShow"
:readonly="isInsured"
:readonly="userInfo.asAppntAddress"
:required="isRequired"
:v-validate="{ required: certiexpiredateRequired }"
:value.sync="userInfo.certiexpiredate"
@@ -96,11 +97,17 @@
@confirm="onDateConfirm($event, '1')"
></FieldDatePicter>
<div class="border-bt relative fs14 p10 flex align-center">
<van-checkbox v-model="userInfo.effectiveDateType" :disabled="effectiveDateTypeAble" class="fr" @change="effectiveDataTypeChange">长期 </van-checkbox>
<van-checkbox
v-model="userInfo.effectiveDateType"
:disabled="effectiveDateTypeAble || this.userInfo.asAppntAddress"
class="fr"
@change="effectiveDataTypeChange"
>长期
</van-checkbox>
</div>
<select-radio
v-validate="'required'"
:disabled="isInsured && sexLimit"
:disabled="userInfo.asAppntAddress"
:radios="sexRadio"
:value.sync="userInfo.sex"
label="性别"
@@ -116,7 +123,7 @@
readonly
required
right-icon="arrow"
@click="setMarriageStatus('10')"
@click="() => !userInfo.asAppntAddress && setMarriageStatus('10')"
/>
<van-field
v-validate="'required'"
@@ -127,7 +134,7 @@
readonly
required
right-icon="arrow"
@click="toSelect('1')"
@click="() => !userInfo.asAppntAddress && toSelect('1')"
/>
<van-field
v-model="areaStr"
@@ -138,9 +145,18 @@
readonly
required
right-icon="arrow"
@click="isAreaListShow = true"
@click="() => !userInfo.asAppntAddress && (isAreaListShow = true)"
/>
<van-field
v-model="userInfo.village"
v-validate="'required'"
:readonly="userInfo.asAppntAddress"
clearable
label=""
maxlength="30"
name="详细地址"
placeholder="请输入详细地址"
/>
<van-field v-model="userInfo.village" v-validate="'required'" clearable label="" maxlength="30" name="详细地址" placeholder="请输入详细地址" />
<!-- <div class="pl10 pt10 pb10 pr10 address fs14">-->
<!-- <van-checkbox v-model="withRootUser.value">同投保人地址</van-checkbox>-->
<!-- </div>-->
@@ -159,7 +175,7 @@
<van-field
v-model="userInfo.mobile"
v-validate="'required|mobile'"
:readonly="isInsured && mobileLimit"
:readonly="userInfo.asAppntAddress"
clearable
label="联系电话"
maxlength="11"
@@ -185,6 +201,7 @@
<occupation-picker
v-validate="'required'"
:chooseName.sync="userInfo.occupationName"
:disabled="userInfo.asAppntAddress"
:healthGrade.sync="userInfo.healthGrade"
:lifeGrade.sync="userInfo.lifeGrade"
:parentShowPicker.sync="occupationShowPicker"
@@ -197,16 +214,7 @@
@on-click="selectClick('2')"
@on-choose="chooseOccupation"
/>
<van-field
v-model="userInfo.bnfOrder"
v-validate="'required|onlyNumber'"
label="受益顺序"
maxlength="1"
name="受益顺序"
placeholder="请输入"
readonly
required
/>
<van-field v-model="userInfo.bnfOrder" v-validate="'required|onlyNumber'" label="受益顺序" maxlength="1" name="受益顺序" placeholder="请输入" required />
<van-field
v-model="userInfo.bnfLot"
v-validate="'required|onlyNumber'"
@@ -257,7 +265,8 @@ import { idToData } from './js/verification'
import { selectComp } from './js/methods'
import getAreaName from '@/assets/js/utils/getAreaNameForSale'
import { getOrderDetail, checkAppointBnf } from '@/api/ebiz/sale/sale'
import { insured } from '@/views/ebiz/saleFlowProImprove/js/state'
import { user } from '@/views/ebiz/saleFlowProImprove/js/enum'
import { applicant, insured } from '@/views/ebiz/saleFlowProImprove/js/state'
let relationToInsured = [
{ id: 2, text: '配偶' },
@@ -348,14 +357,18 @@ export default {
isInsured: false, //是投保人本人,
Insured: false, //投保人本人按钮是否置灰
idLimit: false, //证件起止日期是否只读
saleInsuredPersonInfo: JSON.parse(this.$CacheUtils.getLocItem('saleInsuredPersonInfo')), //被保人信息
saleInsuredPersonInfo: insured, //被保人信息
branchType: '',
subTask: this.task
}
},
props: ['beneficiary', 'task'],
props: ['beneficiary', 'task', 'disableSyncApplicant'],
inject: ['nextStepProcesserContainer'],
computed: {
user() {
return user
},
applicant: () => applicant,
relationToAppnt: {
get() {
const { relationToAppnt } = DataDictionary
@@ -485,7 +498,7 @@ export default {
},
selectClick(index) {
// 同被保险人不允许编辑
if (this.isInsured) {
if (this.isInsured || this.userInfo.asAppntAddress) {
this.$toast('同被保险人不允许编辑')
return false
}
@@ -523,7 +536,7 @@ export default {
//弹框选择
toSelect(pickerType, valueKey) {
//同被保险人不允许编辑
if (this.isInsured) {
if (this.userInfo.asAppntAddress && pickerType !== '7') {
return
}
//pickerType 1、国家地区 2、证件类型 3、文化程度 4、有无社保 5、税收居民身份 6、婚姻状况
@@ -731,6 +744,8 @@ export default {
},
//选择客户
chooseCustomer(data) {
if (this.userInfo.asAppntAddress) return false
this.customerShowPicker = false
this.$jump({
flag: 'navigation',
@@ -1228,6 +1243,16 @@ export default {
goScan() {
this.isScan = true
},
syncToApplicant() {
// 进行同步 投保人信息
const applicant = this.applicant
const ignoreKeys = []
for (const key in this.userInfo) {
if (ignoreKeys.includes(key)) continue
if (!this.userInfo.hasOwnProperty(key) || !applicant.hasOwnProperty(key)) continue
this.userInfo[key] = applicant[key]
}
},
//勾选投保人
asAppntAddress(val) {
if (val) {
@@ -1240,56 +1265,55 @@ export default {
}
this.isInsured = true
let params = {
orderNo: this.$route.query.orderNo
}
getOrderDetail(params).then(res => {
if (res.result == 0) {
let insuredDetail = res.orderDTO.appntDTO
this.userInfo.name = insuredDetail.name //姓名
this.nameLimit = Boolean(insuredDetail.name)
this.userInfo.sex = insuredDetail.sex //性别
this.sexLimit = Boolean(insuredDetail.sex)
this.userInfo.nativeplace = insuredDetail.nativeplace //国家地区
this.userInfo.birthday = insuredDetail.birthday //出生日期
this.birthdayLimit = Boolean(insuredDetail.birthday)
this.userInfo.idType = insuredDetail.idType //证件类型
this.userInfo.idNo = insuredDetail.idNo //证件号码
this.idNoLimit = Boolean(insuredDetail.idNo)
this.userInfo.certificateValidate = insuredDetail.certificateValidate //证件起始日期
this.userInfo.certiexpiredate = insuredDetail.certiexpiredate == '9999-12-31' ? '' : insuredDetail.certiexpiredate //证件截止日期
this.userInfo.effectiveDateType = insuredDetail.certiexpiredate == '9999-12-31' //是否长期
this.userInfo.mobile = insuredDetail.mobile
this.mobileLimit = Boolean(insuredDetail.mobile)
this.userInfo.marriage = insuredDetail.marriage
if (this.userInfo.marriage == 1) {
this.userInfo.marriageStatus = '已婚'
} else if (this.userInfo.marriage == 2) {
this.userInfo.marriageStatus = '未婚'
} else if (this.userInfo.marriage == 3) {
this.userInfo.marriageStatus = '离异'
} else if (this.userInfo.marriage == 4) {
this.userInfo.marriageStatus = '丧偶'
}
let age = utilsAge.getAge(insuredDetail.birthday, new Date())
this.effectiveDateTypeAble = age <= 45
if (age > 45) {
this.userInfo.effectiveDateType = true
}
this.idLimit = true
this.userInfo.occupationCode = insuredDetail.occupationCode //职业类别编码
this.userInfo.occupationName = insuredDetail.occupationName //职业类别名称
this.areaStr = getAreaName([{ code: insuredDetail.homeProvince }, { code: insuredDetail.homeCity }, { code: insuredDetail.homeArea }])
this.userInfo.province = insuredDetail.homeProvince
this.userInfo.city = insuredDetail.homeCity
this.userInfo.area = insuredDetail.homeArea
this.userInfo.village = insuredDetail.homeAddress
this.userInfo.yearSalary = insuredDetail.averageAnnualIncome
this.userInfo.averageAnnualIncome = insuredDetail.averageAnnualIncome
}
})
// this.syncToApplicant()
// getOrderDetail(params).then(res => {
// if (res.result == 0) {
// let insuredDetail = res.orderDTO.appntDTO
// this.userInfo.name = insuredDetail.name //姓名
// this.nameLimit = Boolean(insuredDetail.name)
// this.userInfo.sex = insuredDetail.sex //性别
// this.sexLimit = Boolean(insuredDetail.sex)
// this.userInfo.nativeplace = insuredDetail.nativeplace //国家地区
// this.userInfo.birthday = insuredDetail.birthday //出生日期
// this.birthdayLimit = Boolean(insuredDetail.birthday)
// this.userInfo.idType = insuredDetail.idType //证件类型
// this.userInfo.idNo = insuredDetail.idNo //证件号码
// this.idNoLimit = Boolean(insuredDetail.idNo)
// this.userInfo.certificateValidate = insuredDetail.certificateValidate //证件起始日期
// this.userInfo.certiexpiredate = insuredDetail.certiexpiredate == '9999-12-31' ? '' : insuredDetail.certiexpiredate //证件截止日期
// this.userInfo.effectiveDateType = insuredDetail.certiexpiredate == '9999-12-31' //是否长期
// this.userInfo.mobile = insuredDetail.mobile
// this.mobileLimit = Boolean(insuredDetail.mobile)
// this.userInfo.marriage = insuredDetail.marriage
// if (this.userInfo.marriage == 1) {
// this.userInfo.marriageStatus = '已婚'
// } else if (this.userInfo.marriage == 2) {
// this.userInfo.marriageStatus = '未婚'
// } else if (this.userInfo.marriage == 3) {
// this.userInfo.marriageStatus = '离异'
// } else if (this.userInfo.marriage == 4) {
// this.userInfo.marriageStatus = '丧偶'
// }
// let age = utilsAge.getAge(insuredDetail.birthday, new Date())
// this.effectiveDateTypeAble = age <= 45
// if (age > 45) {
// this.userInfo.effectiveDateType = true
// }
// this.idLimit = true
// this.userInfo.occupationCode = insuredDetail.occupationCode //职业类别编码
// this.userInfo.occupationName = insuredDetail.occupationName //职业类别名称
//
// this.areaStr = getAreaName([{ code: insuredDetail.homeProvince }, { code: insuredDetail.homeCity }, { code: insuredDetail.homeArea }])
// this.userInfo.province = insuredDetail.homeProvince
// this.userInfo.city = insuredDetail.homeCity
// this.userInfo.area = insuredDetail.homeArea
// this.userInfo.village = insuredDetail.homeAddress
//
// this.userInfo.yearSalary = insuredDetail.averageAnnualIncome
// this.userInfo.averageAnnualIncome = insuredDetail.averageAnnualIncome
// }
// })
} else {
this.isInsured = false
this.userInfo.relationToInsured = ''
@@ -1410,6 +1434,15 @@ export default {
idToText: filter.idToText
},
watch: {
applicant: {
deep: true,
immediate: true,
handler() {
if (!this.userInfo.asAppntAddress) return
this.syncToApplicant()
}
},
userInfo: {
deep: true,
handler(value, oldValue) {

View File

@@ -23,6 +23,7 @@
<DesignateBeneficiary
ref="beneficiaryRef"
:beneficiary.sync="beneficiary"
:disableSyncApplicant="index < 1"
:task="`saveBeneficiary_saveOtherBeneficiary-${generateRandomId()}`"
@scaned="getIdentityInfo($event, index)"
@syncBeneficiary="handleSyncBeneficiary($event, index)"

View File

@@ -121,7 +121,6 @@
@click="toSelect('10')"
/>
{{ userInfo.nativeplace }}
<van-field
v-validate="'required'"
:value="userInfo.nativeplace | idToText('nativeplace')"

View File

@@ -1,18 +1,18 @@
<template>
<div id="customer-picker">
<van-field
:label="label"
v-model="name"
@input="onChange"
:label="label"
:placeholder="placeholder"
:readonly="readonly"
:required="required"
:right-icon="$assetsUrl + 'images/avatar.png'"
@click-right-icon="chooseCustomer"
:readonly="readonly"
@blur="handleFieldBlur"
@input="onChange"
@click-right-icon="chooseCustomer"
/>
<van-popup v-model="showPicker" position="bottom" round style="max-height: 95%">
<customer @on-choose="choose" :code="code" :name="name" :life="life" :health="health"></customer>
<customer :code="code" :health="health" :life="life" :name="name" @on-choose="choose"></customer>
</van-popup>
</div>
</template>
@@ -47,8 +47,7 @@ export default {
},
data: {
type: Array,
default: () => {
}
default: () => {}
},
//选项对象中,文字对应的 key
valueKey: {
@@ -119,11 +118,11 @@ export default {
choose(data) {
this.name = data.customerName
this.showPicker = false
this.$emit("update:parentShowPicker", false)
this.$emit('update:parentShowPicker', false)
this.$emit('on-choose', data)
},
chooseCustomer() {
if (this.disabled) {
if (this.disabled || this.readonly) {
return
}
this.showPicker = true
@@ -135,7 +134,7 @@ export default {
},
handleFieldBlur() {
// console.log(this.name)
this.$emit("update:value", this.name)
this.$emit('update:value', this.name)
this.$emit('blur', this.name)
}
}