Commit 621b7859 by Sweet Zhang

Merge branch 'feature-20250827wyz-写业务' into sw

parents df8d349a 3f5ee310
<template>
<el-watermark :font="font" :content="content">
<router-view />
</el-watermark>
......@@ -10,10 +9,10 @@ import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme'
import { reactive } from 'vue'
const font = reactive({
color: 'rgba(0, 0, 0, .15)',
color: 'rgba(0, 0, 0, .15)'
})
const content = reactive('csf')
const content = ref('')
onMounted(() => {
nextTick(() => {
......
......@@ -95,3 +95,51 @@ export function getClientUser(data) {
data: data
})
}
// 银行列表
export function getBankList(data) {
return request({
url: '/base/api/bank/page',
method: 'post',
data: data
})
}
// 转介人列表
export function getUserSaleExpandList(data) {
return request({
url: '/insurance/base/api/userSaleExpand/page',
method: 'post',
data: data
})
}
// 第二个附加险列表
export function secondAdditonalList(data) {
return request({
url: '/product/api/relProjectProductLaunch/parameter/page',
method: 'post',
data: data
})
}
// 获取签单员列表
export function getAllSignList(data) {
return request({
url: '/insurance/base/api/userSignExpand/page',
method: 'post',
data: data
})
}
// 获取团队列表
export function getAllTeam(data) {
return request({
url: '/csf/api/team/page',
method: 'post',
data: data
})
}
// 获取保险公司列表
export function getInsuranceCompany(data) {
return request({
url: '/insurance/base/api/insuranceCompany/page',
data: data,
method: 'post'
})
}
......@@ -222,3 +222,4 @@ export function delSigleAppointment(appointmentBizId) {
method: 'delete'
})
}
......@@ -4,7 +4,10 @@
<template #header>
<div class="cardOneheader">
<div class="cardOneLeft">
<div class="mainTitle">{{ title }}</div>
<div class="mainTitle">
{{ title }}
<slot name="mainTitCustom"></slot>
</div>
<slot name="headerRight"></slot>
</div>
<div class="subTitle" v-if="desTitle">{{ desTitle }}</div>
......@@ -60,6 +63,7 @@ const props = defineProps({
padding-left: 5px;
display: flex;
align-items: center;
margin-right: 20px;
/* border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
......@@ -69,7 +73,7 @@ const props = defineProps({
content: '';
display: inline-block;
width: 4px;
height: 22px;
height: 18px;
background: #0052d9;
margin-right: 5px;
border-radius: 4px;
......
const appointmentInfo = [
// 申请
{
fatherTitle: '',
type: 'object',
key: 'personInfo',
fatherTitle: '行政信息',
keyType: 'object',
key: 'administration',
anchorKey: 'administration',
showMoudle: true, //模块是否展示
data: [
{
......@@ -21,83 +22,12 @@ const appointmentInfo = [
lg: 8 //栅格布局份数
},
{
label: '预约时间',
key: 'confirmAppointmentTime',
domType: 'datetimePicker',
required: false,
disabled: true,
placeholder: '请选择',
show: false,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: ' ',
key: 'newPolicyButton',
domType: 'button',
buttonTxt: '生成新单跟进记录',
buttonType: 'primary',
required: false,
maxLength: 10,
disabled: false,
show: false,
// labelPosition: 'top', //标签的位置
labelWidth: '0px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
},
// 业务信息
{
fatherTitle: '业务信息',
type: 'object',
key: 'business',
labelPosition: 'top', //标签的位置
showMoudle: true, //模块是否展示
// description: '证件信息至少填写一项',
data: [
{
label: '业务编号',
key: 'businessNo',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 20,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '签单员账号',
key: 'businessRepresentAccount1',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 20,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '签单员姓名',
key: 'businessRepresentName1',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 20,
label: '意向签单日',
key: 'intentionAppointmentTime',
domType: 'DatePicker',
required: true,
disabled: false,
placeholder: '请输入',
placeholder: '请选择',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -105,66 +35,24 @@ const appointmentInfo = [
lg: 8 //栅格布局份数
},
{
label: '签单员电话号码',
key: 'businessRepresentMobile1',
domType: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
drawerType: 'phone',
businessRepresentMobile1: {}, //带有区号得电话一定要有一个和key一样得对象用于收集区号和号码
code: 'businessRepresentMobile1Code',
maxLength: 20,
labelPosition: 'top', //标签的位置
labelWidth: '180px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '签单员邮箱',
key: 'businessRepresentEmail1',
domType: 'Input',
inputType: 'text',
maxLength: 30,
required: false,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
},
// 基础信息
{
fatherTitle: '基础信息',
type: 'object',
key: 'basic',
showMoudle: true, //模块是否展示
// description: '证件信息至少填写一项',
data: [
{
label: '意向预约时间',
key: 'intentionAppointmentTime',
domType: 'datetimePicker',
label: '转介人是否陪同',
key: 'isReferrerAccompany',
domType: 'Select',
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '转介人是否陪同',
key: 'isAccompany',
label: '是否需用车',
key: 'isUseCar',
domType: 'Select',
required: false,
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
......@@ -175,10 +63,10 @@ const appointmentInfo = [
lg: 8 //栅格布局份数
},
{
label: '是否有用车需求',
key: 'isUseCar',
label: '是否开户',
key: 'isOpenAccount',
domType: 'Select',
required: false,
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
......@@ -188,75 +76,76 @@ const appointmentInfo = [
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
// {
// label: '预约时间',
// key: 'confirmAppointmentTime',
// domType: 'datetimePicker',
// required: false,
// disabled: true,
// placeholder: '请选择',
// show: false,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: ' ',
// key: 'newPolicyButton',
// domType: 'button',
// buttonTxt: '生成新单跟进记录',
// buttonType: 'primary',
// required: false,
// maxLength: 10,
// disabled: false,
// show: false,
// // labelPosition: 'top', //标签的位置
// labelWidth: '0px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// }
]
},
// 陪同顾问信息
// 陪同转介人信息
{
fatherTitle: '转介人信息',
type: 'object',
key: 'consult',
fatherTitle: '陪同转介人',
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
key: 'referrerDtoList',
anchorKey: 'referrerDtoList',
moudleType: 'referrerDtoList',
dataLength: 1, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
showTable: true,
showMoudle: false, //模块是否展示
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '陪同转介人', //新增按钮得文本
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
isOpen: false, //dom是否展开
data: [
{
label: '姓名',
key: 'accompanyName',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '手机',
key: 'accompanyMobile',
domType: 'arrowRight',
required: false,
disabled: false,
placeholder: '请填写',
show: true,
labelPosition: 'top', //标签的位置
drawerType: 'phone',
accompanyMobile: {}, //带有区号得电话一定要有一个和key一样得对象用于收集区号和号码
code: 'accompanyMobileCode',
maxLength: 20,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '邮箱',
key: 'accompanyEmail',
domType: 'Input',
inputType: 'text',
maxLength: 30,
required: false,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
// {
// id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
// span: 24, //栅格布局份数
// email: '',
// phone: '',
// realName: ''
// }
]
},
// 到港信息
{
fatherTitle: '到港信息',
type: 'object',
fatherTitle: '到港/离港信息',
keyType: 'object',
key: 'position',
anchorKey: 'position',
showMoudle: true, //模块是否展示
data: [
{
label: '到港时间',
key: 'arrivalTime',
domType: 'datetimePicker',
dateValue: '', //YYYY-MM-DD
timeValue: '', //HH:mm
compositionTime: true, //是否组合时间
required: false,
disabled: false,
placeholder: '请选择',
......@@ -270,6 +159,9 @@ const appointmentInfo = [
label: '离港时间(离港时间必须晚于到港时间)',
key: 'departureTime',
domType: 'datetimePicker',
dateValue: '', //YYYY-MM-DD
timeValue: '', //HH:mm
compositionTime: true, //是否组合时间
required: false,
disabled: false,
placeholder: '请选择',
......@@ -295,7 +187,7 @@ const appointmentInfo = [
},
{
label: '签单地',
label: '签单地',
key: 'signingAddress',
domType: 'Input',
inputType: 'text',
......@@ -310,7 +202,7 @@ const appointmentInfo = [
lg: 8 //栅格布局份数
},
{
label: '客户在港期间联络电话',
label: '在港联系电话',
key: 'hkMobile',
domType: 'arrowRight', //带有区号得电话一定要有一个和key一样得对象用于收集区号和号码
required: false,
......@@ -328,27 +220,29 @@ const appointmentInfo = [
}
]
},
// 其他情况
// 陪同转介人信息
{
fatherTitle: '其他情况',
type: 'object',
key: 'other',
fatherTitle: '签单员',
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
key: 'userSignDtoList',
anchorKey: 'userSignDtoList',
moudleType: 'userSignDtoList',
dataLength: 1, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
showTable: true,
showMoudle: true, //模块是否展示
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '签单员', //新增按钮得文本
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
isOpen: false, //dom是否展开
data: [
{
label: '是否开户',
key: 'isOpenAccount',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
// {
// name: '', //姓名
// practiceCode: '', //执业编码
// phone: '', //手机号
// cardType: '', //证件类型
// cardNo: '', //证件号码
// email: '' //邮箱
// }
]
},
// 开户信息
......@@ -356,6 +250,7 @@ const appointmentInfo = [
fatherTitle: '开户信息',
type: 'object',
key: 'openAccount',
anchorKey: 'openAccount',
showMoudle: false, //模块是否展示
data: [
{
......@@ -391,7 +286,7 @@ const appointmentInfo = [
},
{
label: '开户时间段(开始)',
label: '开户时间(起)',
key: 'openAccountStartTime',
domType: 'DatePicker',
timeType: 'date',
......@@ -405,7 +300,7 @@ const appointmentInfo = [
lg: 8 //栅格布局份数
},
{
label: '开户时间段(结束,先选择开始时间)',
label: '开户时间(止)',
key: 'openAccountEndTime',
domType: 'DatePicker',
required: false,
......@@ -467,6 +362,7 @@ const appointmentInfo = [
inputType: 'textarea',
required: false,
maxLength: 300,
rows: 5, //文本域行数
disabled: false,
placeholder: '请输入',
show: true,
......@@ -476,27 +372,234 @@ const appointmentInfo = [
lg: 24 //栅格布局份数
},
{
label: '',
title: '所需资料',
key: 'information',
domType: 'Div',
label: '所需资料',
key: 'materials',
domType: 'Input',
inputType: 'textarea',
required: false,
maxLength: 30,
maxLength: 300,
rows: 5, //文本域行数
disabled: false,
placeholder: '请输入',
show: true,
informationList: [
{ name: '1、身份证' },
{ name: '2、港澳通行证/护照' },
{ name: '3、出生证明(18岁以下受保人)' },
{ name: '4、结婚证(如夫妻为对方支付保费)' },
{ name: '5、通关小白条' }
],
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 24, //栅格布局份数
lg: 24 //栅格布局份数
}
// {
// label: '',
// title: '所需资料',
// key: 'information',
// domType: 'Div',
// required: false,
// maxLength: 30,
// disabled: false,
// placeholder: '请输入',
// show: true,
// informationList: [
// { name: '1、身份证' },
// { name: '2、港澳通行证/护照' },
// { name: '3、出生证明(18岁以下受保人)' },
// { name: '4、结婚证(如夫妻为对方支付保费)' },
// { name: '5、通关小白条' }
// ],
// labelWidth: '120px', //标签宽度
// sm: 24, //栅格布局份数
// lg: 24 //栅格布局份数
// }
]
}
// 业务信息
// {
// fatherTitle: '业务信息',
// type: 'object',
// key: 'business',
// labelPosition: 'top', //标签的位置
// showMoudle: true, //模块是否展示
// // description: '证件信息至少填写一项',
// data: [
// {
// label: '业务编号',
// key: 'businessNo',
// domType: 'Input',
// inputType: 'text',
// required: false,
// maxLength: 20,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '签单员账号',
// key: 'businessRepresentAccount1',
// domType: 'Input',
// inputType: 'text',
// required: false,
// maxLength: 20,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '签单员姓名',
// key: 'businessRepresentName1',
// domType: 'Input',
// inputType: 'text',
// required: false,
// maxLength: 20,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '签单员电话号码',
// key: 'businessRepresentMobile1',
// domType: 'arrowRight',
// required: false,
// disabled: false,
// placeholder: '请填写',
// show: true,
// drawerType: 'phone',
// businessRepresentMobile1: {}, //带有区号得电话一定要有一个和key一样得对象用于收集区号和号码
// code: 'businessRepresentMobile1Code',
// maxLength: 20,
// labelPosition: 'top', //标签的位置
// labelWidth: '180px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '签单员邮箱',
// key: 'businessRepresentEmail1',
// domType: 'Input',
// inputType: 'text',
// maxLength: 30,
// required: false,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// }
// ]
// },
// 基础信息
// {
// fatherTitle: '基础信息',
// type: 'object',
// key: 'basic',
// showMoudle: true, //模块是否展示
// // description: '证件信息至少填写一项',
// data: [
// {
// label: '意向预约时间',
// key: 'intentionAppointmentTime',
// domType: 'datetimePicker',
// required: true,
// disabled: false,
// placeholder: '请选择',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '是否有用车需求',
// key: 'isUseCar',
// domType: 'Select',
// required: false,
// disabled: false,
// placeholder: '请选择',
// dictType: 'sys_no_yes',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// }
// ]
// },
// 陪同顾问信息
// {
// fatherTitle: '转介人信息',
// type: 'object',
// key: 'consult',
// showMoudle: false, //模块是否展示
// data: [
// {
// label: '姓名',
// key: 'accompanyName',
// domType: 'Input',
// inputType: 'text',
// required: false,
// maxLength: 30,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '手机',
// key: 'accompanyMobile',
// domType: 'arrowRight',
// required: false,
// disabled: false,
// placeholder: '请填写',
// show: true,
// labelPosition: 'top', //标签的位置
// drawerType: 'phone',
// accompanyMobile: {}, //带有区号得电话一定要有一个和key一样得对象用于收集区号和号码
// code: 'accompanyMobileCode',
// maxLength: 20,
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '邮箱',
// key: 'accompanyEmail',
// domType: 'Input',
// inputType: 'text',
// maxLength: 30,
// required: false,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// }
// ]
// },
// 其他情况
// {
// fatherTitle: '其他情况',
// type: 'object',
// key: 'other',
// showMoudle: true, //模块是否展示
// data: []
// },
]
export default appointmentInfo
const customer = [
// 与投保人关系-在受保人中显示
{
fatherTitle: '与投保人关系',
type: 'object',
key: 'policyholderRel',
anchorKey: 'policyholderRel',
showTable: false,
showMoudle: false,
data: [
{
label: '与投保人关系',
key: 'policyholderRel',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'csf_ap_rel',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
},
// 基础信息
{
fatherTitle: '基础信息',
......@@ -6,6 +31,7 @@ const customer = [
key: 'personInfo',
anchorKey: 'personInfo',
showTable: false,
showMoudle: true,
data: [
{
label: '名字(中文)',
......@@ -21,7 +47,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
......@@ -37,23 +63,10 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
// {
// label: '称谓',
// key: 'title',
// domType: 'Select',
// required: true,
// disabled: false,
// placeholder: '请选择',
// dictType: 'csf_customer_title',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 8, //栅格布局份数
// lg: 8 //栅格布局份数
// },
{
label: '证件类型',
key: 'documentType',
......@@ -65,7 +78,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -80,7 +93,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
......@@ -95,7 +108,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -108,7 +121,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -123,7 +136,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -137,7 +150,7 @@ const customer = [
drawerType: 'country',
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -152,11 +165,11 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '是否拥有其他国家公民身份(如美国、日本等)',
label: '是否拥有其他国家公民身份',
key: 'isOtherCountry',
domType: 'Select',
required: false,
......@@ -166,7 +179,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -180,24 +193,10 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
// {
// label: '吸烟数量(支/天)',
// key: 'smokeQuantity',
// domType: 'Input',
// inputType: 'number',
// maxLength: 30,
// required: false,
// disabled: false,
// placeholder: '请输入',
// show: false,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 8, //栅格布局份数
// lg: 8 //栅格布局份数
// },
{
label: '婚姻状况',
key: 'maritalStatus',
......@@ -209,7 +208,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -223,7 +222,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -237,7 +236,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -252,7 +251,7 @@ const customer = [
show: false,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -266,7 +265,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
......@@ -282,7 +281,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -297,7 +296,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -307,12 +306,12 @@ const customer = [
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
disabled: true,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
......@@ -325,6 +324,7 @@ const customer = [
anchorKey: 'apiTaxationDtoList',
moudleType: 'apiTaxationDtoList',
dataLength: 1, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
showMoudle: true,
showTable: true,
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '税务', //新增按钮得文本
......@@ -335,7 +335,7 @@ const customer = [
// id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
// span: 24, //栅格布局份数
// taxCountry: '',
// taxNumber: ''
// taxId: ''
// }
]
},
......@@ -346,6 +346,7 @@ const customer = [
key: 'contactInfo',
anchorKey: 'contactInfo',
showTable: false,
showMoudle: true,
data: [
{
label: '移动电话',
......@@ -361,7 +362,7 @@ const customer = [
value: '',
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
......@@ -379,7 +380,7 @@ const customer = [
maxLength: 20,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -394,7 +395,7 @@ const customer = [
maxLength: 20,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -403,13 +404,13 @@ const customer = [
domType: 'Input',
inputType: 'text',
maxLength: 30,
required: true,
required: false,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -421,10 +422,10 @@ const customer = [
maxLength: 20,
disabled: false,
placeholder: '请输入',
show: false,
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
......@@ -440,7 +441,7 @@ const customer = [
mailingAddress: {},
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -455,7 +456,7 @@ const customer = [
residentialAddress: {},
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -470,7 +471,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
......@@ -483,6 +484,7 @@ const customer = [
key: 'companyInfo',
anchorKey: 'companyInfo',
showTable: false,
showMoudle: true,
data: [
{
label: '就业情况',
......@@ -495,7 +497,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -510,7 +512,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -525,7 +527,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -541,7 +543,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -556,7 +558,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -571,7 +573,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -586,7 +588,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -606,7 +608,7 @@ const customer = [
maxLength: 20,
labelPosition: 'top', //标签的位置
labelWidth: '180px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -622,7 +624,7 @@ const customer = [
companyAddress: {},
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -637,7 +639,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
......@@ -649,6 +651,7 @@ const customer = [
key: 'financeInfo',
anchorKey: 'financeInfo',
showTable: false,
showMoudle: true,
data: [
{
label: '平均每月收入',
......@@ -663,7 +666,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -679,7 +682,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -695,7 +698,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -711,7 +714,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
......@@ -737,7 +740,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -751,7 +754,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -765,7 +768,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
......@@ -779,7 +782,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
......@@ -795,7 +798,7 @@ const customer = [
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
......
/**
* 1.普通模块得数据格式,无子级:
* {
一些页面用到得属性,比如个人资料模块得数据格式
data:[] data主要是这个模块对应得表单dom数据
}
2. 有子级得模块得数据格式:
{
一些页面用到得属性,比如家庭状况模块得数据格式
data:[ data主要父级模块对应得表单
{
比如家庭状况中有父亲,母亲,配偶,这个对象就代表这些人
children:[],代表得是这些人对应得表单dom
}
]
}
以上两种格式说明了fnaForm页面得dom数据格式,如果有子级得dom请参照2格式添加,否则可能有未知错误
*/
const fnaForm = [
// 介绍人信息
{
fatherTitle: '个人资料',
keyType: 'Object', //用于表单收集值时,判断是数组还是对象
key: 'personalData',
child: 'no', //没有子级dom,直接展示
fatherRequired: true, //父级必填,代表个人资料这个模块有必填项
data: [
fatherTitle: '转介人信息',
keyType: 'Array',
key: 'brokerList',
anchorKey: 'brokerList',
moudleType: 'brokerList',
dataLength: 1,
showMoudle: true,
showTable: true,
addChildren: true,
addChildrenTxt: '转介人',
fatherRequired: false,
isOpen: false,
// 新增表格列配置
columns: [
{
label: '转介人',
key: 'accountName',
domType: 'SearchSelect',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
label: '姓名',
prop: 'brokerName',
type: 'remoteSelect',
searchType: 'brokerName',
placeholder: '请输入关键词搜索',
required: false
},
// {
// label: '签单员注册编号',
// key: 'registrationNumber',
// domType: 'Input',
// inputType: 'text',
// required: true,
// maxLength: 30,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '140px', //标签宽度
// sm: 8, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '签单员内部编码',
// key: 'number',
// domType: 'Input',
// inputType: 'text',
// required: false,
// maxLength: 30,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '130px', //标签宽度
// sm: 8, //栅格布局份数
// lg: 8 //栅格布局份数
// },
{
label: '客户姓名',
key: 'customerName',
domType: 'Input',
inputType: 'text',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
label: '性别',
prop: 'brokerGender',
type: 'select',
dictType: 'sys_gender',
placeholder: '请选择',
required: false
},
// {
// label: '税务国家',
// key: 'taxCountry',
// domType: 'Input',
// inputType: 'text',
// required: true,
// maxLength: 30,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 8, //栅格布局份数
// lg: 8 //栅格布局份数
// },
{
label: '就业情况',
key: 'employment',
domType: 'Select',
required: true,
maxLength: 30,
disabled: false,
label: '内部编号',
prop: 'brokerNumber',
type: 'input',
placeholder: '请输入',
show: true,
dictType: 'csf_employment',
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
required: false
},
{
label: '是否退休',
key: 'isRetired',
domType: 'Select',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
dictType: 'sys_no_yes',
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
label: '所属团队',
prop: 'brokerTeam',
type: 'remoteSelect',
searchType: 'brokerTeam',
placeholder: '请输入关键词搜索',
required: false
},
{
label: '退休年龄',
key: 'retiredAge',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 30,
disabled: false,
label: '分配比例',
prop: 'brokerRatio',
type: 'inputNumber',
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
required: true
},
{
label: '其他就业情况',
key: 'otherEmployment',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
label: '备注',
prop: 'remark',
type: 'input',
placeholder: '请输入',
show: false,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
required: false
}
],
data: [
{
brokerName: '',
brokerGender: '',
brokerNumber: '',
brokerTeam: '',
brokerRatio: '',
remark: ''
}
]
},
// 受供养人信息
{
fatherTitle: '家庭状况',
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
showTable: true, //以table的形式展示
key: 'familyMembers',
moudleType: 'family',
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '添加儿女', //新增按钮得文本
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
fatherTitle: '受供养人信息',
keyType: 'Array',
key: 'dependantList',
anchorKey: 'dependantList',
moudleType: 'dependantList',
dataLength: 1,
showMoudle: true,
showTable: true,
addChildren: true,
addChildrenTxt: '受供养人',
fatherRequired: false,
isOpen: false,
openIcon: true,
data: [
// 表格列配置
columns: [
{
type: '1',
childTitle: '父亲',
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
age: '',
needProvide: '',
disabled: false,
dictType: 'sys_no_yes',
options: []
label: '与投保人关系',
prop: 'policyholderRel',
type: 'select',
dictType: 'csf_ap_rel',
placeholder: '请选择',
required: false
},
{
type: '2',
childTitle: '母亲',
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
age: '',
needProvide: '',
disabled: false,
dictType: 'sys_no_yes',
options: []
},
label: '年龄',
prop: 'dependantAge',
type: 'inputNumber',
placeholder: '请输入年龄',
required: false
}
],
data: [
{
type: '3',
childTitle: '配偶',
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
age: '',
needProvide: '',
disabled: false,
dictType: 'sys_no_yes',
options: []
policyholderRel: '',
dependantAge: ''
}
]
},
//财务需要分析
// 已生效仍在缴费期的保单情况
{
fatherTitle: '财务需要分析',
subTitle: '保单持有人个人已有保障',
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
fatherTitle: '已生效仍在缴费期的保单情况',
keyType: 'Array',
key: 'existingSecurityOwner',
moudleType: 'finance',
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '保单持有人个人已有保障', //新增按钮得文本
anchorKey: 'existingSecurityOwner',
moudleType: 'existingSecurityOwner',
dataLength: 1,
showMoudle: true,
showTable: true,
dataLength: 5, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
addChildren: true,
addChildrenTxt: '保单',
fatherRequired: false,
isOpen: false,
openIcon: true,
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
data: [
// 表格列配置
columns: [
{
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
childTitle: '保单持有人个人已有保障',
insurer: '',
insuranceType: '',
sumInsured: '',
policyIssueDate: '',
currency: '',
label: '保险公司',
prop: 'insurer',
type: 'remoteSelect',
searchType: 'insurer',
placeholder: '请搜索保险公司名称',
required: true
},
{
label: '保险种类',
prop: 'insuranceType',
type: 'remoteSelect',
searchType: 'insuranceType',
placeholder: '请选择',
required: true
},
{
label: '保单币种',
prop: 'currency',
type: 'select',
dictType: 'bx_currency_type',
options: []
placeholder: '请选择',
required: true
},
{
label: '投保日期',
prop: 'policyIssueDate',
type: 'datePicker',
placeholder: '请选择日期',
required: true
}
]
},
//受保人个人已有保障
{
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
subTitle: '受保人个人已有保障',
key: 'existingSecurityInsured',
moudleType: 'finance',
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '受保人个人已有保障', //新增按钮得文本
dataLength: 5, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
showTable: true,
isOpen: false, //dom是否展开
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
// 有重疾险才让填写
// {
// label: '保额',
// prop: 'sumInsured',
// type: 'inputNumber',
// placeholder: '请输入保额',
// required: true
// },
],
data: [
{
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
subTitle: '受保人个人已有保障',
insurer: '',
insuranceType: '',
sumInsured: '',
policyIssueDate: '',
currency: '',
dictType: 'bx_currency_type',
options: []
}
]
},
// 投资房地产
{
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
key: 'investment',
moudleType: 'finance',
subTitle: '投资房地产',
showTable: true,
dataLength: 2, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '投资房地产', //新增按钮得文本
isOpen: false, //dom是否展开
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
data: [
{
childTitle: '投资房地产',
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
address: '',
currency: '',
dictType: 'bx_currency_type',
marketValue: ''
policyIssueDate: ''
}
]
},
//保单持有人资产
// 不动产信息
{
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
fatherTitle: '不动产信息',
keyType: 'Array',
key: 'primaryResidence',
moudleType: 'finance',
dataLength: 1, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
showTable: true,
subTitle: '保单持有人资产',
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '保单持有人资产', //新增按钮得文本
isOpen: false, //dom是否展开
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
data: [
{
childTitle: '自住用途之房地产',
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
address: '',
currency: '',
dictType: 'bx_currency_type',
marketValue: ''
}
]
},
// 税务国家
{
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
key: 'taxList',
moudleType: 'finance',
dataLength: 1, //设置dataLength,用于控制子级dom的个数,子级保存一个样例数据,便于加子级数据
anchorKey: 'primaryResidence',
moudleType: 'primaryResidence',
dataLength: 1,
showMoudle: true,
showTable: true,
subTitle: '税务',
addChildren: true, //是否可以新增子级dom
addChildrenTxt: '税务', //新增按钮得文本
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
isOpen: false, //dom是否展开
data: [
addChildren: true,
addChildrenTxt: '不动产',
fatherRequired: false,
isOpen: false,
// 表格列配置
columns: [
{
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
taxCountry: '',
taxNumber: ''
}
]
},
//公司业务资料
{
keyType: 'Object', //用于表单收集值时,判断是数组还是对象
key: 'companyBusinessData',
child: 'no', //有子级dom,需要循环展示
isOpen: true, //是否展开
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
subTitle: '公司业务资料 (适用于公司老板跟股东)',
data: [
label: '类型',
prop: 'propertyType',
type: 'select',
dictType: 'csf_property_type',
placeholder: '请选择',
required: true
},
{
label: '公司過去兩年平均純利',
key: 'averageNetProfit',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '220px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
label: '房地产地址',
prop: 'address',
type: 'input',
placeholder: '请输入地址',
required: false
},
{
label: '公司現時大約的總資產',
key: 'estimatedTotalAssets',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '220px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
label: '市值',
prop: 'marketValue',
type: 'inputNumber',
placeholder: '请输入市场价值',
required: false
},
{
label: '币种',
key: 'currency',
domType: 'Select',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
prop: 'currency',
type: 'select',
dictType: 'bx_currency_type',
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
},
placeholder: '请选择',
required: false
}
],
data: [
{
label: '资产所佔百分比 (%)',
key: 'assetPercentage',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '220px', //标签宽度
sm: 8, //栅格布局份数
lg: 8 //栅格布局份数
propertyType: '',
address: '',
marketValue: '',
currency: ''
}
]
},
//支出
// 保费负担能力评估
{
key: 'incomeExpense',
keyType: 'Object', //用于表单收集值时,判断是数组还是对象
child: 'no',
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
fatherTitle: '保费负担能力评估',
type: 'object',
key: 'premiumAffordability',
anchorKey: 'premiumAffordability',
showTable: false,
showMoudle: true,
data: [
{
label:
'在过去12个月里,你从所有所得的收入来源所得的平均每月收入为(包括薪金、花红、佣金、其他薪酬红利、银行存款利息、债券利息及股息等。',
label: '在过去12个月里你的平均每月收入',
key: 'monthlyIncome',
value: '',
domType: 'Input',
inputType: 'text',
required: false,
unit: 'HKD',
showDes: true, //是否展示描述
inputType: 'number',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
placeholder: '请输入平均每月收入',
tooltip: '包括薪金、花红、佣金、其他薪酬红利、银行存款利息、债券利息及股息等',
show: true,
inputWidth: '300px',
labelWidth: '800px', //标签宽度
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 24, //栅格布局份数
lg: 24, //栅格布局份数
labelPosition: 'top' //标签的位置
lg: 8 //栅格布局份数
},
{
label: '过去12个月每月里,你每月的平均开支为',
label: '在过去12个月里你的平均每月开支',
key: 'monthlyExpense',
value: '',
domType: 'Input',
inputType: 'text',
required: false,
unit: 'HKD',
showDes: true, //是否展示描述
inputType: 'number',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
placeholder: '请输入平均每月开支',
show: true,
inputWidth: '300px', //输入框宽度
labelWidth: '260px', //标签宽度
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 24, //栅格布局份数
lg: 12, //栅格布局份数
labelPosition: 'top' //标签的位置
}
]
},
{
key: 'liquidAssets',
keyType: 'Object', //用于表单收集值时,判断是数组还是对象
child: 'no',
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
data: [
lg: 8 //栅格布局份数
},
{
label: '您现时的累积流动资产约有多少?',
key: 'liquidAssets',
value: '',
domType: 'Input',
inputType: 'text',
required: false,
unit: 'HKD',
inputType: 'number',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
placeholder: '请输入流动资产',
tooltip: '流動资産是指可以容易變為现金的資産。例如現金、存款、外幣及股票,不包括物業。',
show: true,
inputWidth: '300px', //输入框宽度
labelWidth: '220px', //标签宽度
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 24, //栅格布局份数
lg: 12, //栅格布局份数
labelPosition: 'top' //标签的位置
lg: 8 //栅格布局份数
},
{
label: '流动资产种类',
label: '流动资产种类有?(多选)',
key: 'liquidAssetType',
value: [],
domType: 'Checkbox',
required: false,
dictType: 'csf_liquid_asset_type',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '100px', //标签宽度
sm: 24, //栅格布局份数
lg: 24, //栅格布局份数
labelPosition: 'top', //标签的位置
dictType: 'csf_liquid_asset_type'
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '',
key: 'otherLiquidAsset',
inputType: 'Input',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: false,
labelWidth: '0px', //标签宽度
sm: 24, //栅格布局份数
lg: 24, //栅格布局份数
labelPosition: 'top' //标签的位置
}
]
},
{
fatherTitle: '',
keyType: 'Object', //用于表单收集值时,判断是数组还是对象
child: 'no',
fatherRequired: false, //父级必填,代表个人资料这个模块有必填项
key: 'other',
data: [
{
label: '首期及续保保费的财富来源',
label: '首期及续保保费的财富来源?(多选)',
key: 'premiumFundingSource',
value: [],
domType: 'Checkbox',
required: false,
maxLength: 30,
dictType: 'csf_premium_funding_source',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '180px', //标签宽度
sm: 24, //栅格布局份数
lg: 24, //栅格布局份数
labelPosition: 'top', //标签的位置
dictType: 'csf_premium_funding_source'
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
]
}
// 公司业务资料
// {
// fatherTitle: '公司业务资料',
// type: 'object',
// key: 'companyBusinessData',
// anchorKey: 'companyBusinessData',
// showTable: false,
// showMoudle: true,
// data: [
// {
// label: '公司过去两年平均纯利',
// key: 'averageNetProfit',
// value: '',
// domType: 'Input',
// unit: 'HKD',
// inputType: 'number',
// required: false,
// maxLength: 300,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '公司现时大约总资产',
// key: 'estimatedTotalAssets',
// value: '',
// domType: 'Input',
// unit: 'HKD',
// inputType: 'number',
// required: false,
// maxLength: 300,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '币种',
// key: 'currency',
// value: '',
// domType: 'Select',
// required: false,
// disabled: false,
// placeholder: '请选择',
// dictType: 'bx_currency_type',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '资产所占百分比(%)',
// key: 'assetPercentage',
// value: '',
// domType: 'Input',
// unit: 'HKD',
// inputType: 'number',
// required: false,
// maxLength: 300,
// disabled: false,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// }
// ]
// }
]
export default fnaForm
......@@ -10,7 +10,6 @@ const insured = [
{
label: '与投保人关系',
key: 'policyholderRel',
// customerKey: 'customerType',
domType: 'Select',
required: true,
disabled: false,
......@@ -498,7 +497,7 @@ const insured = [
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '总负债额',
key: 'totalDebt',
......
import { anchorKey } from 'element-plus/es/components/anchor/src/constants.mjs'
const productPlan = [
{
fatherTitle: '',
fatherTitle: '基础信息',
keyType: 'Object', //用于表单收集值时,判断是数组还是对象
key: 'apiProductPlanMainInfoDto',
child: 'no', //有子级dom,需要循环展示
anchorKey: 'apiProductPlanMainInfoDto',
showMoudle: true, //模块是否展示
showTable: false, //是否展示表格
fatherRequired: true, //父级必填,代表个人资料这个模块有必填项
data: [
{
label: '保险公司',
key: 'companyName',
domType: 'SearchSelect',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
labelPosition: 'top', //标签的位置
lg: 8 //栅格布局份数
},
{
label: '保险种类',
key: 'insuranceTypeName',
domType: 'SearchSelect',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
labelPosition: 'top', //标签的位置
lg: 8 //栅格布局份数
},
{
label: '产品名称',
key: 'productName',
key: 'productLaunchName',
domType: 'SearchSelect',
required: true,
maxLength: 30,
......@@ -22,13 +53,27 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '地区',
key: 'region',
label: '供款期数',
key: 'issueNumber',
domType: 'Select',
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'issueNumber',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保障年期',
key: 'guaranteePeriod',
domType: 'Input',
inputType: 'text',
required: false,
inputType: 'number',
required: true,
maxLength: 20,
disabled: true,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
......@@ -37,8 +82,8 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '货币',
key: 'currency',
label: '保单币种',
key: 'policyCurrency',
domType: 'Select',
required: true,
disabled: false,
......@@ -51,14 +96,14 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '供款年期',
key: 'paymentTerm',
domType: 'Select',
required: true,
label: '保单额度(重疾)',
key: 'sumInsured',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 20,
disabled: false,
placeholder: '请选择',
dictType: 'paymentTerm',
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -95,14 +140,13 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '保额',
key: 'sumInsured',
domType: 'Input',
inputType: 'number',
label: '首期付款方式',
key: 'initialPaymentMethod',
domType: 'Select',
required: false,
maxLength: 20,
disabled: false,
placeholder: '请输入',
placeholder: '请选择',
dictType: 'csf_ap_first_issue',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -110,13 +154,14 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '是否预缴保费',
key: 'isPrepay',
domType: 'Select',
label: '保单征费',
key: 'policyLevy',
domType: 'Input',
inputType: 'number',
required: true,
maxLength: 20,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -124,13 +169,13 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '首期付款方式',
key: 'initialPaymentMethod',
label: '是否预缴',
key: 'isPrepay',
domType: 'Select',
required: false,
required: true,
disabled: false,
placeholder: '请选择',
dictType: 'csf_ap_first_issue',
dictType: 'sys_no_yes',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -138,13 +183,13 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '续期付款方式',
key: 'renewalPaymentMethod',
label: '是否追溯',
key: 'isTraceable',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'csf_ap_first_issue',
dictType: 'sys_no_yes',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -152,13 +197,13 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '红利分配方式',
key: 'dividendDistributionMethod',
label: '保单日期回溯',
key: 'isBacktrack',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'csf_ap_dividend',
dictType: 'sys_no_yes',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
......@@ -166,8 +211,8 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '保单日期回溯',
key: 'isBacktrack',
label: '是否参加递增保障权益',
key: 'isJoin',
domType: 'Select',
required: false,
disabled: false,
......@@ -180,44 +225,75 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '保单生效日',
key: 'policyEffectiveDate',
domType: 'DatePicker',
label: '红利分配方式',
key: 'dividendDistributionMethod',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
show: false,
dictType: 'csf_ap_dividend',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '是否参加递增保障权益',
key: 'isJoin',
label: '续期付款方式',
key: 'renewalPaymentMethod',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'sys_no_yes',
dictType: 'csf_ap_first_issue',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
}
// {
// label: '地区',
// key: 'region',
// domType: 'Input',
// inputType: 'text',
// required: false,
// maxLength: 20,
// disabled: true,
// placeholder: '请输入',
// show: true,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// },
// {
// label: '保单生效日',
// key: 'policyEffectiveDate',
// domType: 'DatePicker',
// required: false,
// disabled: false,
// placeholder: '请选择',
// show: false,
// labelPosition: 'top', //标签的位置
// labelWidth: '120px', //标签宽度
// sm: 12, //栅格布局份数
// lg: 8 //栅格布局份数
// }
]
},
//附加险
{
showMoudle: true, //模块是否展示
fatherTitle: '附加',
fatherTitle: '附加计划',
keyType: 'Array', //用于表单收集值时,判断是数组还是对象
key: 'apiProductPlanAdditionalInfoDtoList',
child: 'yes', //有子级dom,需要循环展示
anchorKey: 'apiProductPlanAdditionalInfoDtoList',
fatherRequired: true, //父级必填,代表个人资料这个模块有必填项
addBtn: true,
emptySpan: 24, //空状态得span
addChildren: true,
addChildrenTxt: '新增附加险',
showTable: true, //是否展示表格
data: [
// {
// id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
......@@ -347,6 +423,169 @@ const productPlan = [
// }
// ]
// }
],
// 弹窗表单的配置
formItem: [
{
label: '产品名称',
value: '',
key: 'productLaunchName',
domType: 'SearchSelect',
required: false,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
labelPosition: 'top', //标签的位置
lg: 8 //栅格布局份数
},
{
label: '供款期数',
key: 'issueNumber',
value: '',
domType: 'Select',
required: false,
disabled: false,
placeholder: '请选择',
dictType: 'issueNumber',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保障年期(若是终身,输入999)',
key: 'guaranteePeriod',
value: '',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保单币种',
key: 'policyCurrency',
value: '',
domType: 'Select',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
dictType: 'bx_currency_type',
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保单额度(重疾)',
key: 'sumInsured',
value: '',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '每期保费',
key: 'eachIssuePremium',
value: '',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保障地区',
key: 'guaranteeRegion',
value: '',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保障级别',
value: '',
key: 'protectionLevel',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '自付额',
value: '',
key: 'deductibles',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '附加保障',
value: '',
key: 'additionalSafeguards',
domType: 'Input',
inputType: 'textarea',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 24, //栅格布局份数
lg: 24 //栅格布局份数
}
]
}
]
......
......@@ -9,7 +9,13 @@ const useDictStore = defineStore('dict', {
insureCompanyList: [], //保险公司数据
clientUserList: [], //用户数据,转介人
dictTypeLists: [], //字典列表,根据请求得不同会变化,所以使用之前需要使用useDictLists请求数据
signNameList: []
signNameList: [],
bankList: [], //银行列表
userSaleExpandList: [], //最新转介人列表
productAdditionalList: [], //附加险产品列表对应的是产品计划
signPeopleList: [], //所有签单员
allTeaList: [], //所有团队
allInsuranceCompanyList: [] //最新的保险公司列表
}),
actions: {
// 获取字典
......@@ -84,6 +90,30 @@ const useDictStore = defineStore('dict', {
// 设置签单人姓名列表
setSignNameList(nameList) {
this.signNameList = nameList
},
//设置银行列表
setBankList(list) {
this.bankList = list
},
//设置最新转介人列表
setUserSaleExpandList(list) {
this.userSaleExpandList = list
},
//设置最新的附加险产品列表
setProductAdditionalList(list) {
this.productAdditionalList = list
},
//设置签单员列表
setSignPeopleList(list) {
this.signPeopleList = list
},
//设置团队列表
setAllTeaList(list) {
this.allTeaList = list
},
//设置最新的保险公司列表
setAllInsuranceCompanyList(list) {
this.allInsuranceCompanyList = list
}
}
})
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -153,6 +153,46 @@ export const validateEnglish = (rule, value, callback) => {
callback()
}
/**
* 英文姓名校验规则
*/
export const validateChinese = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入中文姓名'))
return
}
// 验证是否只包含中文字符
const chineseRegex = /^[\u4e00-\u9fa5]+$/
if (!chineseRegex.test(value)) {
callback(new Error('只能输入中文'))
return
}
// 验证长度在2-6之间
if (value.length < 2 || value.length > 6) {
callback(new Error('长度应在2-6个字符之间'))
return
}
callback()
}
/**
* BMI校验规则
*/
export const validateBMI = (rule, value, callback) => {
if (!value) {
return
}
if (value < 19) {
return callback(new Error('BMI值不能小于19'))
}
if (value >= 23.5) {
return callback(new Error('BMI值不能大于23.5'))
}
callback()
}
/**
* 手机号校验规则
......@@ -169,7 +209,401 @@ export const validatePhone = (rule, value, callback) => {
callback()
}
// 身份证验证相关方法
/**
* 验证身份证号码是否合法
* @param {string} idCard 身份证号码
* @returns {boolean} 是否合法
*/
export function validIDCard(idCard) {
if (!idCard) return false
const idCardStr = idCard.toString().trim()
// 长度验证
if (idCardStr.length !== 15 && idCardStr.length !== 18) {
return false
}
// 格式验证
if (idCardStr.length === 15) {
// 15位身份证:全部为数字
if (!/^\d{15}$/.test(idCardStr)) {
return false
}
// 验证出生日期
const birthDateStr = '19' + idCardStr.substr(6, 6) // 19yyMMdd
if (!validateBirthDate(birthDateStr)) {
return false
}
// 验证省份代码
const provinceCode = idCardStr.substr(0, 2)
if (!validateProvinceCode(provinceCode)) {
return false
}
} else if (idCardStr.length === 18) {
// 18位身份证:前17位为数字,最后一位为数字或X(大小写)
if (!/^\d{17}[\dXx]$/.test(idCardStr)) {
return false
}
// 验证出生日期
const birthDateStr = idCardStr.substr(6, 8) // yyyyMMdd
if (!validateBirthDate(birthDateStr)) {
return false
}
// 验证省份代码
const provinceCode = idCardStr.substr(0, 2)
if (!validateProvinceCode(provinceCode)) {
return false
}
// 验证校验码
if (!validateCheckCode(idCardStr.toUpperCase())) {
return false
}
}
return true
}
/**
* 验证出生日期是否有效
* @param {string} birthDateStr 出生日期字符串 (yyyyMMdd 或 yyMMdd)
* @returns {boolean} 是否有效
*/
function validateBirthDate(birthDateStr) {
// 统一为8位格式
if (birthDateStr.length === 6) {
birthDateStr = '19' + birthDateStr
}
if (birthDateStr.length !== 8) {
return false
}
const year = parseInt(birthDateStr.substr(0, 4))
const month = parseInt(birthDateStr.substr(4, 2))
const day = parseInt(birthDateStr.substr(6, 2))
// 验证年月日是否有效
if (year < 1900 || year > new Date().getFullYear()) {
return false
}
if (month < 1 || month > 12) {
return false
}
// 验证每月天数
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
// 闰年二月处理
if (month === 2 && isLeapYear(year)) {
if (day < 1 || day > 29) {
return false
}
} else {
if (day < 1 || day > daysInMonth[month - 1]) {
return false
}
}
// 验证日期不能晚于当前日期
const birthDate = new Date(year, month - 1, day)
const currentDate = new Date()
if (birthDate > currentDate) {
return false
}
// 验证年龄(最大150岁)
const age = calculateAge(birthDate)
if (age > 150) {
return false
}
return true
}
/**
* 验证省份代码
* @param {string} code 省份代码
* @returns {boolean} 是否有效
*/
function validateProvinceCode(code) {
const provinceCodes = [
'11',
'12',
'13',
'14',
'15', // 华北
'21',
'22',
'23', // 东北
'31',
'32',
'33',
'34',
'35',
'36',
'37', // 华东
'41',
'42',
'43',
'44',
'45',
'46', // 华中/华南
'50',
'51',
'52',
'53',
'54', // 西南
'61',
'62',
'63',
'64',
'65', // 西北
'71',
'81',
'82',
'91' // 港澳台及国外
]
return provinceCodes.includes(code)
}
/**
* 验证18位身份证的校验码
* @param {string} idCard 18位身份证号码(需大写)
* @returns {boolean} 是否校验通过
*/
function validateCheckCode(idCard) {
// 校验码对应关系
const checkCodeMap = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
// 系数表
const coefficient = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
// 计算校验位
let sum = 0
for (let i = 0; i < 17; i++) {
sum += parseInt(idCard.charAt(i)) * coefficient[i]
}
// 取模
const mod = sum % 11
// 获取计算出的校验码
const expectedCheckCode = checkCodeMap[mod]
// 与实际校验码比较
const actualCheckCode = idCard.charAt(17)
return expectedCheckCode === actualCheckCode
}
/**
* 判断是否为闰年
* @param {number} year 年份
* @returns {boolean} 是否为闰年
*/
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
}
/**
* 计算年龄
* @param {Date} birthDate 出生日期
* @returns {number} 年龄
*/
function calculateAge(birthDate) {
const today = new Date()
let age = today.getFullYear() - birthDate.getFullYear()
const monthDiff = today.getMonth() - birthDate.getMonth()
// 如果当前月份小于出生月份,或者月份相同但日期小于出生日期,则年龄减1
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--
}
return age
}
/**
* 从身份证提取信息
* @param {string} idCard 身份证号码
* @returns {Object|null} 身份证信息对象,无效返回null
*/
export function extractIDCardInfo(idCard) {
if (!validIDCard(idCard)) {
return null
}
const idCardStr = idCard.toString().trim().toUpperCase()
// 提取出生日期
let birthDateStr = ''
if (idCardStr.length === 15) {
birthDateStr = '19' + idCardStr.substr(6, 6)
} else {
birthDateStr = idCardStr.substr(6, 8)
}
const year = parseInt(birthDateStr.substr(0, 4))
const month = parseInt(birthDateStr.substr(4, 2))
const day = parseInt(birthDateStr.substr(6, 2))
// 提取性别
let genderCode = 0
if (idCardStr.length === 15) {
genderCode = parseInt(idCardStr.substr(14, 1))
} else {
genderCode = parseInt(idCardStr.substr(16, 1))
}
const gender = genderCode % 2 === 1 ? 1 : 0 // 1:男, 0:女
// 提取省份代码
const provinceCode = idCardStr.substr(0, 2)
const province = getProvinceName(provinceCode)
// 计算年龄
const birthDate = new Date(year, month - 1, day)
const age = calculateAge(birthDate)
return {
provinceCode,
province,
birthDate: `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`,
year,
month,
day,
gender,
genderText: gender === 1 ? '男' : '女',
age
}
}
/**
* 根据省份代码获取省份名称
* @param {string} code 省份代码
* @returns {string} 省份名称
*/
function getProvinceName(code) {
const provinceMap = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外'
}
return provinceMap[code] || '未知'
}
/**
* 身份证校验规则(用于Element Plus表单验证)
*/
export const validateIdCard = (rule, value, callback) => {
if (!value) {
// 如果值为空且字段不是必填的,直接通过校验
// 如果必填,应该在rules中另外添加required规则
return callback()
}
// 基本格式检查
const idCardStr = value.toString().trim()
if (idCardStr.length !== 15 && idCardStr.length !== 18) {
return callback(new Error('身份证号码长度应为15位或18位'))
}
if (idCardStr.length === 15) {
// 15位身份证:全部为数字
if (!/^\d{15}$/.test(idCardStr)) {
return callback(new Error('15位身份证号码应全部为数字'))
}
} else {
// 18位身份证:前17位为数字,最后一位为数字或X
if (!/^\d{17}[\dXx]$/.test(idCardStr)) {
return callback(new Error('18位身份证号码格式不正确'))
}
}
// 使用完整验证函数
if (!validIDCard(value)) {
return callback(new Error('请输入有效的身份证号码'))
}
callback()
}
/**
* 简单验证身份证格式(不验证校验码和详细逻辑)
*/
export const validateIdCardSimple = (rule, value, callback) => {
if (!value) {
return callback()
}
const idCardStr = value.toString().trim()
// 15位身份证验证
if (idCardStr.length === 15) {
if (!/^\d{15}$/.test(idCardStr)) {
return callback(new Error('15位身份证号码应全部为数字'))
}
} else if (idCardStr.length === 18) {
// 18位身份证验证
if (!/^\d{17}[\dXx]$/.test(idCardStr)) {
return callback(new Error('18位身份证号码格式不正确'))
}
} else {
return callback(new Error('身份证号码长度应为15位或18位'))
}
callback()
}
// 将身份证验证方法添加到默认导出对象中
export default {
validateEnglish,
validatePhone
validateChinese,
validatePhone,
validateBMI,
validateIdCard,
validateIdCardSimple
}
<template>
<div class="formContainer">
<div class="formLeft" v-if="showAnchor">
<el-affix :offset="affixOffset">
<el-anchor
:direction="direction"
:type="type"
:offset="anchorOffset"
@click="handleAnchorClick"
>
<!-- -->
<el-anchor-link
v-for="item in anchorList"
:href="'#' + item.title"
:title="item.name"
@click="e => handleLinkClick(e, item.title)"
/>
</el-anchor>
</el-affix>
</div>
<div class="formRight" :class="showAnchor ? 'formRightSelf' : ''">
<slot name="form-right"></slot>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, getCurrentInstance } from 'vue'
const props = defineProps({
containerRef: {
type: Object,
default: () => {
return {}
}
},
direction: {
type: String,
default: 'vertical'
},
type: {
type: String,
default: 'default'
},
anchorOffset: {
type: Number,
default: 30
},
affixOffset: {
type: Number,
default: 60
},
anchorList: {
type: Array,
default: () => {
return []
}
},
// 新增:滚动容器的选择器
scrollContainerSelector: {
type: String,
default: ''
},
// 新增:滚动到元素时额外的偏移量
scrollOffset: {
type: Number,
default: 0
},
domIndex: {
type: Number,
default: 0
},
showAnchor: {
type: Boolean,
default: true
}
})
const emit = defineEmits(['anchor-click'])
// 处理锚点点击
const handleAnchorClick = e => {
// 阻止默认的锚点跳转
e.preventDefault()
}
// 处理链接点击
const handleLinkClick = (e, anchorId) => {
e.preventDefault()
e.stopPropagation()
emit('anchor-click', anchorId)
// 延迟执行滚动,确保 DOM 已经更新
setTimeout(() => {
scrollToAnchor(anchorId)
}, 50)
}
// 滚动到锚点
const scrollToAnchor = anchorId => {
const targetElement = document.getElementById(anchorId)
if (!targetElement) return
let scrollContainer
if (props.scrollContainerSelector) {
scrollContainer = document.querySelectorAll(props.scrollContainerSelector)
}
if (scrollContainer.length > 0) {
// 计算在容器内的相对位置
const containerRect = scrollContainer[props.domIndex].getBoundingClientRect()
const targetRect = targetElement.getBoundingClientRect()
// 计算滚动位置
const scrollTop =
targetRect.top -
containerRect.top +
scrollContainer[props.domIndex].scrollTop -
props.scrollOffset
// 平滑滚动
scrollContainer[props.domIndex].scrollTo({
top: scrollTop,
behavior: 'smooth'
})
} else {
// 如果没有指定容器,使用默认滚动
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
})
}
}
// 暴露方法给父组件
defineExpose({
scrollToAnchor
})
</script>
<style lang="scss" scoped>
.formContainer {
width: 100%;
box-sizing: border-box;
display: flex;
}
.formLeft {
width: 15%;
box-sizing: border-box;
height: 100vh;
}
.formRight {
flex: 1;
padding-left: 10px;
box-sizing: border-box;
}
.formRightSelf {
border-left: 3px solid rgb(247 247 247);
}
</style>
<template>
<div>
<div v-if="processedCustomerData.length > 0" class="customerContainer">
<div class="customerContainer">
<div ref="customerRightRef">
<div class="editBtn">
<el-button
v-if="props.customerBizId"
v-if="props.customerBizId && tabSource == 'customer'"
type="primary"
icon="EditPen"
@click="handleEditStatus"
>编辑</el-button
>
</div>
<div class="customerLeft" v-if="customerRightRef">
<CommonAnchor
:anchorList="anchorList"
:affixOffset="250"
:anchorOffset="10"
:scrollContainerSelector="'.tabPaneBox'"
:scrollOffset="10"
:domIndex="1"
/>
</div>
<div class="customerRight" ref="customerRightRef">
<el-form ref="customerRef" :model="form" :rules="rules" label-width="120px">
<el-row v-for="(father, fIndex) in processedCustomerData" :id="father.anchorKey">
<div class="formBox">
<CardOne :title="father.fatherTitle">
<template #content>
<el-row :gutter="20" v-if="!father.showTable">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItem" v-if="child.show">
<div>
<el-form-item
:label="
child.key === 'residentialAddress' && child.type === 'arrowRight'
? ''
: child.label
"
:prop="child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<!-- 自定义 label 插槽 -->
<template
v-if="
child.key === 'residentialAddress' && child.type === 'arrowRight'
<CommonForm
:anchorList="anchorList"
:affixOffset="affixOffset"
:anchorOffset="10"
:scrollContainerSelector="anchorContainer"
:scrollOffset="10"
:domIndex="tabIndex"
:activeName="activeName"
v-if="customerRightRef"
>
<template #form-right>
<el-form :model="form" :rules="rules" label-width="120px" ref="customerFormRef">
<el-row v-for="(father, fIndex) in processedCustomerData" :id="father.anchorKey">
<div class="formBox">
<CardOne :title="father.fatherTitle" v-if="father.showMoudle">
<template #content>
<el-row :gutter="20" v-if="!father.showTable">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItem" v-if="child.show">
<div>
<el-form-item
:label="
child.key === 'residentialAddress' && child.domType === 'arrowRight'
? ''
: child.label
"
#label
>
<div class="custom-label">
<span>{{ child.label }}</span>
<el-checkbox-group
v-model="form.isCopyAddress"
size="small"
style="margin-left: 8px"
@change="changeAddressStatus(child)"
:disabled="copyAddress"
>
<el-checkbox :value="true" name="isCopyAddress">
同通讯地址
</el-checkbox>
</el-checkbox-group>
</div>
</template>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="child.disabled"
@change="handleInputChange(child)"
:prop="child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<template #append v-if="child.unit" @click="handleAppendInput(child)">
<span :style="{ color: child.unitColor }">{{ child.unit }}</span>
<!-- 自定义 label 插槽 -->
<template
v-if="
child.key === 'residentialAddress' &&
child.domType === 'arrowRight'
"
#label
>
<div class="custom-label">
<span>{{ child.label }}</span>
<el-checkbox-group
v-model="form.isCopyAddress"
size="small"
style="margin-left: 8px"
@change="changeAddressStatus(child)"
:disabled="copyAddress"
>
<el-checkbox :value="true" name="isCopyAddress">
同通讯地址
</el-checkbox>
</el-checkbox-group>
</div>
</template>
</el-input>
<el-select
v-if="child.domType === 'Select'"
v-model="form[child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(child)"
:disabled="child.disabled"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="
child.key == 'age' || child.key == 'bmi' ? true : editStatus
"
@blur="handleInputBlur(child)"
>
<template #append v-if="child.unit">
<span
@click="handleAppendInput(child)"
:style="{ color: child.unitColor }"
>{{ child.unit }}</span
>
</template>
</el-input>
<el-select
v-if="child.domType === 'Select'"
v-model="form[child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(child)"
:disabled="editStatus"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[child.key]"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:placeholder="child.placeholder"
:disabled="editStatus"
:disabled-date="time => disabledDate(time, child)"
:default-value="defaultDisplayDate"
@change="handleDateChange(child)"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[child.key]"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:placeholder="child.placeholder"
:disabled="child.disabled"
:disabled-date="time => disabledDate(time, child)"
:default-value="defaultDisplayDate"
@change="handleDateChange(child)"
/>
<el-input
v-if="child.domType === 'arrowRight'"
v-model="form[child.key]"
:placeholder="child.placeholder"
@click="handleFoucs(child)"
:suffix-icon="ArrowRight"
readonly
:disabled="child.disabled"
>
</el-input>
</el-form-item>
</div>
</el-col>
</template>
</el-row>
<el-row v-if="father.showTable">
<el-col :span="24" v-if="father.addChildren">
<el-button
:disabled="editStatus"
type="primary"
icon="Plus"
size="small"
style="margin-bottom: 10px"
@click="addChildren(father)"
>{{ father.addChildrenTxt }}</el-button
>
</el-col>
<el-table :data="father.data" border v-if="father.data.length > 0">
<template v-if="father.key == 'apiTaxationDtoList'">
<el-table-column label="税务国家" prop="taxCountry" align="center">
<template #default="scope">
<el-input
size="default"
placeholder="请输入"
v-model="scope.row.taxCountry"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="税务编号" prop="taxId" align="center">
<template #default="scope">
<el-input
v-model="scope.row.taxId"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon
class="deleteIcon"
@click="deleteChildren(father, scope.$index)"
><Delete
/></el-icon>
</template>
</el-table-column>
<el-input
v-if="child.domType === 'arrowRight'"
v-model="form[child.key]"
:placeholder="child.placeholder"
@click="handleFoucs(child)"
:suffix-icon="ArrowRight"
readonly
:disabled="editStatus"
>
</el-input>
</el-form-item>
</div>
</el-col>
</template>
</el-table>
</el-row>
</template>
</CardOne>
</div>
</el-row>
<el-row>
<el-col>
<div class="tabButton">
<el-button
type="primary"
icon="RefreshRight"
@click="resetForm"
size="large"
:disabled="editStatus"
>取消</el-button
>
<el-button
type="primary"
icon="Check"
@click="submitForm"
size="large"
:disabled="editStatus"
>提交</el-button
>
</el-row>
<el-row v-if="father.showTable">
<el-col :span="24" v-if="father.addChildren">
<el-button
:disabled="editStatus"
type="primary"
icon="Plus"
size="small"
style="margin-bottom: 10px"
@click="addChildren(father)"
>{{ father.addChildrenTxt }}</el-button
>
</el-col>
<el-table :data="father.data" border v-if="father.data.length > 0">
<template v-if="father.key == 'apiTaxationDtoList'">
<el-table-column label="税务国家" prop="taxCountry" align="center">
<template #default="scope">
<el-input
size="default"
placeholder="请输入"
v-model="scope.row.taxCountry"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="税务编号" prop="taxId" align="center">
<template #default="scope">
<el-input
v-model="scope.row.taxId"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon
class="deleteIcon"
@click="deleteChildren(father, scope.$index)"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
</el-table>
</el-row>
</template>
</CardOne>
</div>
</el-col>
</el-row>
</el-form>
</div>
<el-dialog title="客户信息" v-model="openList" width="600px" append-to-body>
<div>
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="68px">
<el-form-item label="客户姓名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入姓名" @input="customerList" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" circle @click="customerList" />
<el-button type="info" icon="Refresh" circle @click="resetCustomerList" />
</el-form-item>
</el-form>
<div class="customerBox">
<div class="customerItem" v-for="item in tableData" :key="item.id">
<div class="top">
<div class="left">
<div>{{ item.name }}</div>
<div v-if="item.gender" style="margin: 0 5px">-</div>
<div v-if="item.gender" class="gender">
<dict-tag :options="sys_gender" :value="item.gender" />
</div>
</div>
<div class="right">
<el-button type="primary" size="small" @click="handleExport(item)"
>导入客户信息</el-button
</el-row>
<el-row v-if="tabSource == 'customer'">
<el-col>
<div class="tabButton">
<el-button
type="primary"
icon="RefreshRight"
@click="resetForm"
size="large"
:disabled="editStatus"
>取消</el-button
>
<!-- @click="submitForm" -->
<el-button
type="primary"
icon="Check"
@click="handleFormValues"
size="large"
:disabled="editStatus"
>提交</el-button
>
</div>
</div>
<div class="bottom">
<div class="infoItem">
<span>证件类型:</span>
<span> <dict-tag :options="csf_id_type" :value="item.idType" /></span>
</div>
<div class="infoItem">
<span>证件号码:</span>
<span> {{ item.idCard || '暂无' }}</span>
</div>
<div class="infoItem">
<span>电话号码:</span>
<span> {{ item.phone || '暂无' }}</span>
</div>
<div class="infoItem">
<span>出生日期:</span>
<span> {{ formatToDate(item.birthday) || '暂无' }}</span>
</div>
</div>
</div>
</div>
</div>
</el-dialog>
</el-col>
</el-row>
</el-form>
</template>
</CommonForm>
</div>
<Phone
@close="handleCloseDrawer"
......@@ -267,10 +225,93 @@
@confirmCountry="confirmDrawer"
/>
<!-- 历史客户的弹窗 -->
<CommonDialog
dialogTitle="历史客户"
:showConfirm="false"
cancleText="关闭"
dialogWidth="70%"
:openDialog="openList"
@close="openList = false"
>
<div class="dialogBox">
<CommonPage
:operationBtnList="operationBtnList"
:visibleDefaultButtons="visibleDefaultButtons"
:showSearchForm="true"
:show-pagination="true"
:currentPage="queryParams.pageNo"
:total="total"
:pageSize="queryParams.pageSize"
@current-change="changePageNo"
@size-change="changePageSize"
>
<!-- 查询条件插槽 -->
<template #searchForm>
<el-form :model="queryParams" ref="queryRef" label-width="100px" label-position="top">
<el-row :gutter="30">
<el-col :sm="12" :lg="8" :xs="24">
<el-form-item label="姓名" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入姓名" clearable />
</el-form-item>
</el-col>
<el-col :sm="12" :lg="8" :xs="24">
<el-form-item label="手机号" prop="mobile">
<el-input v-model="queryParams.mobile" placeholder="请输入手机号" clearable />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<!-- 表格插槽 -->
<template #table>
<el-table v-loading="tableLoading" :data="tableData" @row-click="handleExport">
<!-- <el-table-column type="selection" width="55" align="center" /> -->
<el-table-column label="姓名" align="center" prop="nameCn" width="200" />
<el-table-column label="性别" align="center" prop="gender">
<template #default="scope">
<dict-tag :options="fetchDictData('sys_gender')" :value="scope.row.gender" />
</template>
</el-table-column>
<el-table-column label="证件类型" align="center" prop="documentType">
<template #default="scope">
<dict-tag
:options="fetchDictData('csf_id_type')"
:value="scope.row.documentType"
/>
</template>
</el-table-column>
<el-table-column label="证件号码" align="center" prop="idNumber" />
<el-table-column label="电话号码" align="center" prop="mobile" />
<el-table-column label="出生日期" align="center" width="180" prop="birthday">
<template #default="scope">
<span>{{ scope.row.birthday ? formatToDate(scope.row.birthday) : '--' }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
width="150"
class-name="small-padding fixed-width"
fixed="right"
>
<template #default="scope">
<el-button link type="primary" @click="handleExport(scope.row)"
>使用客户资料</el-button
>
</template>
</el-table-column>
</el-table>
</template>
</CommonPage>
</div>
</CommonDialog>
</div>
</template>
<script setup name="customer">
import { validateEnglish } from '@/utils/validate'
import { validateEnglish, validateBMI, validateIdCard, validateChinese } from '@/utils/validate'
import { calculateExactAge } from '@/utils/date'
import dayjs from 'dayjs'
import { ArrowRight } from '@element-plus/icons-vue'
......@@ -278,7 +319,9 @@ import customerDomData from '@/formJson/customer'
import Country from '@/views/components/country'
import Phone from '@/views/components/phone'
import Address from '@/views/components/address'
import CommonAnchor from '@/components/commonAnchor'
import CommonForm from '@/views/components/commonForm'
import CommonDialog from '@/components/commonDialog'
import CommonPage from '@/components/commonPage'
import CardOne from '@/components/formCard/cardOne'
import { watch } from 'vue'
import {
......@@ -287,23 +330,21 @@ import {
editCustomer,
getCustomerList,
addFna,
calculateFieldValue,
calculateFieldValue
} from '@/api/sign/fna'
import useDictStore from '@/store/modules/dict'
const dictStore = useDictStore() //获取字典数据
const props = defineProps({
activeName: { type: String, default: '' }, //tab名称
tabPaneRef: {
type: Object,
default: null
},
fearthStatus: { type: String, default: '' }, //父组件状态,新增、修改
customerBizId: { type: String, default: '' } //提交状态,新增、修改
fatherEditStatus: { type: Boolean, default: true }, //因为嵌套了双层tab,所以需要父组件传值控制子组件的编辑状态
anchorContainer: { type: String, default: '' }, //锚点滚动容器
tabIndex: { type: [String, Number], default: '' }, //tab索引
affixOffset: { type: Number, default: 250 }, //锚点吸顶距离
customerBizId: { type: String, default: '' }, //提交状态,新增、修改
tabSource: { type: String, default: '' } //引用这个组件的页面来源,用于逻辑判断
})
const emit = defineEmits(['handleSuccess'])
const { proxy } = getCurrentInstance()
const { csf_id_type, sys_gender } = proxy.useDict('csf_id_type', 'sys_gender')
const anchorList = ref([]) //锚点列表
const customerRightRef = ref(null)
const showPhoneDrawer = ref(false) //电话抽屉开关
const showAddressDrawer = ref(false) //地址抽屉开关
......@@ -318,10 +359,8 @@ const oldObjInfo = ref({}) // 修改时存储原始数据,便于撤销操作
const tableLoading = ref(false)
const tableData = ref([])
const total = ref(0)
const customerRef = ref(null)
//计算默认显示的日期(18年前的今天)
const defaultDisplayDate = ref(dayjs().subtract(18, 'year').toDate())
// const copyAddress = ref(false) //是否可以复制地址
// 地址组件菜单数据
const addressMenuList = ref([
{
......@@ -377,7 +416,7 @@ const deleteKeyList = ref([
'objType',
'mailingAddress',
'residentialAddress',
'residenceAddress',
'mailingAddress',
'companyAddress'
]) // 存储需要删除的key
const data = reactive({
......@@ -387,12 +426,117 @@ const data = reactive({
rules: {}, //表单验证规则,
queryParams: {
pageNo: 1,
pageSize: 4,
pageSize: 10,
name: undefined
}
})
const { form, rules, processedCustomerData, queryParams, oldCustomerData } = toRefs(data)
const handleAppendInput = child => {}
// 控制要显示的默认按钮
const visibleDefaultButtons = ref(['query', 'reset']) // 只显示新增和查询两个默认按钮
// 按钮配置
const operationBtnList = ref([
{
key: 'reset',
size: 'small',
direction: 'right',
click: resetQuery
},
{
key: 'query',
size: 'small',
direction: 'right',
click: handleQuery
}
])
const customerFormRef = ref(null)
const changePageNo = val => {
queryParams.value.pageNo = val
customerList()
}
const changePageSize = val => {
queryParams.value.pageSize = val
customerList()
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNo = 1
customerList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm('queryRef')
queryParams.value = {
pageNo: 1,
pageSize: 10
}
handleQuery()
}
const handleAppendInput = child => {
if (child.key == 'nameCn') {
if (editStatus.value) {
proxy.$modal.confirm(`请先点击编辑在导入客户信息`, { showCancel: '0', title: '填写提示' })
return
}
openList.value = true
queryParams.value = {
pageNo: 1,
pageSize: 10
}
customerList()
}
}
const handleInputBlur = child => {
if (form.value['documentType'] == 'idCard' && child.key == 'idNumber') {
getFieldValue(child.key)
} else if (
(child.key == 'weight' || child.key == 'height') &&
form.value['weight'] &&
form.value['height']
) {
getFieldValue(child.key)
} else if (child.key == 'nameCn' && form.value['nameCn']) {
getFieldValue(child.key)
}
}
const getFieldValue = key => {
let obj = {}
if (form.value['documentType'] == 'idCard' && key == 'idNumber') {
obj = {
calculateType: 6,
requestValue: form.value['idNumber']
}
} else if (key == 'weight' || key == 'height') {
obj = {
calculateType: 5,
requestValueList: [form.value['height'], form.value['weight']]
}
} else if (key == 'nameCn') {
obj = {
calculateType: 1,
requestValue: form.value['nameCn']
}
}
calculateFieldValue(obj).then(res => {
if (res.code == 200) {
res.data.forEach(item => {
if (obj.calculateType == 6) {
if (item.calculateType == 2) {
form.value['gender'] = item.responseKey
} else if (item.calculateType == 3) {
form.value['birthday'] = item.requestValue
} else if (item.calculateType == 4) {
form.value['age'] = item.requestValue
}
} else if (obj.calculateType == 5) {
form.value['bmi'] = item.responseValue
} else if (obj.calculateType == 1) {
form.value['namePyEn'] = item.responseValue
}
})
}
})
}
// 添加表单子级dom
const addChildren = father => {
const processedData = JSON.parse(JSON.stringify(processedCustomerData.value))
......@@ -401,7 +545,7 @@ const addChildren = father => {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
taxCountry: '',
taxNumber: ''
taxId: ''
}
for (const section of processedData) {
......@@ -409,9 +553,8 @@ const addChildren = father => {
section.data.push(obj4)
}
}
//更新form表单对应的数据,以便收集填写的值
// form.value[father.key].push(obj)
processedCustomerData.value = processedData
console.log('processedCustomerData.value', processedCustomerData.value)
}
const deleteChildren = (father, childIndex) => {
if (editStatus.value) {
......@@ -427,10 +570,10 @@ const deleteChildren = (father, childIndex) => {
processedCustomerData.value = processedData
}
const copyAddress = computed(() => {
const residenceAddressIndex = addressQuickList.value.findIndex(
item => item.type === 'residenceAddress'
const mailingAddressIndex = addressQuickList.value.findIndex(
item => item.type === 'mailingAddress'
)
if (residenceAddressIndex !== -1) {
if (mailingAddressIndex !== -1) {
return false
} else {
return true
......@@ -440,10 +583,10 @@ const changeAddressStatus = child => {
// 复用地址
if (form.value.isCopyAddress.length > 0 && form.value.isCopyAddress[0]) {
if (child.key == 'residentialAddress') {
form.value[child.key] = form.value['residenceAddress']
form.value[child.key] = form.value['mailingAddress']
// 这里是直接复用地址了,但是地址组件的值是双向绑定的,所以这里需要手动更新地址组件的值
addressQuickList.value.forEach(item => {
if (item.type == 'residenceAddress') {
if (item.type == 'mailingAddress') {
saveKey.value[child.key] = { ...item, type: child.key }
}
})
......@@ -451,15 +594,7 @@ const changeAddressStatus = child => {
}
console.log('saveKey.value', saveKey.value)
}
const handleInputChange = child => {
if (
(child.key == 'lastName' || child.key == 'firstName') &&
form.value['lastName'] &&
form.value['firstName']
) {
form.value['name'] = form.value['lastName'] + form.value['firstName']
}
}
const handleDateChange = child => {
let age = null
if (child.key == 'birthday') {
......@@ -479,20 +614,16 @@ const disabledDate = (time, child) => {
return time.getTime() > Date.now()
}
}
const resetCustomerList = () => {
queryParams.value = {
pageNo: 1,
pageSize: 4,
name: undefined
}
customerList()
}
const exportInfo = () => {
if (props.customerBizId && editStatus.value) {
proxy.$modal.confirm(`请先点击编辑在导入客户信息`, { showCancel: '0', title: '填写提示' })
return
}
queryParams.value = {
pageNo: 1,
pageSize: 10,
name: undefined
}
openList.value = true
customerList()
}
......@@ -510,7 +641,11 @@ const customerList = () => {
}
// 从客户列表中导入客户信息到当前表单
const handleExport = row => {
oldCustomerData.value = JSON.parse(JSON.stringify(processedCustomerData.value)) // 修改时存储原始数据,便于撤销操作
oldObjInfo.value = JSON.parse(JSON.stringify(form.value)) // 修改时存储原始数据,便于撤销操作
console.log('导入前form', oldObjInfo.value)
console.log('导入前dom', oldCustomerData.value)
setFormValue(row, processedCustomerData.value, true)
openList.value = false
}
......@@ -537,12 +672,30 @@ const fetchDictData = dictType => {
}
// 处理表单配置,添加字典数据
const processFormData = async () => {
anchorList.value = []
// 深拷贝原始数据
const processedData = JSON.parse(JSON.stringify(customerDomData))
rules.value = {}
for (const section of processedData) {
anchorList.value.push({ title: section.anchorKey, name: section.fatherTitle })
// 如果在受保人中,与投保人关系已填写,根据填写内容展示对应的模块
if (
props.activeName == 'insurantInfo' &&
form.value['policyholderRel'] &&
form.value['policyholderRel'] == 'MYSELF'
) {
if (section.key == 'policyholderRel') {
section.showMoudle = true
} else {
section.showMoudle = false
}
} else {
section.showMoudle = true
}
if (props.activeName == 'insurantInfo' && section.key == 'policyholderRel') {
section.showMoudle = true
} else if (props.activeName !== 'insurantInfo' && section.key == 'policyholderRel') {
section.showMoudle = false
}
if (section.data) {
for (const field of section.data) {
if (field.dictType) {
......@@ -555,32 +708,38 @@ const processFormData = async () => {
{ required: true, message: `${field.label}不能为空`, trigger: 'blur' },
{ validator: validateEnglish, trigger: 'change' }
]
} else if (field.key === 'nameCn') {
rules.value[field.key] = [
{ required: true, message: `${field.label}不能为空`, trigger: 'blur' },
{ validator: validateChinese, trigger: 'blur' }
]
} else {
rules.value[field.key] = [
{ required: true, message: `${field.label}不能为空`, trigger: 'blur' }
]
}
}
if (props.customerBizId) {
field.disabled = true
} else if (field.key !== 'age') {
field.disabled = false
}
// if (field.key === 'bmi') {
// rules.value[field.key] = [
// { required: false, trigger: 'change' },
// { validator: validateBMI,trigger: 'change' }
// ]
// }
}
}
}
// 为私有的加form验证
if (props.activeName == 'insurantInfo') {
rules.value['policyholderRel'] = [
{ required: true, message: `与投保人关系不能为空`, trigger: 'blur' }
]
}
if (props.customerBizId) {
getCustomerInfo(props.customerBizId, processedData)
editStatus.value = true
} else {
editStatus.value = false
form.value.customerType = 'INDIVIDUAL'
processedCustomerData.value = oldCustomerData.value = processedData
}
console.log('====================================')
console.log('anchorList.value', anchorList.value)
console.log('====================================')
console.log('form', form.value)
}
//弹出右侧抽屉
......@@ -641,8 +800,8 @@ const confirmDrawer = info => {
// console.log('抽屉info', info)
// info 为抽屉返回的值
if (drawerInfo.value.type == 'arrowRight' && drawerInfo.value.drawerType) {
// console.log('drawerInfo.value', drawerInfo.value)
if (drawerInfo.value.domType == 'arrowRight' && drawerInfo.value.drawerType) {
console.log('drawerInfo.value', drawerInfo.value)
let newObj = info[drawerInfo.value.key]
//要判断drawerType
......@@ -714,11 +873,14 @@ const confirmDrawer = info => {
default:
break
}
console.log('form.value', form.value)
console.log(' saveKey.value', saveKey.value)
// 手动触发表单验证
nextTick(() => {
// 根据不同的drawerType确定要验证的字段key
const validateField = drawerInfo.value.key
customerRef.value.clearValidate(validateField)
customerFormRef.value.clearValidate(validateField)
})
}
......@@ -727,26 +889,33 @@ const confirmDrawer = info => {
const handleSelectChange = child => {
switch (child.key) {
// case 'smokingStatus':
// // 选择吸烟,展示吸烟数量
// if (form.value[child.key] == '1') {
// resetShow('smokeQuantity', true)
// } else {
// resetShow('smokeQuantity', false)
// }
// break
// case 'idType':
// // 选择吸烟,展示吸烟数量
// if (form.value[child.key] == 'idCard') {
// resetShow('idCardAddress', true)
// } else {
// resetShow('idCardAddress', false)
// }
// break
case 'documentType':
break
case 'isRetirement':
if (form.value[child.key] == '1') {
resetShow('retirementAge', true)
} else {
resetShow('retirementAge', false)
}
break
case 'policyholderRel':
processedCustomerData.value.forEach(section => {
if (form.value[child.key] == 'MYSELF') {
if (section.key == 'policyholderRel') {
section.showMoudle = true
} else {
section.showMoudle = false
}
} else {
section.showMoudle = true
}
})
break
default:
break
}
}
// 改变编辑状态
const handleEditStatus = () => {
editStatus.value = !editStatus.value
......@@ -757,8 +926,12 @@ const handleEditStatus = () => {
for (const field of section.data) {
if (editStatus.value) {
field.disabled = true
} else if (field.key !== 'age') {
field.disabled = false
} else {
if (field.key == 'age' || field.key == 'bmi') {
field.disabled = true
} else {
field.disabled = false
}
}
}
}
......@@ -780,13 +953,16 @@ const setFormValue = (obj, formData, exportValue) => {
// if (section.key == 'personInfo') {
// section.data.push()
// }
if (
section.key == 'apiTaxationDtoList' &&
obj.apiTaxationDtoList &&
obj.apiTaxationDtoList.length > 0
) {
section.data = JSON.parse(JSON.stringify(obj.apiTaxationDtoList))
}
if (section.data) {
for (const field of section.data) {
// if (obj.smokeQuantity && field.key == 'smokeQuantity') {
// field.show = true
// }
//证件类型是身份证,身份证地址就显示否则不显示
if (field.key == 'idCardAddress' && obj.idType == 'idCard') {
if (obj.isRetirement && obj.isRetirement == '1' && field.key == 'retirementAge') {
field.show = true
}
//要判断drawerType,因为抽屉要回显数据
......@@ -848,12 +1024,12 @@ const setFormValue = (obj, formData, exportValue) => {
break
case 'country':
form.value[field.key] = obj.countryName
form.value[field.key] = obj.nationality
saveKey.value[field.key] = {
country: obj.country || '',
countryCode: obj.country || '',
countryName: obj.countryName || '',
name: obj.countryName || '',
// country: obj.country || '',
// countryCode: obj.country || '',
// countryName: obj.countryName || '',
name: obj.nationality || '',
objType: field.drawerType
}
break
......@@ -890,11 +1066,11 @@ const setFormValue = (obj, formData, exportValue) => {
phoneQuickList.value = removeDuplicates(tempPhoneList, 'phoneString')
addressQuickList.value = removeDuplicates(tempAddressList, 'addressString')
if (!exportValue) {
// 保存一份就得表单数据便于做撤销操作
oldObjInfo.value = JSON.parse(JSON.stringify(form.value))
}
processedCustomerData.value = oldCustomerData.value = processedData
// if (!exportValue) {
// // 保存一份就得表单数据便于做撤销操作
// oldObjInfo.value = JSON.parse(JSON.stringify(form.value))
// }
processedCustomerData.value = processedData
}
// 数组去重
function removeDuplicates(arr, key) {
......@@ -923,105 +1099,16 @@ const getInvalidFields = fields => {
}
return errors
}
// 表单提交
const submitForm = () => {
//提交得时候要处理税务国家得数据。表格得值收集在processedCustomerData中,所以需要从processedCustomerData中取值
let submitObj = { ...form.value }
let addressList = []
submitObj['birthday'] = proxy.formatToDate(submitObj['birthday'])
proxy.$refs['customerRef'].validate((valid, fields) => {
if (valid) {
//处理表单数据
for (const key1 in form.value) {
for (const key2 in saveKey.value) {
//要判断drawerType
switch (saveKey.value[key2].objType) {
case 'phone':
if (key1 == key2) {
for (const key3 in saveKey.value[key2]) {
submitObj[key3] = saveKey.value[key2][key3]
}
}
break
case 'address':
if (key1 == key2) {
addressList.push(saveKey.value[key2])
}
break
case 'country':
if (key1 == key2) {
submitObj['country'] = saveKey.value[key2]['countryCode']
submitObj['countryName'] = saveKey.value[key2]['name']
}
break
default:
break
}
}
}
submitObj['birthday'] = proxy.formatToDate(submitObj['birthday'])
submitObj['addressList'] = addressList
// 删除多余字段
deleteKeyList.value.forEach(item => {
delete submitObj[item]
})
if (props.customerBizId) {
editCustomer(submitObj).then(res => {
if (res.code == 200) {
handleEditStatus()
proxy.$message.success('客户修改成功')
emit('handleSuccess', {
tab: 'customer',
customerBizId: props.customerBizId,
type: 'edit'
})
}
})
} else {
addFna({ remark: '' }).then(response => {
if (response.code == 200) {
// res.data.fnaBizId 写到这了,先增加fna,再增加客户 看一下流程是否报错
addCustomer(submitObj).then(res => {
if (res.code == 200) {
proxy.$message.success('客户新增成功')
emit('handleSuccess', {
tab: 'customer',
customerBizId: res.data.customerBizId,
fnaBizId: response.data.fnaBizId,
type: 'add'
})
}
})
}
})
}
// emit('submitForm', submitObj)
errorFields.value = [] // 清空错误信息
} else {
// 获取校验失败的字段信息
errorFields.value = getInvalidFields(fields)
if (errorFields.value.length > 0) {
proxy.$message.error(errorFields.value[0].message)
}
}
})
}
const resetForm = () => {
proxy.$modal
.confirm('是否确认撤销所作操作?')
.then(function () {
if (props.customerBizId) {
form.value = { ...oldObjInfo.value }
editStatus.value = true
} else {
// resetShow('smokeQuantity', false)
proxy.$refs['customerRef'].resetFields()
}
processedCustomerData.value = JSON.parse(JSON.stringify(oldCustomerData.value))
customerFormRef.value.resetFields()
console.log('切换之前的form', oldObjInfo.value)
console.log('切换之前的dom', oldCustomerData.value)
// processedCustomerData.value = JSON.parse(JSON.stringify(oldCustomerData.value))
setFormValue(oldObjInfo.value, oldCustomerData.value)
})
.catch(() => {})
......@@ -1035,19 +1122,211 @@ function getCustomerInfo(customerBizId, formData) {
}
})
}
// 根据联动重置表单项的显示与否
const resetShow = (key, status) => {
for (const section of processedCustomerData.value) {
if (section.data) {
for (const field of section.data) {
if (field.key == key) {
// 获取字典数据
field.show = status
}
}
}
}
}
// 方法1:使用 Promise 包装 validateField
const debugValidation = async () => {
const fieldNames = Object.keys(rules.value)
console.log('开始验证以下字段:', fieldNames)
// 1. 为每个字段创建验证Promise,并直接返回该字段的验证结果
const validationPromises = fieldNames.map(field => {
return new Promise(resolve => {
if (!customerFormRef.value) {
console.error(`[${field}] 表单实例不存在`)
resolve({ field, error: null, valid: false }) // 标记为无效
return
}
customerFormRef.value.validateField(field, errorMessage => {
console.log(`[${field}] 验证结果:`, errorMessage ? `失败 - ${errorMessage}` : '通过')
// 关键修改:只有当 errorMessage 存在(有错误)时,才携带错误信息
if (errorMessage) {
resolve({ field, error: errorMessage, valid: false })
} else {
resolve({ field, error: null, valid: true })
}
})
})
})
// 2. 等待所有验证完成
const results = await Promise.all(validationPromises)
// 3. 筛选出所有验证失败的字段
const errors = results
.filter(result => !result.valid && result.error)
.map(result => ({ field: result.field, message: result.error }))
console.log('最终收集到的错误列表:', errors)
return errors
}
// 滚动到第一个错误字段
const scrollToFirstError = () => {
const firstError = document.querySelector('.el-form-item__error')
if (firstError) {
firstError.scrollIntoView({ behavior: 'smooth', block: 'center' })
}
}
const handleFormValues = () => {
return new Promise(async resolve => {
let submitObj = { ...form.value }
let addressList = []
submitObj['birthday'] = proxy.formatToDate(submitObj['birthday'])
customerFormRef.value.validate((valid, fields) => {
if (valid) {
errorFields.value = [] // 清空错误信息
//处理表单数据
for (const key1 in form.value) {
for (const key2 in saveKey.value) {
//要判断drawerType
switch (saveKey.value[key2].objType) {
case 'phone':
if (key1 == key2) {
for (const key3 in saveKey.value[key2]) {
submitObj[key3] = saveKey.value[key2][key3]
}
}
break
case 'address':
if (key1 == key2) {
addressList.push(saveKey.value[key2])
}
break
case 'country':
if (key1 == key2) {
submitObj['country'] = saveKey.value[key2]['countryCode']
submitObj['countryName'] = saveKey.value[key2]['name']
}
break
default:
break
}
}
}
submitObj['birthday'] = proxy.formatToDate(submitObj['birthday'])
submitObj['addressList'] = addressList
processedCustomerData.value.forEach(item => {
if (item.key == 'apiTaxationDtoList' && item.data.length > 0) {
submitObj['apiTaxationDtoList'] = item.data.filter(item => {
return item.taxCountry && item.taxCountry.trim() && item.taxId && item.taxId.trim()
})
}
})
// 删除多余字段
deleteKeyList.value.forEach(item => {
delete submitObj[item]
})
if (errorFields.value.length > 0) {
proxy.$message.error(errorFields.value[0].message)
return undefined
}
if (props.customerBizId && props.activeName == 'customer') {
editCustomer(submitObj).then(res => {
if (res.code == 200) {
handleEditStatus()
proxy.$message.success('客户修改成功')
emit('handleSuccess', {
tab: 'customer',
customerBizId: props.customerBizId,
type: 'edit'
})
}
})
} else if (!props.customerBizId && props.activeName == 'customer') {
addFna({ remark: '' }).then(response => {
if (response.code == 200) {
addCustomer(submitObj).then(res => {
if (res.code == 200) {
proxy.$message.success('客户新增成功')
emit('handleSuccess', {
tab: 'customer',
customerBizId: res.data.customerBizId,
fnaBizId: response.data.fnaBizId,
type: 'add'
})
}
})
}
})
}
resolve(errorFields.value.length == 0 ? submitObj : null)
} else {
errorFields.value = getInvalidFields(fields)
if (errorFields.value.length > 0) {
proxy.$message.error(errorFields.value[0].message)
}
resolve(undefined)
}
})
})
}
const anchorList = computed(() => {
let data = []
for (const section of processedCustomerData.value) {
if (section.showMoudle) {
data.push({ title: section.anchorKey, name: section.fatherTitle })
}
}
return data
})
watch(
() => props.activeName,
newVal => {
if (newVal === 'customer') {
customerRightRef.value = null
editStatus.value = false
customerRightRef.value = null
if (newVal === 'customer' || newVal === 'policyholder' || newVal === 'insurantInfo') {
processFormData()
// 因为客户资料里的编辑状态是单独控制的
if (props.tabSource == 'customer' && props.customerBizId) {
editStatus.value = true
} else if (props.tabSource == 'customer' && !props.customerBizId) {
editStatus.value = false
}
}
}
)
watch(
() => props.fatherEditStatus,
newVal => {
editStatus.value = newVal
}
)
// 暴露给父组件
defineExpose({
handleFormValues,
handleEditStatus
})
</script>
<style lang="scss" scoped>
.dialogBox {
margin: 10px;
width: 100%;
height: 600px;
overflow-y: scroll;
}
.customerContainer {
display: flex;
/* display: flex; */
height: 100%;
box-sizing: border-box;
position: relative;
......@@ -1169,4 +1448,11 @@ watch(
margin-bottom: 0px;
}
}
/* 响应式调整 */
/* @media (max-width: 768px) {
.editBtn {
right: 5.5%;
top: 16%;
}
} */
</style>
<template>
<div>
<div v-if="processedFanFormData.length > 0">
<el-row>
<div v-if="processedFanFormData.length > 0">
<div ref="fanContainerRef">
<!-- <el-row>
<el-col :span="24">
<div class="topBtn">
<el-button
......@@ -13,428 +13,305 @@
>
</div>
</el-col>
</el-row>
<el-form ref="fanFormRef" :model="form" :rules="rules">
<div v-for="father in processedFanFormData">
<div>
<div class="fatherLable">
{{ father.fatherTitle }}
<div class="openCon" v-if="father.openIcon" @click="changeOpenStatus(father)">
<el-icon v-if="!father.isOpen"><Hide /></el-icon>
<el-icon v-else><View /></el-icon>
</div>
</div>
<div class="subTitle" v-if="father.subTitle && father.isOpen">
{{ father.subTitle }}
</div>
</div>
<el-row v-if="father.child == 'no'" :gutter="20">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItem" v-if="child.show">
<div>
<el-form-item
:label="child.label"
:prop="father.key + '.' + child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="child.disabled"
:style="{ width: child.inputWidth ? child.inputWidth : '100%' }"
/>
<el-input
v-if="child.inputType === 'Input'"
:type="child.inputType"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="child.disabled"
:style="{ width: child.inputWidth ? child.inputWidth : '100%' }"
class="formInput"
/>
<el-select
v-if="child.domType === 'Select'"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(father, child)"
:disabled="child.disabled"
clearable
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[father.key][child.key]"
type="date"
:placeholder="child.placeholder"
:disabled="child.disabled"
/>
<el-checkbox-group
v-if="child.domType === 'Checkbox'"
v-model="form[father.key][child.key]"
:disabled="child.disabled"
@change="changeCheck(father, child)"
>
<el-checkbox
v-for="item in child.options"
:key="item.value"
:label="item.value"
>
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
<el-select
v-model="form[father.key][child.key]"
v-if="child.domType === 'SearchSelect'"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索"
:remote-method="query => searchSelectList(query, child.key)"
:loading="searchLoadingStates[child.key]"
:disabled="child.disabled"
clearable
>
<el-option
v-for="item in searchOptions[child.key] || []"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</div>
</el-col>
</template>
</el-row>
<el-row v-if="father.showTable && father.isOpen">
<el-table :data="father.data" border>
<template v-if="father.key == 'familyMembers'">
<el-table-column label="亲属" prop="childTitle" width="100px" align="center">
<template #default="scope">
{{
scope.row.type == '4'
? `${scope.row.childTitle}-${scope.$index - 2}`
: scope.row.childTitle
}}
</template>
</el-table-column>
<el-table-column label="年龄" prop="age" align="center">
<template #default="scope">
<el-input
v-model="scope.row.age"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="是否需要供养" prop="needProvide" align="center">
<template #default="scope">
<el-select
v-model="scope.row.needProvide"
placeholder="请选择"
:disabled="editStatus"
clearable
</el-row> -->
<CommonForm
:anchorList="anchorList"
:affixOffset="250"
:anchorOffset="10"
:scrollContainerSelector="anchorContainer"
:scrollOffset="10"
:domIndex="tabIndex"
:activeName="activeName"
v-if="fanContainerRef"
>
<template #form-right>
<el-form :model="form" :rules="rules" ref="fanFormRef">
<el-row v-for="(father, fIndex) in processedFanFormData" :id="father.anchorKey">
<div class="formBox">
<CardOne :title="father.fatherTitle" v-if="father.showMoudle">
<template #mainTitCustom>
<div
class="dependNum"
v-if="father.key == 'dependantList' && father.data.length > 0"
>
<el-option
v-for="item in scope.row.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column
width="60px"
v-if="father.data && father.data.some(item => item.type === '4')"
align="center"
label="操作"
>
<template #default="scope">
<el-icon
v-if="scope.row.type == '4'"
@click="deleteChildren(father, scope.$index)"
class="deleteIcon"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
<template
v-if="
father.key == 'existingSecurityOwner' || father.key == 'existingSecurityInsured'
"
>
<el-table-column label="保险公司" prop="insurer" align="center">
<template #default="scope">
<el-input
size="default"
placeholder="请输入"
v-model="scope.row.insurer"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="保障类型" prop="insuranceType" align="center">
<template #default="scope">
<el-input
v-model="scope.row.insuranceType"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="保额" prop="sumInsured" align="center">
<template #default="scope">
<el-input
v-model="scope.row.sumInsured"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
受供养人数目:{{ father.data.length }}
</div>
</template>
</el-table-column>
<template #content>
<el-row :gutter="20" v-if="!father.showTable" class="selfStyle">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItem" v-if="child.show">
<div>
<el-form-item
:label="
child.key === 'monthlyIncome' && child.domType === 'Input'
? ''
: child.label
"
:prop="child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<!-- 自定义 label 插槽 -->
<template
v-if="
(child.key === 'monthlyIncome' || child.key === 'liquidAssets') &&
child.domType === 'Input'
"
#label
>
<div class="custom-label">
<span>{{ child.label }}</span>
<el-tooltip :content="child.tooltip" placement="top">
<el-icon><QuestionFilled /></el-icon>
</el-tooltip>
</div>
</template>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="child.value"
:placeholder="child.placeholder"
maxlength="30"
:disabled="editStatus"
>
<template #append v-if="child.unit">
<span>{{ child.unit }}</span>
</template>
</el-input>
<el-select
v-if="child.domType === 'Select'"
v-model="child.value"
:placeholder="child.placeholder"
@change="handleSelectChange(child)"
:disabled="editStatus"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="child.value"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:placeholder="child.placeholder"
:disabled="editStatus"
:disabled-date="time => disabledDate(time, child)"
:default-value="defaultDisplayDate"
@change="handleDateChange(child)"
/>
<el-table-column label="币种" prop="currency" align="center">
<template #default="scope">
<el-select
v-model="scope.row.currency"
placeholder="请选择"
:disabled="editStatus"
clearable
>
<el-option
v-for="item in scope.row.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="保单签发日期" prop="policyIssueDate" align="center">
<template #default="scope">
<el-date-picker
style="width: 100%"
v-model="scope.row.policyIssueDate"
type="date"
placeholder="请输入"
:disabled="editStatus"
:disabled-date="disabledDate"
/>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon @click="deleteChildren(father, scope.$index)" class="deleteIcon"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
<template v-if="father.key == 'investment'">
<el-table-column label="地址" prop="address" align="center">
<template #default="scope">
<el-input
size="default"
placeholder="请输入"
v-model="scope.row.address"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="市值" prop="marketValue" align="center">
<template #default="scope">
<el-input
v-model="scope.row.marketValue"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="币种" prop="currency" align="center">
<template #default="scope">
<el-select
v-model="scope.row.currency"
placeholder="请选择"
:disabled="editStatus"
clearable
>
<el-option
v-for="item in scope.row.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon @click="deleteChildren(father, scope.$index)" class="deleteIcon"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
<el-input
v-if="child.domType === 'arrowRight'"
v-model="child.value"
:placeholder="child.placeholder"
@click="handleFoucs(child)"
:suffix-icon="ArrowRight"
readonly
:disabled="editStatus"
>
</el-input>
<el-checkbox-group
v-if="child.domType === 'Checkbox'"
v-model="child.value"
:disabled="editStatus"
>
<template class="customCheckBox">
<el-checkbox
v-for="item in child.options"
:key="item.value"
:label="item.value"
>
{{ item.label }}
</el-checkbox>
<template v-if="father.key == 'primaryResidence'">
<el-table-column label="自住用途之房地产地址" prop="address" align="center">
<template #default="scope">
<el-input
size="default"
placeholder="请输入"
v-model="scope.row.address"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="自住用途之房地产市值" prop="marketValue" align="center">
<template #default="scope">
<el-input
v-model="scope.row.marketValue"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="币种" prop="currency" align="center">
<template #default="scope">
<el-select
v-model="scope.row.currency"
placeholder="请选择"
:disabled="editStatus"
clearable
>
<el-option
v-for="item in scope.row.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon @click="deleteChildren(father, scope.$index)" class="deleteIcon"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
<template v-if="father.key == 'taxList'">
<el-table-column label="税务国家" prop="taxCountry" align="center">
<template #default="scope">
<el-input
size="default"
placeholder="请输入"
v-model="scope.row.taxCountry"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="税务编号" prop="taxNumber" align="center">
<template #default="scope">
<el-input
v-model="scope.row.taxNumber"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon @click="deleteChildren(father, scope.$index)" class="deleteIcon"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
</el-table>
<el-col
:span="24"
v-if="father.addChildren"
style="display: flex; justify-content: center"
>
<el-button
:disabled="editStatus"
style="margin-top: 10px"
type="primary"
icon="Plus"
@click="addChildren(father)"
>{{ father.addChildrenTxt }}</el-button
>
</el-col>
</el-row>
</div>
<el-input
style="width: 250px"
v-if="
child.key === 'liquidAssetType' &&
child.value.filter(item => item == 'G').length > 0
"
v-model="child.otherLiquidAsset"
placeholder="请输入说明"
:disabled="editStatus"
/>
</template>
</el-checkbox-group>
</el-form-item>
</div>
</el-col>
</template>
</el-row>
<el-row v-if="father.showTable">
<el-col :span="24" v-if="father.addChildren">
<el-button
:disabled="editStatus"
type="primary"
icon="Plus"
size="small"
style="margin-bottom: 10px"
@click="addChildren(father)"
>{{ father.addChildrenTxt }}</el-button
>
</el-col>
<el-table :data="father.data" border v-if="father.data.length > 0">
<!-- 动态渲染列 -->
<el-table-column
v-for="column in father.columns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
align="center"
>
<template #default="scope">
<!-- 远程搜索选择框 -->
<el-select
v-if="column.type === 'remoteSelect'"
v-model="scope.row[column.prop]"
filterable
remote
reserve-keyword
:placeholder="column.placeholder"
:remote-method="query => searchSelectList(query, column.searchType)"
:loading="searchLoadingStates[column.searchType]"
:disabled="editStatus"
@change="handleRemoteSelectChange(scope.row, column)"
>
<el-option
v-for="item in searchOptions[column.searchType] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- 普通选择框 -->
<el-select
v-else-if="column.type === 'select'"
v-model="scope.row[column.prop]"
:placeholder="column.placeholder"
:disabled="editStatus"
>
<el-option
v-for="item in fetchDictData(column.dictType)"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- 日期选择器 -->
<el-date-picker
v-else-if="column.type === 'datePicker'"
v-model="scope.row[column.prop]"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:placeholder="column.placeholder"
:disabled="editStatus"
style="width: 100%"
/>
<!-- 数字输入框 -->
<el-input
v-else-if="column.type === 'inputNumber'"
v-model.number="scope.row[column.prop]"
:placeholder="column.placeholder"
:disabled="editStatus"
type="number"
>
<template v-if="column.unit" #append>
<span>{{ column.unit }}</span>
</template>
</el-input>
<el-row>
<el-col>
<div class="tabButton">
<el-button
type="primary"
icon="RefreshRight"
size="large"
@click="submitForm('temp')"
:disabled="editStatus"
>暂存</el-button
>
<el-button
type="success"
icon="Check"
@click="submitForm('save')"
size="large"
:disabled="editStatus"
>立即预约</el-button
>
</div>
</el-col>
</el-row>
</el-form>
<!-- 普通输入框(默认) -->
<el-input
v-else
v-model="scope.row[column.prop]"
:placeholder="column.placeholder"
:disabled="editStatus"
/>
</template>
</el-table-column>
<!-- 操作列(固定) -->
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon
class="deleteIcon"
@click="deleteChildren(father, scope.$index)"
><Delete
/></el-icon>
</template>
</el-table-column>
</el-table>
</el-row>
</template>
</CardOne>
</div>
</el-row>
<el-row>
<el-col>
<div class="tabButton">
<el-button
type="primary"
icon="RefreshRight"
size="large"
@click="submitForm('temp')"
:disabled="editStatus"
>暂存</el-button
>
<el-button
type="success"
icon="Check"
@click="submitForm('save')"
size="large"
:disabled="editStatus"
>立即预约</el-button
>
</div>
</el-col>
</el-row>
</el-form>
</template>
</CommonForm>
</div>
<div v-else class="domEmpty" v-loading="loading"></div>
<!-- <div v-else class="domEmpty" v-loading="loading"></div> -->
</div>
</template>
<script setup name="fanForm">
import CommonForm from '@/views/components/commonForm'
import CardOne from '@/components/formCard/cardOne'
import { processUserName } from '@/utils/common'
import useDictStore from '@/store/modules/dict'
import fanFormDomData from '@/formJson/fnaForm'
import { watch, nextTick } from 'vue'
import { addfanForm, getfanFormDetail, editFanForm, getCustomerList } from '@/api/sign/fna'
import { listTenantUser } from '@/api/common'
import { getUserSaleExpandList, getAllTeam, getInsuranceCompany } from '@/api/common'
import useUserStore from '@/store/modules/user'
const userStore = useUserStore()
const dictStore = useDictStore() //获取字典数据
const props = defineProps({
customerInfo: { type: Object, default: () => {} }, //客户详情
activeName: { type: String, default: '' }, //tab名称
fearthStatus: { type: String, default: '' }, //父组件状态,新增、修改
fnaFormBizId: { type: String, default: '' }, //提交状态,新增、修改
customerBizId: { type: String, default: '' }, //提交状态,新增、修改
dictTypeLists: { type: Array, default: () => [] } //多个字典值数据
dictTypeLists: { type: Array, default: () => [] }, //多个字典值数据
anchorContainer: { type: String, default: '' }, //锚点滚动容器
tabIndex: { type: [String, Number], default: '' } //tab索引
})
const emit = defineEmits(['handleSuccess'])
const { proxy } = getCurrentInstance()
// const { sys_no_yes } = proxy.useDict('sys_no_yes')
const fanContainerRef = ref(null)
const loading = ref(false)
const fanFormRef = ref(null)
const errorFields = ref([]) // 存储校验失败的字段信息
......@@ -465,61 +342,70 @@ const {
tempFanFormValue,
tempFanFormData
} = toRefs(data)
const changeCheck = (father, child) => {
if (child.key == 'liquidAssetType') {
resetShow('otherLiquidAsset', form.value[father.key][child.key].includes('G'))
const handleRemoteSelectChange = (row, column) => {
console.log(row, column)
// 通过保险公司查保险种类 row中收集了insurer的值
if (column.prop == 'insurer') {
}
}
const changeOpenStatus = father => {
const processedData = JSON.parse(JSON.stringify(processedFanFormData.value))
for (const section of processedData) {
if (
father.key == 'familyMembers' &&
section.key == father.key &&
section.moudleType == 'family'
) {
section.isOpen = !father.isOpen
}
if (section.moudleType == 'finance' && father.key !== 'familyMembers') {
section.isOpen = !father.isOpen
}
}
processedFanFormData.value = processedData
console.log('processedFanFormData.value', processedFanFormData.value)
}
const disabledDate = time => {
return time.getTime() > Date.now()
}
// 搜索方法
const searchSelectList = async (query, fieldKey) => {
// 设置该字段的加载状态
searchLoadingStates.value[fieldKey] = true
let queryString = query.trim()
try {
// 根据不同的字段key调用不同的API
if (fieldKey === 'accountName') {
const params = {
tenantBizId: userStore.projectInfo.tenantBizId,
realName: query.trim(),
if (fieldKey === 'brokerName') {
const params5 = {
pageNo: 1,
pageSize: 10
pageSize: 10,
queryContent: queryString
}
const response = await listTenantUser(params)
if (response.code == 200) {
let result = processUserName(response.data.records)
result = result.map(item => {
const response5 = await getUserSaleExpandList(params5)
if (response5.code == 200) {
response5.data.records = response5.data.records.map(item => {
return {
value: item.userBizId,
label: item.showName
...item,
label: item.realName,
value: item.userSaleBizId
}
})
searchOptions.value[fieldKey] = result
searchOptions.value[fieldKey] = response5.data.records
}
} else if (fieldKey === 'brokerTeam') {
const params8 = {
pageNo: 1,
pageSize: 10,
teamName: queryString
}
const response8 = await getAllTeam(params8)
if (response8.code == 200) {
response8.data.records = response8.data.records.map(item => {
return {
...item,
label: item.teamName,
value: item.teamBizId
}
})
searchOptions.value[fieldKey] = response8.data.records
}
} else if (fieldKey === 'insurer') {
const params9 = {
pageNo: 1,
pageSize: 10,
queryContent: queryString
}
const response9 = await getInsuranceCompany(params9)
if (response9.code == 200) {
response9.data.records = response9.data.records.map(item => {
return {
...item,
label: item.fullName,
value: item.insuranceCompanyBizId
}
})
searchOptions.value[fieldKey] = response9.data.records
}
}
// 可以添加其他字段的处理,可以放其他的字段得请求,目前只有accountName,以后有了其他的在填充
else if (fieldKey === 'otherField') {
console.log('otherField')
}
} catch (error) {
console.error(`${fieldKey} 搜索失败`, error)
......@@ -529,6 +415,10 @@ const searchSelectList = async (query, fieldKey) => {
}
}
const disabledDate = time => {
return time.getTime() > Date.now()
}
// 获取字典数据
const fetchDictData = dictType => {
let options = []
......@@ -569,72 +459,37 @@ const processFormData = async () => {
form.value[section.key] = {}
}
if (section.data) {
for (const formKey in form.value) {
if (section.key == formKey) {
if (section.dataLength) {
for (let i = 1; i < section.dataLength; i++) {
section.data.push(JSON.parse(JSON.stringify(section.data[0])))
form.value[formKey].push(JSON.parse(JSON.stringify(section.data[0])))
}
}
for (const field of section.data) {
// 为下拉搜索框加options
if (field.domType == 'SearchSelect') {
if (field.key == 'accountName') {
searchOptions.value[field.key] = dictStore.tenantUserList
}
}
if (section.key == formKey && field.children) {
for (const child of field.children) {
if (child.dictType) {
child.options = fetchDictData(child.dictType)
if (child.dictType == 'sys_no_yes') {
noYesList.value = child.options
}
}
if (props.fnaFormBizId) {
child.disabled = true
} else {
child.disabled = false
}
}
}
if (field.dictType) {
// 获取字典数据
field.options = fetchDictData(field.dictType)
if (field.dictType == 'sys_no_yes') {
noYesList.value = field.options
}
}
//
/*
1.没有嵌套子级的也就是没有children的数据加rules,根据data中的required字段判断是否必填
2.有嵌套子级的也就是有children的数据,根据children中的required字段判断是否必填,现在没这个需求,所以先注释
*/
if (field.required && section.child == 'no') {
rules.value[section.key][field.key] = [
{ required: true, message: `${field.label}不能为空`, trigger: 'blur' }
]
}
if (props.fnaFormBizId) {
field.disabled = true
} else {
if (field.key == 'customerName' && section.key == 'personalData') {
form.value['personalData'][field.key] = props.customerInfo.firstNamePinyin
}
field.disabled = false
}
}
if (section.child == 'yes') {
form.value[formKey] = section.data //便于表单收集值
for (const field of section.data) {
// 为下拉搜索框加options
// if (field.domType == 'SearchSelect') {
// if (field.key == 'accountName') {
// searchOptions.value[field.key] = dictStore.tenantUserList
// }
// }
if (field.dictType) {
// 获取字典数据
field.options = fetchDictData(field.dictType)
if (field.dictType == 'sys_no_yes') {
noYesList.value = field.options
}
}
if (field.required) {
rules.value[field.key] = [
{ required: true, message: `${field.label}不能为空`, trigger: 'blur' }
]
}
if (props.fnaFormBizId) {
field.disabled = true
} else {
field.disabled = false
}
}
}
}
if (props.fnaFormBizId) {
getFanformInfo(props.fnaFormBizId, processedData)
editStatus.value = true
// getFanformInfo(props.fnaFormBizId, processedData)
// editStatus.value = true
} else {
// tab切走在切回来时,表单会重置,所以这里需要把表单的值赋回去
if (Object.keys(tempFanFormValue.value).length > 0) {
......@@ -649,67 +504,55 @@ const processFormData = async () => {
}
editStatus.value = false
loading.value = false
console.log('processedFanFormData.value', processedFanFormData.value)
}
processedFanFormData.value = oldFanFormData.value = processedData
}
// 添加表单子级dom
const addChildren = father => {
const processedData = JSON.parse(JSON.stringify(processedFanFormData.value))
let obj = {
type: '4',
childTitle: '儿女',
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
delete: true, //是否显示删除按钮
age: '',
needProvide: '',
options: noYesList.value
let obj1 = {
brokerName: '',
brokerGender: '',
brokerNumber: '',
brokerTeam: '',
brokerRatio: '',
remark: ''
}
let obj2 = {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
policyholderRel: '',
dependantAge: ''
}
let obj3 = {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
insurer: '',
insuranceType: '',
sumInsured: '',
policyIssueDate: '',
currency: '',
options: fetchDictData('bx_currency_type')
policyIssueDate: ''
}
let obj3 = {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
let obj4 = {
propertyType: '',
address: '',
currency: '',
marketValue: '',
options: fetchDictData('bx_currency_type')
}
let obj4 = {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
taxCountry: '',
taxNumber: ''
currency: ''
}
for (const section of processedData) {
if (father.key == 'familyMembers' && section.key == father.key) {
section.data.push(obj)
}
if (father.key == 'existingSecurityOwner' && section.key == father.key) {
section.data.push(obj2)
if (father.key == 'brokerList' && section.key == father.key) {
section.data.push(obj1)
}
if (father.key == 'existingSecurityInsured' && section.key == father.key) {
if (father.key == 'dependantList' && section.key == father.key) {
section.data.push(obj2)
}
if (father.key == 'investment' && section.key == father.key) {
if (father.key == 'existingSecurityOwner' && section.key == father.key) {
section.data.push(obj3)
}
if (father.key == 'primaryResidence' && section.key == father.key) {
section.data.push(obj3)
}
if (father.key == 'taxList' && section.key == father.key) {
section.data.push(obj4)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].push(obj)
processedFanFormData.value = processedData
}
const deleteChildren = (father, childIndex) => {
......@@ -1116,6 +959,15 @@ function getFanformInfo(fnaFormBizId, formData) {
}
})
}
const anchorList = computed(() => {
let data = []
for (const section of processedFanFormData.value) {
if (section.showMoudle) {
data.push({ title: section.anchorKey, name: section.fatherTitle })
}
}
return data
})
watch(fanFormRef, newVal => {
if (newVal) {
for (const key in rules.value) {
......@@ -1128,20 +980,30 @@ watch(fanFormRef, newVal => {
watch(
() => props.activeName,
newVal => {
fanContainerRef.value = null
tempFanFormValue.value = JSON.parse(JSON.stringify(form.value))
tempFanFormData.value = JSON.parse(JSON.stringify(processedFanFormData.value))
if (newVal === 'fnaform') {
openList.value = false
setTimeout(() => {
processFormData()
}, 500)
processFormData()
}
}
)
</script>
<style lang="scss" scoped>
.dependNum {
font-size: 14px;
font-weight: none;
margin-left: 10px;
}
.customCheckBox {
display: flex;
flex-direction: column;
width: 100%;
}
.domEmpty {
width: 100%;
height: 100%;
display: flex;
align-items: center;
......@@ -1267,6 +1129,12 @@ watch(
.formFna :deep(.el-checkbox) {
margin-right: 10px;
}
.selfStyle :deep(.el-form-item--label-top .el-form-item__label) {
text-align: none !important;
display: flex;
align-items: center;
justify-content: flex-start;
}
/* @media only screen and (min-width: 768px) {
.formInput {
......
......@@ -20,9 +20,20 @@
</div>
</div>
</div>
<div class="tabsBox" ref="tabPaneRef">
<el-tabs v-model="activeName" class="demo-tabs" :before-leave="beforeTabLeave">
<el-tab-pane v-for="tab in tabsList" :key="tab.name" :label="tab.label" :name="tab.name">
<div class="tabsBox">
<el-tabs
v-model="activeName"
class="demo-tabs"
:before-leave="beforeTabLeave"
ref="tabPaneRef"
>
<el-tab-pane
v-for="(tab, tIndex) in tabsList"
:key="tab.name"
:label="tab.label"
:name="tab.name"
>
<!-- 注意tabPaneBox这个类名与子组件的锚点定位相关,不能轻易改动 -->
<div :class="{ tabPaneBox: activeName !== 'appointment' }">
<div v-if="tab.name === 'overview'" class="overviewBox">
<div
......@@ -75,20 +86,22 @@
<Customer
v-if="tab.name === 'customer'"
:activeName="activeName"
:fearthStatus="route.query.type"
:customerBizId="processInfo.customerBizId"
@handleSuccess="handleSuccess"
:tabPaneRef="tabPaneRef"
:tabIndex="tabsList.findIndex(t => t.name === 'customer')"
anchorContainer=".tabPaneBox"
tabSource="customer"
/>
<div v-if="tab.name === 'fnaform'">
<FanForm
:activeName="activeName"
:fearthStatus="route.query.type"
:fnaFormBizId="processInfo.fnaFormBizId"
:customerBizId="processInfo.customerBizId"
:dictTypeLists="dictTypeLists"
:customerInfo="customerInfo"
@handleSuccess="handleSuccess"
:tabIndex="tabsList.findIndex(t => t.name === 'fnaform')"
anchorContainer=".tabPaneBox"
/>
</div>
<div v-if="tab.name === 'appointment'">
......@@ -115,7 +128,17 @@ import AppointmentEdit from '@/views/sign/appointment/appointmentEdit'
import useUserStore from '@/store/modules/user'
import useDictStore from '@/store/modules/dict'
import { addFna, getProcessDetail, updateProcess, getCustomerDetail } from '@/api/sign/fna'
import { listTenantUser, getInsuranceProductList, getAdditionalProductList } from '@/api/common'
import {
listTenantUser,
getInsuranceProductList,
getAdditionalProductList,
getBankList,
getUserSaleExpandList,
secondAdditonalList,
getAllSignList,
getAllTeam,
getInsuranceCompany
} from '@/api/common'
import Customer from './components/customer'
import FanForm from './components/fanForm'
......@@ -206,17 +229,17 @@ const getDictsData = async () => {
pageSize: 10
}
const response2 = await getInsuranceProductList(params2)
if (response2.code == 200) {
response2.data.records = response2.data.records.map(item => {
return {
...item,
label: item.productName,
value: item.productBizId
}
})
dictStore.setInsureProductList(response2.data.records)
}
// const response2 = await getInsuranceProductList(params2)
// if (response2.code == 200) {
// response2.data.records = response2.data.records.map(item => {
// return {
// ...item,
// label: item.productName,
// value: item.productBizId
// }
// })
// dictStore.setInsureProductList(response2.data.records)
// }
const params3 = {
pageNo: 1,
pageSize: 10
......@@ -233,6 +256,100 @@ const getDictsData = async () => {
})
dictStore.setAdditionalProductList(response3.data.records)
}
const params4 = {
pageNo: 1,
pageSize: 99999
}
const response4 = await getBankList(params4)
if (response4.code == 200) {
response4.data.records = response4.data.records.map(item => {
return {
...item,
label: item.bankName,
value: item.bankBizId
}
})
dictStore.setBankList(response4.data.records)
}
const params5 = {
pageNo: 1,
pageSize: 99999
}
const response5 = await getUserSaleExpandList(params5)
if (response5.code == 200) {
response5.data.records = response5.data.records.map(item => {
return {
...item,
label: item.realName,
value: item.userSaleBizId
}
})
dictStore.setUserSaleExpandList(response5.data.records)
}
const params6 = {
pageNo: 1,
pageSize: 99999,
projectBizId: userStore.projectInfo.projectBizId,
tenantBizId: userStore.projectInfo.tenantBizId,
fieldBizId: 'field_olk1qZe81qHHKXbw',
fieldValueBizId: 'field_value_yXzTigvgUdRMFpoR'
}
const response6 = await secondAdditonalList(params6)
if (response6.code == 200) {
response6.data.records = response6.data.records.map(item => {
return {
...item,
label: item.title,
value: item.productLaunchBizId
}
})
dictStore.setProductAdditionalList(response6.data.records)
}
const params7 = {
pageNo: 1,
pageSize: 99999
}
const response7 = await getAllSignList(params7)
if (response7.code == 200) {
response7.data.records = response7.data.records.map(item => {
return {
...item,
label: item.realName,
value: item.userSignBizId
}
})
dictStore.setSignPeopleList(response7.data.records)
}
const params8 = {
pageNo: 1,
pageSize: 99999
}
const response8 = await getAllTeam(params8)
if (response8.code == 200) {
response8.data.records = response8.data.records.map(item => {
return {
...item,
label: item.teamName,
value: item.teamBizId
}
})
dictStore.setAllTeaList(response8.data.records)
}
const params9 = {
pageNo: 1,
pageSize: 99999
}
const response9 = await getInsuranceCompany(params9)
if (response9.code == 200) {
response9.data.records = response9.data.records.map(item => {
return {
...item,
label: item.fullName,
value: item.insuranceCompanyBizId
}
})
dictStore.setAllInsuranceCompanyList(response9.data.records)
}
// 请求每个流程中所涉及到的字典值数据
proxy.useDictLists([
'csf_employment',
......@@ -260,7 +377,8 @@ const getDictsData = async () => {
'wj_question_first_category',
'wj_question_second_category',
'csf_ap_policy_transfer',
'md_bank'
'md_bank',
'csf_property_type'
])
}
......@@ -276,15 +394,7 @@ const processUpdate = (data, status) => {
}
})
}
// 新建流程
// const getAddInfo = () => {
// addFna({ remark: '' }).then(res => {
// if (res.code == 200) {
// // 获取流程详情
// getProcessInfo(res.data.fnaBizId)
// }
// })
// }
// 获取流程详情
function getProcessInfo(fnaBizId, changeTab) {
getProcessDetail(fnaBizId).then(res => {
......@@ -311,7 +421,7 @@ function getProcessInfo(fnaBizId, changeTab) {
// Tab切换前的验证
const beforeTabLeave = (activeTabName, oldTabName) => {
if (processInfo.value.customerBizId) {
getCustomerInfo(processInfo.value.customerBizId)
// getCustomerInfo(processInfo.value.customerBizId)
}
// 如果切换到总览,始终允许
if (activeTabName === 'overview' || activeTabName === 'customer') {
......@@ -515,13 +625,9 @@ getDictsData()
}
}
}
/* .tabPaneBox {
height: calc(100vh - 275px);
overflow-y: auto;
padding-right: 10px;
} */
.tabPaneBox {
height: calc(100vh - 275px);
height: calc(100vh - 280px);
overflow-y: auto;
padding-right: 10px;
position: relative;
......
......@@ -72,6 +72,7 @@
:data="tenantList"
@selection-change="tableSelect"
@sort-change="sortChange"
border
>
<el-table-column type="index" width="50" label="序号" />
<el-table-column label="客户姓名" align="center" prop="customerName" width="100" />
......@@ -130,16 +131,6 @@
</template>
</el-table-column>
</el-table>
<!-- <div style="width: 100%; display: flex; justify-content: flex-end; margin-bottom: 30px">
<pagination
v-show="total >= 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
style="text-align: right"
/>
</div> -->
</template>
</CommonPage>
<!-- 下一步到预约 -->
......
......@@ -44,12 +44,19 @@
<el-row v-if="isEmbed">
<el-col>
<div class="topButtonBox">
<el-button
<!-- <el-button
v-if="idsObj.appointmentBizId && pageSource !== 'policyList'"
type="primary"
icon="Plus"
@click="handleAddExecl"
>上传EXECL</el-button
> -->
<el-button
v-if="pageSource !== 'policyList'"
type="primary"
:icon="Edit"
@click="handleEdit"
>编辑</el-button
>
<el-button
v-if="pageSource !== 'policyList'"
......@@ -86,6 +93,10 @@
:appointmentStatus="appointmentSummeryInfo.status"
@handleSuccessEdit="getAppointmentInfo(idsObj.appointmentBizId)"
ref="appointmentInfoRef"
:tabIndex="tabsList.findIndex(t => t.name === 'appointmentInfo')"
anchorContainer=".appointmentTabPaneBox"
:fatherTabName="tabName"
:editStatus="editStatus"
/>
</div>
<div v-if="tab.name === 'productPlan'">
......@@ -100,10 +111,27 @@
@policyEditSuccess="getPolicyDetail"
:pageSource="pageSource"
:showSubmitBtn="showSubmitBtn"
:tabIndex="tabsList.findIndex(t => t.name === 'productPlan')"
anchorContainer=".appointmentTabPaneBox"
:fatherTabName="tabName"
:editStatus="editStatus"
/>
</div>
<!-- 投保人 -->
<div v-if="tab.name === 'policyholder'">
<PolicyHolderInfo
<!-- :customerBizId="processInfo.customerBizId" @handleSuccess="handleSuccess"-->
<Customer
:activeName="activeName"
:fatherTabName="tabName"
:fatherStatus="editStatus"
:affixOffset="360"
:tabIndex="tabsList.findIndex(t => t.name === 'policyholder')"
anchorContainer=".appointmentTabPaneBox"
tabSource="policyholder"
ref="policyHolderInfoRef"
:fatherEditStatus="editStatus"
/>
<!-- <PolicyHolderInfo
:activeName="activeName"
:formStatus="formStatus"
:customerInfo="customerInfo"
......@@ -115,10 +143,22 @@
:pageSource="pageSource"
:showSubmitBtn="showSubmitBtn"
@policyEditSuccess="getPolicyDetail"
/>
/> -->
</div>
<div v-if="tab.name === 'insurantInfo'">
<InsuredInfo
<!-- :customerBizId="processInfo.customerBizId" @handleSuccess="handleSuccess"-->
<Customer
:activeName="activeName"
:fatherTabName="tabName"
:fatherStatus="editStatus"
:affixOffset="360"
:tabIndex="tabsList.findIndex(t => t.name === 'insurantInfo')"
anchorContainer=".appointmentTabPaneBox"
tabSource="insurantInfo"
ref="insuredInfoRef"
:fatherEditStatus="editStatus"
/>
<!-- <InsuredInfo
:activeName="activeName"
:formStatus="formStatus"
:customerInfo="customerInfo"
......@@ -131,7 +171,7 @@
:pageSource="pageSource"
:showSubmitBtn="showSubmitBtn"
@policyEditSuccess="getPolicyDetail"
/>
/> -->
</div>
<div v-if="tab.name === 'secondHolder'">
<SecondHolderInfo
......@@ -302,6 +342,7 @@ import PolicyTransferInfo from './components/policyTransferInfo.vue'
import FileUpload from './components/fileUpload.vue'
import HealthInfo from './components/healthInfo.vue'
import PolicyInfo from '@/views/sign/underwritingMain/components/policyInfo' //新单跟进里的保单信息
import Customer from '@/views/sign/FnaList/components/customer'
import PolicyFileUpload from '@/views/sign/underwritingMain/components/fileUpload.vue' //新单跟进里的保单附件
import PolicyBrokerInfo from '@/views/sign/underwritingMain/components/brokerInfo.vue' //新单跟进里的保单附件
import PolicyMailing from '@/views/sign/underwritingMain/components/policyMailing.vue' //新单跟进里的保单附件
......@@ -319,8 +360,16 @@ import {
uploadExcel
} from '@/api/sign/appointment'
import { getPolicyfollow, getPolicyInfo, signName } from '@/api/sign/underwritingMain'
import { listTenantUser, getInsuranceProductList, getAdditionalProductList } from '@/api/common'
import { Check } from '@element-plus/icons-vue'
import {
listTenantUser,
getInsuranceProductList,
getAdditionalProductList,
getBankList,
getUserSaleExpandList,
secondAdditonalList,
getAllSignList
} from '@/api/common'
import { Check, Edit } from '@element-plus/icons-vue'
import { ref, nextTick, onUnmounted } from 'vue'
const emit = defineEmits(['handleSuccess'])
......@@ -363,13 +412,14 @@ const processInfo = ref({
createTime: proxy.parseTime(new Date()),
customerName: userStore.name
})
const editStatus = ref(false) //编辑状态
const execlDialog = ref(false)
const isEmbed = ref(false) //是否作为组件插入
const policyNo = ref('') //新单跟进保单号
const currentPolicyholderInfo = ref({}) //存储下投保人信息,受保人模块要用到
const tabsList = ref([
{
label: '约信息',
label: '约信息',
name: 'appointmentInfo',
id: 1,
key: 'appointmentBizId'
......@@ -559,7 +609,7 @@ function getAppointmentInfo(appointmentBizId, changeTab) {
processInfo.value.status = item.label
}
})
getCustomerInfo(res.data.apiAppointmentInfoDto.customerBizId)
// getCustomerInfo(res.data.apiAppointmentInfoDto.customerBizId)
if (!appointmentSummeryInfo.value.apiAppointmentInfoDto.appointmentBizId) {
showStorage.value = true
}
......@@ -653,7 +703,73 @@ const getDictsData = async () => {
})
dictStore.setAdditionalProductList(response3.data.records)
}
const params4 = {
pageNo: 1,
pageSize: 99999
}
const response4 = await getBankList(params4)
if (response4.code == 200) {
response4.data.records = response4.data.records.map(item => {
return {
...item,
label: item.bankName,
value: item.bankBizId
}
})
dictStore.setBankList(response4.data.records)
}
const params5 = {
pageNo: 1,
pageSize: 99999
}
const response5 = await getUserSaleExpandList(params5)
if (response5.code == 200) {
console.log('response5', response5)
response5.data.records = response5.data.records.map(item => {
return {
...item,
label: item.realName,
value: item.userSaleBizId
}
})
dictStore.setUserSaleExpandList(response5.data.records)
}
const params6 = {
pageNo: 1,
pageSize: 99999,
projectBizId: userStore.projectInfo.projectBizId,
tenantBizId: userStore.projectInfo.tenantBizId,
fieldBizId: 'field_olk1qZe81qHHKXbw',
fieldValueBizId: 'field_value_yXzTigvgUdRMFpoR'
}
const response6 = await secondAdditonalList(params6)
if (response6.code == 200) {
response6.data.records = response6.data.records.map(item => {
return {
...item,
label: item.title,
value: item.productLaunchBizId
}
})
dictStore.setProductAdditionalList(response6.data.records)
}
const params7 = {
pageNo: 1,
pageSize: 99999
}
const response7 = await getAllSignList(params7)
if (response7.code == 200) {
response7.data.records = response7.data.records.map(item => {
return {
...item,
label: item.realName,
value: item.userSignBizId
}
})
dictStore.setSignPeopleList(response7.data.records)
}
proxy.useDictLists([
'csf_employment',
'sys_no_yes',
......@@ -686,54 +802,6 @@ const getDictsData = async () => {
}
// Tab切换前的验证
const beforeTabLeave = (activeTabName, oldTabName) => {
// 受保人如果选择了本人,使用投保人得信息填充
// oldTabName == 'policyholder' &&
if (activeTabName == 'insurantInfo') {
currentPolicyholderInfo.value = policyHolderInfoRef.value[0].providePolicyholderInfoData()
} else if (
oldTabName !== 'policyholder' &&
activeTabName == 'insurantInfo' &&
showSubmitBtn.value &&
Object.keys(currentPolicyholderInfo.value).length == 0
) {
currentPolicyholderInfo.value = appointmentSummeryInfo.value.apiPolicyholderInfoDto
}
console.log('预约切换tab', currentPolicyholderInfo.value)
// 健康信息模块,如果投保人选择了本人以及受保人选择了本人,健康信息展示投保人/受保人
let policyHolderResult = policyHolderInfoRef.value[0].handleFormValues()
let insuredResult = insuredInfoRef.value[0].handleFormValues()
console.log('policyHolderResult', policyHolderResult)
console.log('insuredResult', insuredResult)
foldInsurantInfo.value = false
if (activeTabName == 'questionnaires') {
// 投保人和受保人都点击过可以拿到最新填写得表单值
if (
policyHolderResult.customerType &&
policyHolderResult.customerType == 'INDIVIDUAL' &&
insuredResult.policyholderRel &&
insuredResult.policyholderRel == 'MYSELF'
) {
foldInsurantInfo.value = true
} else if (
!policyHolderResult.customerType &&
!insuredResult.policyholderRel &&
showSubmitBtn.value
) {
// 如果投保人和受保人都没有点击过,则使用预约单里得信息
let policyHolderInfo = appointmentSummeryInfo.value.apiPolicyholderInfoDto
let insuredInfo = appointmentSummeryInfo.value.apiInsurantInfoDto
if (
policyHolderInfo.customerType &&
policyHolderInfo.customerType == 'INDIVIDUAL' &&
insuredInfo.policyholderRel &&
insuredInfo.policyholderRel == 'MYSELF'
) {
foldInsurantInfo.value = true
}
}
}
return true
}
......@@ -752,16 +820,17 @@ const isArray = value => {
const isObject = value => {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}
const handleSubmit = type => {
const handleSubmit = async type => {
// 提交得时候要拿到各个步骤得表单数据
if (appointmentInfoRef.value) {
submitAppointmentObj.value.apiAppointmentInfoDto =
appointmentInfoRef.value[0].handleFormValues()
if (!submitAppointmentObj.value.apiAppointmentInfoDto) return
}
if (productPlanRef.value) {
submitAppointmentObj.value.apiProductPlanInfoDto = productPlanRef.value[0].handleSubmitForm()
}
// if (appointmentInfoRef.value) {
// const result = await appointmentInfoRef.value[0].handleFormValues()
// submitAppointmentObj.value.apiAppointmentInfoDto = result
// if (!submitAppointmentObj.value.apiAppointmentInfoDto) return
// }
// if (productPlanRef.value) {
// submitAppointmentObj.value.apiProductPlanInfoDto = productPlanRef.value[0].handleSubmitForm()
// }
if (policyHolderInfoRef.value) {
submitAppointmentObj.value.apiPolicyholderInfoDto =
policyHolderInfoRef.value[0].handleFormValues()
......@@ -769,6 +838,7 @@ const handleSubmit = type => {
if (insuredInfoRef.value) {
submitAppointmentObj.value.apiInsurantInfoDto = insuredInfoRef.value[0].handleFormValues()
}
return
if (secondHolderInfoRef.value) {
submitAppointmentObj.value.apiSecondHolderInfoDto =
secondHolderInfoRef.value[0].handleFormValues()
......@@ -777,7 +847,7 @@ const handleSubmit = type => {
submitAppointmentObj.value.apiBeneficiaryInfoDtoList =
beneficiaryInfoRef.value[0].handleFormValues()
}
// return
return
// 代表新增预约
if (formStatus.value == 'appointmentAdd' && !idsObj.value.appointmentBizId) {
submitAppointmentObj.value.apiAppointmentInfoDto.customerBizId =
......@@ -858,7 +928,6 @@ const handleSubmit = type => {
// 编辑预约单
editAppointmentDetail(submitAppointmentObj.value).then(res => {
if (res.code == 200) {
// getAppointmentInfo(idsObj.value.appointmentBizId)
appointmentInfoRef.value[0].handleEditStatus(true)
productPlanRef.value[0].handleEditStatus(true)
policyHolderInfoRef.value[0].handleEditStatus(true)
......@@ -887,7 +956,9 @@ const handleSubmit = type => {
})
}
}
const handleEdit = () => {
editStatus.value = !editStatus.value
}
//修改预约数据
if (route.query.appointmentNo && route.query.source == 'appointmentList') {
processInfo.value = route.query
......@@ -901,7 +972,7 @@ const pageSource = computed(() => {
})
const tabHight = computed(() => {
if (pageSource.value == 'fnaList') {
return 'calc(100vh - 407px)'
return 'calc(100vh - 412px)'
} else if (pageSource.value == 'policyList') {
return 'calc(100vh - 225px)'
} else {
......@@ -910,7 +981,7 @@ const tabHight = computed(() => {
})
const minHight = computed(() => {
if (pageSource.value == 'fnaList') {
return 'calc(100vh - 84.5px)'
return 'calc(100vh - 80px)'
} else if (pageSource.value == 'policyList') {
return 'calc(100vh - 84.5px)'
} else {
......@@ -934,11 +1005,11 @@ watch(
//代表是新增预约状态
if (!idsObj.value.appointmentBizId) {
formStatus.value = 'appointmentAdd'
getCustomerInfo(props.processDetail.customerBizId)
// getCustomerInfo(props.processDetail.customerBizId)
tabsList.value = [
{
label: '约信息',
label: '约信息',
name: 'appointmentInfo',
id: 1,
key: 'appointmentBizId'
......@@ -983,10 +1054,10 @@ watch(
activeName.value = 'appointmentInfo'
})
} else {
getAppointmentInfo(idsObj.value.appointmentBizId)
// getAppointmentInfo(idsObj.value.appointmentBizId)
tabsList.value = [
{
label: '约信息',
label: '约信息',
name: 'appointmentInfo',
id: 1,
key: 'appointmentBizId'
......@@ -1094,7 +1165,7 @@ const getPolicyDetail = tabName => {
}
if (route.query.source == 'policyList') {
idsObj.value.policyBizId = route.query.policyBizId
getCustomerInfo(props.policyDetailInfo.customerBizId)
// getCustomerInfo(props.policyDetailInfo.customerBizId)
appointmentSummeryInfo.value = JSON.parse(JSON.stringify(props.policyDetailInfo))
if (appointmentSummeryInfo.value.apiProductPlanInfoDto) {
appointmentSummeryInfo.value.apiAppointmentInfoDto = JSON.parse(
......@@ -1235,6 +1306,17 @@ const showSubmitBtn = computed(() => {
return false
}
})
if (route.query.appointmentNo && route.query.source == 'appointmentList') {
editStatus.value = true
} else if (route.query.source == 'policyList') {
editStatus.value = true
} else if (route.query.source == 'fnaList' && idsObj.value.appointmentBizId) {
editStatus.value = true
} else if (route.query.source == 'fnaList' && !idsObj.value.appointmentBizId) {
editStatus.value = false
}
console.log('editStatus.value ', editStatus.value, idsObj.value)
onUnmounted(() => {
// 彻底重置所有响应式数据
submitAppointmentObj.value = {}
......
<template>
<div>
<div v-if="processedAppointmentData.length > 0">
<el-row>
<el-col :span="24">
<div class="topBtn">
<el-button
v-if="props.idsObj.appointmentBizId"
type="primary"
icon="EditPen"
@click="handleEditStatus(!editStatus)"
>编辑</el-button
>
</div>
</el-col>
</el-row>
<el-form ref="appointmentInfoFormRef" :model="form" :rules="rules" label-width="120px">
<div v-for="father in processedAppointmentData">
<el-row style="margin-bottom: 10px" v-if="father.showMoudle">
<div class="formBox">
<div class="fatherLable">{{ father.fatherTitle }}</div>
<div class="fatherDes">{{ father.description }}</div>
<div v-if="processedAppointmentData.length > 0">
<div ref="appointmentRef">
<CommonForm
:anchorList="anchorList"
:affixOffset="360"
:anchorOffset="10"
:scrollContainerSelector="anchorContainer"
:scrollOffset="10"
:domIndex="tabIndex"
:activeName="activeName"
v-if="appointmentRef"
>
<template #form-right>
<el-form ref="appointmentInfoFormRef" :model="form" :rules="rules" label-width="120px">
<div v-for="father in processedAppointmentData">
<el-row style="margin-bottom: 10px" v-if="father.showMoudle" :id="father.anchorKey">
<div class="formBox">
<CardOne :title="father.fatherTitle">
<template #content>
<!-- 不是表格 -->
<el-row :gutter="20" v-if="!father.showTable">
<template v-for="child in father.data" :key="child.key">
<el-col
:sm="child.sm"
:lg="child.lg"
class="formItemBox"
v-if="child.show"
>
<div>
<el-form-item
:label-width="child.labelWidth"
:label="child.label"
:prop="child.key"
:key="child.key"
:label-position="child.labelPosition"
class="button-form-item"
>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[child.key]"
:placeholder="child.placeholder"
maxlength="30"
:rows="child.rows"
:disabled="editStatus"
/>
<el-select
v-if="child.domType === 'Select'"
v-model="form[child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(father, child)"
:disabled="editStatus"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- 带时分的时间框 -->
<div
v-if="child.domType === 'datetimePicker'"
class="compositionDateTime"
>
<el-date-picker
type="date"
placeholder="选择日期"
style="width: 100%"
v-model="form[child.key]"
:disabled="editStatus"
@change="handleDateChange(child)"
:disabled-date="time => disabledDate(time, child)"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
@clear="handleDateClear(child)"
/>
<span class="text-gray-500">-</span>
<el-time-picker
placeholder="选择时分"
style="width: 100%"
v-model="child.timeValue"
:disabled="editStatus"
format="HH:mm"
value-format="HH:mm"
/>
</div>
<!-- 不带时分 -->
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[child.key]"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:placeholder="child.placeholder"
:disabled="editStatus"
:disabled-date="time => disabledDate(time, child)"
@change="handleDateChange(child)"
@clear="handleDateClear(child)"
/>
<el-input
v-if="child.domType === 'arrowRight'"
v-model="form[child.key]"
:placeholder="child.placeholder"
:suffix-icon="ArrowRight"
readonly
:disabled="editStatus"
@focus="handleFoucs(child)"
>
</el-input>
<el-button
class="formBtn"
v-if="child.domType === 'button'"
:type="child.buttonType"
@click="handleButtonClick(child)"
>{{ child.buttonTxt }}</el-button
>
<el-row :gutter="20">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItemBox" v-if="child.show">
<div>
<el-form-item
:label-width="child.labelWidth"
:label="child.label"
:prop="child.key"
:key="child.key"
:label-position="child.labelPosition"
class="button-form-item"
>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="child.disabled"
/>
<el-select
v-if="child.domType === 'Select'"
v-model="form[child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(father, child)"
:disabled="child.disabled"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- 带时分的时间框 -->
<el-date-picker
v-model="form[child.key]"
style="width: 100%"
v-if="child.domType === 'datetimePicker'"
:type="child.timeType || 'datetime'"
:placeholder="child.placeholder"
:disabled="child.disabled"
@change="handleDateChange(child)"
:disabled-date="time => disabledDate(time, child)"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
@clear="handleDateClear(child)"
/>
<!-- 不带时分 -->
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[child.key]"
type="date"
:placeholder="child.placeholder"
:disabled="child.disabled"
:disabled-date="time => disabledDate(time, child)"
@change="handleDateChange(child)"
@clear="handleDateClear(child)"
/>
<el-input
v-if="child.domType === 'arrowRight'"
v-model="form[child.key]"
:placeholder="child.placeholder"
:suffix-icon="ArrowRight"
readonly
:disabled="child.disabled"
@focus="handleFoucs(child)"
>
</el-input>
<el-button
class="formBtn"
v-if="child.domType === 'button'"
:type="child.buttonType"
@click="handleButtonClick(child)"
>{{ child.buttonTxt }}</el-button
>
<!-- 搜索下拉框 :remote-method="query => searchSelectList(query, child)" remote-->
<el-select
v-model="form[child.key]"
v-if="child.domType === 'SearchSelect'"
filterable
:allow-create="child.allowCreate"
:reserve-keyword="false"
placeholder="请输入关键词搜索"
:loading="searchLoadingStates[child.key]"
:disabled="child.disabled"
>
<el-option
v-for="item in searchOptions[child.key] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<div v-if="child.domType === 'Div'" class="divClass">
<div v-if="child.key == 'information'" class="desBox">
<div class="title">{{ child.title }}</div>
<div class="informationBox">
<div v-for="(item, index) in child.informationList" :key="index">
{{ item.name }}
<el-select
v-model="form[child.key]"
v-if="child.domType === 'SearchSelect'"
filterable
:allow-create="child.allowCreate"
reserve-keyword
@change="handleSelectChange(father, child)"
:remote-method="query => searchSelectList(query, child.key)"
placeholder="请输入关键词搜索"
:loading="searchLoadingStates[child.key]"
:disabled="editStatus"
>
<el-option
v-for="item in searchOptions[child.key] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<div v-if="child.domType === 'Div'" class="divClass">
<div v-if="child.key == 'information'" class="desBox">
<div class="title">{{ child.title }}</div>
<div class="informationBox">
<div
v-for="(item, index) in child.informationList"
:key="index"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</el-col>
</template>
</el-col>
</template>
</el-row>
<!-- 是表格数据 -->
<el-row v-if="father.showTable">
<el-col :span="24" v-if="father.addChildren">
<el-button
:disabled="editStatus"
type="primary"
icon="Plus"
size="small"
style="margin-bottom: 10px"
@click="addChildren(father)"
>{{ father.addChildrenTxt }}</el-button
>
</el-col>
<el-table :data="father.data" border v-if="father.data.length > 0">
<template v-if="father.key == 'referrerDtoList'">
<el-table-column label="姓名" prop="realName" align="center">
<template #header>
<span class="required-label">姓名</span>
</template>
<template #default="scope">
<el-select
v-model="scope.row.realName"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索"
:remote-method="query => searchSelectList(query, 'realName')"
:loading="searchLoadingStates['realName']"
:disabled="editStatus"
>
<el-option
v-for="item in searchOptions['realName'] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="手机号" prop="phone" align="center">
<template #header>
<span class="required-label">手机号</span>
</template>
<template #default="scope">
<el-input
v-model="scope.row.phone"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="邮箱" prop="email" align="center">
<template #header>
<span class="required-label">邮箱</span>
</template>
<template #default="scope">
<el-input
v-model="scope.row.email"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon
class="deleteIcon"
@click="deleteChildren(father, scope.$index)"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
<template v-if="father.key == 'userSignDtoList'">
<el-table-column label="姓名" prop="name" align="center">
<template #header>
<span class="required-label">姓名</span>
</template>
<template #default="scope">
<el-select
v-model="scope.row.name"
filterable
remote
reserve-keyword
placeholder="请选择"
:remote-method="query => searchSelectList(query, 'name')"
:loading="searchLoadingStates['name']"
:disabled="editStatus"
>
<el-option
v-for="item in searchOptions['name'] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="手机号" prop="phone" align="center">
<template #header>
<span class="required-label">手机号</span>
</template>
<template #default="scope">
<el-input
v-model="scope.row.phone"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="执业编码" prop="practiceCode" align="center">
<template #header>
<span class="required-label">执业编码</span>
</template>
<template #default="scope">
<el-input
v-model="scope.row.practiceCode"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="邮箱" prop="email" align="center">
<template #default="scope">
<el-input
v-model="scope.row.email"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column label="证件类型" prop="cardType" align="center">
<template #default="scope">
<el-select
v-model="scope.row.cardType"
placeholder="请选择"
:disabled="editStatus"
clearable
>
<el-option
v-for="item in fetchDictData('csf_id_type')"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column label="证件号" prop="cardNo" align="center">
<template #default="scope">
<el-input
v-model="scope.row.cardNo"
size="default"
placeholder="请输入"
:disabled="editStatus"
/>
</template>
</el-table-column>
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon
@click="deleteChildren(father, scope.$index)"
class="deleteIcon"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
</el-table>
</el-row>
</template>
</CardOne>
</div>
</el-row>
</div>
</el-row>
</div>
<el-row v-if="props.idsObj.appointmentBizId">
<el-col>
<div class="tabButton">
<!-- <el-button
type="primary"
icon="RefreshRight"
@click="resetForm"
size="large"
:disabled="editStatus"
>重置</el-button
> -->
<el-button
type="primary"
icon="Check"
@click="submitForm"
size="large"
:disabled="editStatus"
>提交</el-button
>
</div>
</el-col>
</el-row>
</el-form>
</el-form>
</template>
</CommonForm>
</div>
<!-- <div v-else class="domEmpty" v-loading="loading"></div> -->
<Phone
@close="handleCloseDrawer"
:showDrawer="showPhoneDrawer"
......@@ -192,29 +372,35 @@ import Phone from '@/views/components/phone'
import Address from '@/views/components/address'
import { watch, nextTick } from 'vue'
import { getCustomerDetail } from '@/api/sign/fna'
import { editAppointmentInfo, newPolicy } from '@/api/sign/appointment'
import { getBankList, getAllSignList, getUserSaleExpandList } from '@/api/common'
import CommonForm from '@/views/components/commonForm'
import CardOne from '@/components/formCard/cardOne'
import useDictStore from '@/store/modules/dict'
const dictStore = useDictStore() //获取字典数据
const props = defineProps({
activeName: { type: String, default: '' }, //tab名称
formStatus: { type: String, default: '' }, //父组件状态,新增、修改
idsObj: { type: Object, default: () => ({}) }, //父组件传递过来的id对象
apiAppointmentInfoDto: { type: Object, default: () => ({}) }, //父组件传递过来的约信息的详情
apiAppointmentInfoDto: { type: Object, default: () => ({}) }, //父组件传递过来的约信息的详情
appointmentStatus: { type: Number }, //父组件传递过来的预约的状态
customerBizId: { type: String, default: '' } //提交状态,新增、修改
customerBizId: { type: String, default: '' }, //提交状态,新增、修改
fatherTabName: { type: String, default: '' }, //一级tab名称
anchorContainer: { type: String, default: '' }, //锚点滚动容器
editStatus: { type: Boolean, default: true }, //编辑状态
tabIndex: { type: [String, Number], default: '' } //tab索引
})
const emit = defineEmits(['handleSuccessEdit'])
const { proxy } = getCurrentInstance()
// const { csf_id_type, sys_gender } = proxy.useDict('csf_id_type', 'sys_gender')
const appointmentRef = ref(null)
const showPhoneDrawer = ref(false) //电话抽屉开关
const showAddressDrawer = ref(false) //地址抽屉开关
const showCountryDrawer = ref(false) //国家/地区抽屉开关
const drawerInfo = ref({}) // 用于存储所有arrowRight类型的输入框输入值
const saveKey = ref({}) // 用于存储当前点击的drawer框返回的对象,修改的时候回显值也要存key
const errorFields = ref([]) // 存储校验失败的字段信息
const editStatus = ref(true) // 表单是否可编辑,若是修改初始不可编辑
const openList = ref(false) // 客户列表弹窗
const oldObjInfo = ref({}) // 修改时存储原始数据,便于撤销操作
const consultKey = ref({})
......@@ -292,21 +478,120 @@ const data = reactive({
}
})
const { form, rules, processedAppointmentData, queryParams, oldAppointmentData } = toRefs(data)
// 添加表单子级dom
const addChildren = father => {
const processedData = JSON.parse(JSON.stringify(processedAppointmentData.value))
let obj4 = {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
email: '',
phone: '',
realName: ''
}
let obj5 = {
id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
name: '', //姓名
practiceCode: '', //执业编码
phone: '', //手机号
cardType: '', //证件类型
cardNo: '', //证件号码
email: '' //邮箱
}
for (const section of processedData) {
if (father.key == 'referrerDtoList' && section.key == father.key) {
section.data.push(obj4)
}
if (father.key == 'userSignDtoList' && section.key == father.key) {
section.data.push(obj5)
}
}
//更新form表单对应的数据,以便收集填写的值
// form.value[father.key].push(obj)
processedAppointmentData.value = processedData
}
const deleteChildren = (father, childIndex) => {
if (props.editStatus.value) {
proxy.$modal.confirm(`请先点击编辑再进行删除操作`, { showCancel: '0', title: '填写提示' })
return
}
const processedData = JSON.parse(JSON.stringify(processedAppointmentData.value))
for (const section of processedData) {
if (father.key == 'referrerDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
if (father.key == 'userSignDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
processedAppointmentData.value = processedData
}
// 搜索方法
const searchSelectList = async (query, field) => {
const searchSelectList = async (query, key) => {
// 设置该字段的加载状态
searchLoadingStates.value[field.key] = true
searchLoadingStates.value[key] = true
let queryString = query.trim()
try {
// 根据不同的字段key调用不同的API
if (field.key === 'bankName') {
console.log('searchOptions.value[field.key]', searchOptions.value[field.key])
if (key === 'bankName') {
const params4 = {
pageNo: 1,
pageSize: 10,
queryContent: queryString
}
const response4 = await getBankList(params4)
if (response4.code == 200) {
response4.data.records = response4.data.records.map(item => {
return {
...item,
label: item.bankName,
value: item.bankBizId
}
})
searchOptions.value[key] = response4.data.records
}
} else if (key == 'realName') {
const params5 = {
pageNo: 1,
pageSize: 10,
queryContent: queryString
}
const response5 = await getUserSaleExpandList(params5)
if (response5.code == 200) {
response5.data.records = response5.data.records.map(item => {
return {
...item,
label: item.realName,
value: item.userSaleBizId
}
})
searchOptions.value[key] = response5.data.records
}
} else if (key == 'name') {
const params5 = {
pageNo: 1,
pageSize: 10,
realName: queryString
}
const response5 = await getAllSignList(params5)
if (response5.code == 200) {
response5.data.records = response5.data.records.map(item => {
return {
...item,
label: item.realName,
value: item.userSignBizId
}
})
searchOptions.value[key] = response5.data.records
}
}
} catch (error) {
console.error(`${field.label} 搜索失败`, error)
searchOptions.value[field.key] = []
console.error(` 搜索失败`, error)
searchOptions.value[key] = []
} finally {
searchLoadingStates.value[field.key] = false
searchLoadingStates.value[key] = false
}
}
const disabledDate = (time, child) => {
......@@ -321,22 +606,7 @@ const disabledDate = (time, child) => {
// 默认禁用今天及今天之前
return inputDate.isBefore(today, 'day') || inputDate.isSame(today, 'day')
break
// case 'arrivalTime':
// // 如果允许选择今天,只禁用今天之前的日期
// return inputDate.isBefore(today, 'day')
// break
// case 'departureTime':
// // 获取开始日期(需要从表单数据中获取)
// const startTime1 = form.value.arrivalTime
// if (startTime1) {
// const arrivalDate = dayjs(startTime1).startOf('day')
// // 只禁用到达日期之前的日期,允许选择同一天
// return inputDate.isBefore(arrivalDate, 'day')
// } else {
// // 如果没有选择到达时间,禁用今天之前的日期
// return inputDate.isBefore(today, 'day')
// }
// break
case 'confirmAppointmentTime':
return inputDate.isBefore(today, 'day')
break
......@@ -393,8 +663,7 @@ const handleDateChange = child => {
resetShow({ type: 'child', key: 'openAccountEndTime', status: false, flag: 'disabled' })
disabledDate(form.value['openAccountStartTime'], { key: 'openAccountEndTime' })
}
// resetShow({ type: 'child', key: 'departureTime', status: false, flag: 'disabled' })
// disabledDate(form.value['arrivalTime'], { key: 'departureTime' })
// 离港时间在到港时间之前
if (
child.key == 'arrivalTime' &&
......@@ -415,51 +684,6 @@ const handleDateChange = child => {
} else if (child.key === 'confirmAppointmentTime' && form.value[child.key]) {
resetShow({ type: 'child', key: 'newPolicyButton', status: true, flag: 'show' })
}
// if (child.key === 'confirmAppointmentTime' && form.value[child.key]) {
// if (form.value['arrivalTime']) {
// const appointmentTimestamp = dayjs(form.value['confirmAppointmentTime']).valueOf()
// const arrivalTimestamp = dayjs(form.value['arrivalTime']).valueOf()
// if (appointmentTimestamp < arrivalTimestamp) {
// proxy.$modal.msgError('预约时间早于到港时间,请重新选择预约时间')
// form.value['confirmAppointmentTime'] = ''
// return
// } else if (appointmentTimestamp > arrivalTimestamp) {
// } else {
// proxy.$modal.msgError('预约时间应晚于到港时间,请重新选择预约时间')
// form.value['confirmAppointmentTime'] = ''
// return
// }
// }
// resetShow({ type: 'child', key: 'newPolicyButton', status: true, flag: 'show' })
// } else if (child.key === 'confirmAppointmentTime' && !form.value[child.key]) {
// resetShow({ type: 'child', key: 'newPolicyButton', status: false, flag: 'show' })
// } else if (child.key === 'arrivalTime') {
// if (form.value['confirmAppointmentTime']) {
// const appointmentTimestamp = dayjs(form.value['confirmAppointmentTime']).valueOf()
// const arrivalTimestamp = dayjs(form.value['arrivalTime']).valueOf()
// if (appointmentTimestamp < arrivalTimestamp) {
// proxy.$modal.msgError('预约时间早于到港时间,请重新选择到港时间')
// form.value['arrivalTime'] = ''
// form.value['departureTime'] = ''
// resetShow({ type: 'child', key: 'departureTime', status: true, flag: 'disabled' })
// } else if (appointmentTimestamp > arrivalTimestamp) {
// console.log('预约时间晚于到港时间')
// } else {
// proxy.$modal.msgError('到港时间应早于预约时间,请重新选择到港时间')
// form.value['arrivalTime'] = ''
// form.value['departureTime'] = ''
// resetShow({ type: 'child', key: 'departureTime', status: true, flag: 'disabled' })
// }
// }
// } else if (child.key === 'confirmAppointmentTime') {
// if (form.value['arrivalTime']) {
// const appointmentTimestamp = dayjs(form.value['confirmAppointmentTime']).valueOf()
// const arrivalTimestamp = dayjs(form.value['arrivalTime']).valueOf()
// console.log('appointmentTimestamp', appointmentTimestamp)
// console.log('arrivalTimestamp', arrivalTimestamp)
// }
// }
}
// 获取字典数据
const fetchDictData = dictType => {
......@@ -512,7 +736,10 @@ const processFormData = async () => {
field.options = fetchDictData(field.dictType)
}
if (field.key == 'bankName') {
searchOptions.value[field.key] = fetchDictData(field.dictType)
searchOptions.value[field.key] = dictStore.bankList
}
if (field.key == 'realName') {
searchOptions.value[field.key] = dictStore.userSaleExpandList
}
if (field.required) {
if (field.key === 'firstNamePinyin') {
......@@ -531,10 +758,11 @@ const processFormData = async () => {
}
if (props.idsObj.appointmentBizId) {
editStatus.value = true
// editStatus.value = true
setFormValue(props.apiAppointmentInfoDto, processedData)
} else {
editStatus.value = false
// 新增给默认值
form.value['isReferrerAccompany'] = form.value['isOpenAccount'] = form.value['isUseCar'] = 0
processedAppointmentData.value = processedData
}
}
......@@ -674,12 +902,12 @@ const resetShow = obj => {
}
const handleSelectChange = (father, child) => {
switch (child.key) {
case 'isAccompany':
case 'isReferrerAccompany':
// 选择吸烟,展示吸烟数量
if (form.value[child.key] == '1') {
resetShow({ type: 'father', key: 'consult', status: true })
resetShow({ type: 'father', key: 'referrerDtoList', status: true })
} else {
resetShow({ type: 'father', key: 'consult', status: false })
resetShow({ type: 'father', key: 'referrerDtoList', status: false })
}
break
......@@ -690,6 +918,23 @@ const handleSelectChange = (father, child) => {
} else {
resetShow({ type: 'father', key: 'openAccount', status: false })
}
break
case 'bankName':
// 选择吸烟,展示吸烟数量
if (form.value[child.key]) {
if (
searchOptions.value[child.key].findIndex(item => item.value == form.value[child.key]) !==
-1
) {
searchOptions.value[child.key].forEach(item => {
if (item.value == form.value[child.key]) {
form.value['materials'] = item.materials
}
})
} else {
form.value['materials'] = ''
}
}
break
......@@ -754,9 +999,9 @@ const setFormValue = (obj, formData) => {
} else {
field.disabled = false
}
if (field.key == 'bankName') {
searchOptions.value[field.key] = fetchDictData(field.dictType)
}
// if (field.key == 'bankName') {
// searchOptions.value[field.key] = fetchDictData(field.dictType)
// }
// 处理时间
if (field.key == 'openAccountEndTime' && obj[field.key]) {
// 开始时间是否在结束时间之前
......@@ -898,119 +1143,194 @@ const getInvalidFields = fields => {
return errors
}
// 处理表单填写得数据
const handleFormValues = () => {
let submitObj = { ...form.value }
const pattern = /Time$/ // 以Time结尾
return new Promise(resolve => {
let submitObj = { ...form.value }
const pattern = /Time$/
//处理表单数据
for (const key1 in form.value) {
// 不开户去除开户相关信息
if (key1 == 'isOpenAccount' && form.value[key1] === 0) {
for (const key4 in openAccountKey.value) {
delete submitObj[key4]
}
}
// 没顾问去除顾问相关信息
if (key1 == 'isAccompany' && form.value[key1] === 0) {
for (const key5 in consultKey.value) {
delete submitObj[key5]
}
}
if (pattern.test(key1) && form.value[key1]) {
submitObj[key1] = proxy.formatToDateTime(form.value[key1])
}
for (const key2 in saveKey.value) {
//要判断drawerType
switch (saveKey.value[key2].objType) {
case 'phone':
if (key1 == key2) {
for (const key3 in saveKey.value[key2]) {
submitObj[key3] = saveKey.value[key2][key3]
proxy.$refs['appointmentInfoFormRef'].validate((valid, fields) => {
if (valid) {
errorFields.value = [] // 清空错误信息
//处理表单数据
for (const key1 in form.value) {
// 不开户去除开户相关信息
if (key1 == 'isOpenAccount' && form.value[key1] == 0) {
for (const key4 in openAccountKey.value) {
delete submitObj[key4]
}
}
break
case 'address':
if (key1 == key2) {
addressList.push(saveKey.value[key2])
if (pattern.test(key1) && form.value[key1]) {
submitObj[key1] = proxy.formatToDateTime(form.value[key1])
}
break
case 'country':
if (key1 == key2) {
submitObj['country'] = saveKey.value[key2]['countryCode']
submitObj['countryName'] = saveKey.value[key2]['name']
// 处理电话和地址相关的
for (const key2 in saveKey.value) {
//要判断drawerType
switch (saveKey.value[key2].objType) {
case 'phone':
if (key1 == key2) {
for (const key3 in saveKey.value[key2]) {
submitObj[key3] = saveKey.value[key2][key3]
}
}
break
case 'address':
if (key1 == key2) {
addressList.push(saveKey.value[key2])
}
break
case 'country':
if (key1 == key2) {
submitObj['country'] = saveKey.value[key2]['countryCode']
submitObj['countryName'] = saveKey.value[key2]['name']
}
break
default:
break
}
}
break
default:
break
}
}
}
if (submitObj['departureTime']) {
// 开始时间是否在结束时间之前
if (
submitObj['arrivalTime'] &&
!dayjs(submitObj['arrivalTime']).isBefore(dayjs(submitObj['departureTime']))
) {
proxy.$message.error('预约信息模块--离港时间必须晚于到港时间!!')
return undefined
}
}
}
if (submitObj['bankName']) {
searchOptions.value['bankName'].forEach(item => {
if (submitObj['bankName'] == item.bankBizId) {
submitObj['bankName'] = item.bankName
}
})
}
return submitObj
}
// 表单提交
const submitForm = () => {
// return
proxy.$refs['appointmentInfoFormRef'].validate((valid, fields) => {
if (valid) {
let submitObj = handleFormValues()
console.log('====================================')
console.log('submitObj', submitObj)
console.log('====================================')
// return
if (!submitObj) return
if (props.idsObj.appointmentBizId) {
editAppointmentInfo(submitObj).then(res => {
if (res.code == 200) {
handleEditStatus(true)
proxy.$message.success('预约信息修改成功')
emit('handleSuccessEdit')
let obj = {
realName: '转介人姓名',
phone: '转介人手机',
email: '转介人邮箱'
}
let obj1 = {
name: '签单员姓名',
phone: '签单员电话',
practiceCode: '签单员执业编码'
}
processedAppointmentData.value.forEach(item => {
if (item.key == 'referrerDtoList') {
if (form.value['isReferrerAccompany'] == 1 && item.data.length > 0) {
submitObj['referrerDtoList'] = item.data.map((item1, index) => {
if (item1.realName) {
searchOptions.value['realName'].forEach(item2 => {
if (item1.realName == item2.userSaleBizId) {
item1.realName = item2.realName
}
})
}
for (const key in item1) {
if (!item1[key]) {
errorFields.value.push({
message: `陪同转介人-第${index + 1}${obj[key]}不能为空`
})
}
}
return {
realName: item1.realName,
phone: item1.phone,
email: item1.email
}
})
} else if (form.value['isReferrerAccompany'] == 1 && item.data.length == 0) {
errorFields.value.push({
message: '签约信息模块--转介人陪同时,陪同转介人信息不能为空!!'
})
}
}
if (item.key == 'position') {
item.data.forEach((item1, index) => {
if (item1.compositionTime) {
if (item1.timeValue) {
submitObj[item1.key] = form.value[item1.key] + ' ' + item1.timeValue + ':00'
} else {
submitObj[item1.key] = form.value[item1.key] + ' 00:00:00'
}
}
})
}
if (item.key == 'userSignDtoList' && item.data.length > 0) {
submitObj['userSignDtoList'] = item.data.map((item1, index) => {
if (item1.name) {
searchOptions.value['name'].forEach(item2 => {
if (item1.name == item2.userSignBizId) {
item1.name = item2.realName
}
})
}
for (const key in item1) {
if (!item1[key]) {
errorFields.value.push({
message: `签单员-第${index + 1}${obj1[key]}不能为空`
})
}
}
return {
name: item1.name,
phone: item1.phone,
email: item1.email,
practiceCode: item1.practiceCode,
cardType: item1.cardType,
cardNo: item1.cardNo
}
})
}
})
console.log('submitObj', submitObj)
if (submitObj['departureTime']) {
// 开始时间是否在结束时间之前
if (
submitObj['arrivalTime'] &&
!dayjs(submitObj['arrivalTime']).isBefore(dayjs(submitObj['departureTime']))
) {
errorFields.value.push({
message: '签约信息模块--离港时间必须晚于到港时间!!'
})
// return undefined
}
}
if (errorFields.value.length > 0) {
proxy.$message.error(errorFields.value[0].message)
}
resolve(errorFields.value.length == 0 ? submitObj : null)
} else {
errorFields.value = getInvalidFields(fields)
if (errorFields.value.length > 0) {
proxy.$message.error(errorFields.value[0].message)
}
resolve(undefined)
}
errorFields.value = [] // 清空错误信息
} else {
// 获取校验失败的字段信息
errorFields.value = getInvalidFields(fields)
if (errorFields.value.length > 0) {
proxy.$message.error(errorFields.value[0].message)
}
}
})
}
const resetForm = () => {
proxy.$modal
.confirm('是否确认撤销所作操作?')
.then(function () {
form.value = { ...oldObjInfo.value }
editStatus.value = true
processedAppointmentData.value = JSON.parse(JSON.stringify(oldAppointmentData.value))
proxy.$refs['appointmentInfoFormRef'].resetFields()
})
.catch(() => {})
})
}
const anchorList = computed(() => {
let data = []
for (const section of processedAppointmentData.value) {
if (section.showMoudle) {
data.push({ title: section.anchorKey, name: section.fatherTitle })
}
}
return data
})
watch(
() => props.activeName,
newVal => {
appointmentRef.value = null
if (newVal === 'appointmentInfo') {
openList.value = false
setTimeout(() => {
processFormData()
}, 500)
processFormData()
}
}
)
// 因为tab嵌套了两层,所以需要监听父组件的tab否则锚点的显示就会有bug
watch(
() => props.fatherTabName,
newVal => {
if (newVal) {
appointmentRef.value = null
}
}
)
......@@ -1030,6 +1350,11 @@ defineExpose({
})
</script>
<style lang="scss" scoped>
.required-label::before {
content: '*';
color: #f56c6c;
margin-right: 4px;
}
.domEmpty {
width: 100%;
height: 100%;
......@@ -1150,6 +1475,16 @@ defineExpose({
margin-bottom: 0px;
}
}
.deleteIcon {
color: red;
font-size: 18px;
padding-top: 10px;
}
.compositionDateTime {
display: flex;
width: 100%;
box-sizing: border-box;
}
@media only screen and (min-width: 768px) {
.formBtn {
margin-top: 0 !important;
......
<template>
<div>
<div v-if="processedProductData.length > 0">
<el-row>
<el-col :span="24">
<div class="topBtn">
<!-- v-if="props.idsObj.appointmentBizId" -->
<el-button
v-if="props.showSubmitBtn"
type="primary"
icon="EditPen"
@click="handleEditStatus(!editStatus)"
>编辑</el-button
<!-- 只画好了样式具体的逻辑还没处理 -->
<div v-if="processedProductData.length > 0">
<div ref="productRef">
<CommonForm
:anchorList="anchorList"
:affixOffset="360"
:anchorOffset="10"
:scrollContainerSelector="anchorContainer"
:scrollOffset="10"
:domIndex="tabIndex"
:activeName="activeName"
v-if="productRef"
>
<template #form-right>
<el-form ref="productFormRef" :model="form" :rules="rules">
<el-row
v-for="father in processedProductData"
style="margin-bottom: 10px"
:id="father.anchorKey"
>
</div>
</el-col>
</el-row>
<el-form ref="productFormRef" :model="form" :rules="rules">
<el-row v-for="father in processedProductData" style="margin-bottom: 10px">
<div class="formBox formFna">
<div class="fatherLable">
<span>{{ father.fatherTitle }}</span>
<el-button
style="margin-left: 10px"
v-if="father.addBtn"
type="primary"
icon="Plus"
@click="addChildren(father)"
size="small"
:disabled="editStatus"
>新增</el-button
>
</div>
<div class="subTitle" v-if="father.subTitle">{{ father.subTitle }}</div>
<el-row v-if="father.child == 'no'" :gutter="20">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItem" v-if="child.show">
<div>
<el-form-item
:label="child.label"
:prop="father.key + '.' + child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="child.disabled"
:style="{ width: child.inputWidth ? child.inputWidth : '100%' }"
/>
<el-select
v-if="child.domType === 'Select'"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(father, child)"
:disabled="child.disabled"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[father.key][child.key]"
type="date"
:placeholder="child.placeholder"
:disabled="child.disabled"
/>
<el-checkbox-group
v-if="child.domType === 'Checkbox'"
v-model="form[father.key][child.key]"
:disabled="child.disabled"
>
<el-checkbox
v-for="item in child.options"
:key="item.value"
:label="item.value"
<div class="formBox formFna">
<CardOne :title="father.fatherTitle">
<template #content>
<el-row v-if="!father.showTable" :gutter="20">
<template v-for="child in father.data" :key="child.key">
<el-col :sm="child.sm" :lg="child.lg" class="formItem" v-if="child.show">
<div>
<el-form-item
:label="child.label"
:prop="father.key + '.' + child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
maxlength="30"
:disabled="editStatus"
:style="{ width: child.inputWidth ? child.inputWidth : '100%' }"
/>
<el-select
v-if="child.domType === 'Select'"
v-model="form[father.key][child.key]"
:placeholder="child.placeholder"
@change="handleSelectChange(father, child)"
:disabled="editStatus"
>
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="form[father.key][child.key]"
type="date"
:placeholder="child.placeholder"
:disabled="editStatus"
/>
<el-checkbox-group
v-if="child.domType === 'Checkbox'"
v-model="form[father.key][child.key]"
:disabled="editStatus"
>
<el-checkbox
v-for="item in child.options"
:key="item.value"
:label="item.value"
>
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
<el-select
v-model="form[father.key][child.key]"
v-if="child.domType === 'SearchSelect'"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索"
:remote-method="query => searchSelectList(query, child.key)"
:loading="searchLoadingStates[child.key]"
:disabled="editStatus"
@change="handleSearchSelectChange(father, child)"
>
<el-option
v-for="item in searchOptions[child.key] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</div>
</el-col>
</template>
</el-row>
<!-- 是表格数据 -->
<el-row v-if="father.showTable">
<el-col :span="24" v-if="father.addChildren">
<el-button
:disabled="editStatus"
type="primary"
icon="Plus"
size="small"
style="margin-bottom: 10px"
@click="addChildren(father)"
>{{ father.addChildrenTxt }}</el-button
>
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
<el-select
v-model="form[father.key][child.key]"
v-if="child.domType === 'SearchSelect'"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索"
:remote-method="query => searchSelectList(query, child.key)"
:loading="searchLoadingStates[child.key]"
:disabled="child.disabled"
@change="handleSearchSelectChange(father, child)"
>
<el-option
v-for="item in searchOptions[child.key] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</div>
</el-col>
</template>
</el-col>
<el-table :data="father.data" border v-if="father.data.length > 0">
<template v-if="father.key == 'apiProductPlanAdditionalInfoDtoList'">
<el-table-column label="姓名" prop="realName" align="center" />
<el-table-column width="60px" align="center" label="操作">
<template #default="scope">
<el-icon
class="deleteIcon"
@click="deleteChildren(father, scope.$index)"
><Delete
/></el-icon>
</template>
</el-table-column>
</template>
</el-table>
</el-row>
</template>
</CardOne>
</div>
</el-row>
<!-- 有子孙的dom -->
<el-row v-if="father.child == 'yes' && father.data.length > 0" :gutter="20">
<template v-for="(child, childIndex) in father.data" :key="child.id">
<el-col :span="child.span">
<div
class="childLabel"
v-if="father.key == 'apiProductPlanAdditionalInfoDtoList'"
@click="deleteChildren(father, childIndex)"
</el-form>
</template>
</CommonForm>
</div>
<CommonDialog
:dialogTitle="dialogTitle"
confirmText="确定"
cancleText="关闭"
dialogWidth="70%"
:showClose="true"
:openDialog="dialogVisible"
@close="dialogVisible = false"
>
<div class="dialogBox">
<el-form>
<el-row :gutter="20">
<template v-for="(child, dIndex) in additionalProductForm">
<el-col :sm="child.sm" :lg="child.lg" class="formItem">
<el-form-item
:label="child.label"
:prop="child.key"
:key="child.key"
:label-width="child.labelWidth"
:label-position="child.labelPosition"
>
<el-input
v-if="child.domType === 'Input'"
:type="child.inputType"
v-model="child.value"
:placeholder="child.placeholder"
maxlength="30"
/>
<el-select
v-if="child.domType === 'Select'"
v-model="child.value"
:placeholder="child.placeholder"
>
<span>{{ `${child.childTitle}-${childIndex + 1}` }}</span>
<el-icon
v-if="child.deleteBtn"
style="color: red; font-size: 18px; margin-left: 10px"
><Delete
/></el-icon>
</div>
</el-col>
<template v-for="grandchildren in child.children" :key="grandchildren.key">
<el-col
:sm="grandchildren.sm"
:lg="grandchildren.lg"
class="formItem"
v-if="grandchildren.show && form[father.key] && form[father.key][childIndex]"
<el-option
v-for="item in child.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="child.domType === 'DatePicker'"
v-model="child.value"
type="date"
:placeholder="child.placeholder"
/>
<el-select
v-model="child.value"
v-if="child.domType === 'SearchSelect'"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索"
@change="handleSearchSelectChange(child.key, dIndex)"
:remote-method="query => searchSelectList(query, child.key)"
:loading="searchLoadingStates[child.key]"
>
<el-form-item
:label="grandchildren.label"
:prop="grandchildren.key"
:key="grandchildren.key"
:label-width="grandchildren.labelWidth"
:label-position="grandchildren.labelPosition"
>
<el-input
v-if="grandchildren.domType === 'Input'"
:type="grandchildren.inputType"
v-model="form[father.key][childIndex][grandchildren.key]"
:placeholder="grandchildren.placeholder"
maxlength="30"
:disabled="grandchildren.disabled"
/>
<!-- 下拉框 -->
<el-select
v-if="grandchildren.domType === 'Select'"
v-model="form[father.key][childIndex][grandchildren.key]"
:placeholder="grandchildren.placeholder"
:disabled="grandchildren.disabled"
>
<el-option
v-for="item in grandchildren.options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-date-picker
style="width: 100%"
v-if="grandchildren.domType === 'DatePicker'"
v-model="form[father.key][childIndex][grandchildren.key]"
type="date"
:placeholder="grandchildren.placeholder"
:disabled="grandchildren.disabled"
/>
<!-- 搜索下拉框 -->
<el-select
v-model="form[father.key][childIndex][grandchildren.key]"
v-if="grandchildren.domType === 'SearchSelect'"
filterable
remote
reserve-keyword
placeholder="请输入关键词搜索"
:remote-method="query => searchSelectList(query, grandchildren.key)"
:loading="searchLoadingStates[grandchildren.key]"
:disabled="grandchildren.disabled"
>
<el-option
v-for="item in searchOptions[grandchildren.key] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</template>
</template>
</el-row>
</div>
</el-row>
<el-row v-if="props.showSubmitBtn">
<el-col>
<div class="tabButton">
<el-button
type="success"
icon="Check"
@click="submitForm()"
size="large"
:disabled="editStatus"
>保存</el-button
>
</div>
</el-col>
</el-row>
</el-form>
</div>
<el-option
v-for="item in searchOptions[child.key] || []"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
</div>
</CommonDialog>
</div>
</template>
<script setup name="customer">
import CommonForm from '@/views/components/commonForm'
import CommonDialog from '@/components/commonDialog'
import CardOne from '@/components/formCard/cardOne'
import useDictStore from '@/store/modules/dict'
import productDomData from '@/formJson/productPlan'
import { watch } from 'vue'
import { getInsuranceProductList, getAdditionalProductList } from '@/api/common'
import {
getInsuranceProductList,
getAdditionalProductList,
secondAdditonalList
} from '@/api/common'
import { editProductPlanInfo, delAdditional } from '@/api/sign/appointment'
import { updatePolicyProduct, delPolicyAdditional } from '@/api/sign/underwritingMain'
import useUserStore from '@/store/modules/user'
......@@ -240,19 +242,27 @@ const props = defineProps({
pageSource: { type: String, default: '' }, //页面来源
idsObj: { type: Object, default: () => ({}) }, //父组件传递过来的id对象
apiProductPlanInfoDto: { type: Object, default: () => ({}) }, //父组件传递过来的预约信息的详情
appointmentStatus: { type: Number } //父组件传递过来的预约的状态
appointmentStatus: { type: Number }, //父组件传递过来的预约的状态
fatherTabName: { type: String, default: '' }, //一级tab名称
anchorContainer: { type: String, default: '' }, //锚点滚动容器
editStatus: { type: Boolean, default: true }, //编辑状态
tabIndex: { type: [String, Number], default: '' } //tab索引
})
const emit = defineEmits(['handleSuccessEdit', 'policyEditSuccess'])
const { proxy } = getCurrentInstance()
// const { sys_no_yes } = proxy.useDict('sys_no_yes')
const saveKey = ref({}) // 用于存储当前点击的drawer框返回的对象,修改的时候回显值也要存key
const dialogTitle = ref('新增')
const dialogVisible = ref(false)
const productRef = ref(null) // 用于存储当前点击的drawer框返回的对象,修改的时候回显值也要存key
const errorFields = ref([]) // 存储校验失败的字段信息
const editStatus = ref(true) // 表单是否可编辑,若是修改初始不可编辑
// const anchorList = ref([]) // 存储校验失败的字段信息
// const editStatus = ref(true) // 表单是否可编辑,若是修改初始不可编辑
const openList = ref(false) // 客户列表弹窗
const oldObjInfo = ref({}) // 修改时存储原始数据,便于撤销操作
const currencyType = ref([]) // 是否列表
const searchOptions = ref({}) // 存储不同key对应的选项
const searchLoadingStates = ref({}) // 存储不同key对应的加载状态
const additionalProductForm = ref([]) // 附加险的表单
const data = reactive({
form: {},
tempForm: {}, //由于切换tab的时候,表单数据会重置,所以需要保存一份临时表单数据
......@@ -266,46 +276,102 @@ const data = reactive({
}
})
const { form, rules, processedProductData, queryParams, oldProductDomData, tempForm } = toRefs(data)
const resetForm = () => {
proxy.$modal
.confirm('是否确认撤销所作操作?')
.then(function () {
form.value = { ...oldObjInfo.value }
editStatus.value = true
processedProductData.value = JSON.parse(JSON.stringify(oldProductDomData.value))
proxy.$refs['productFormRef'].resetFields()
})
.catch(() => {})
// 添加表单子级dom
const addChildren = father => {
if (props.editStatus) {
proxy.$message.warning('请先点击编辑')
return
}
if (father.key == 'apiProductPlanAdditionalInfoDtoList') {
dialogTitle.value = '新增附加计划'
additionalProductForm.value = JSON.parse(JSON.stringify(father.formItem))
dialogVisible.value = true
}
}
const handleSearchSelectChange = (father, child) => {
let productItem = dictStore.insureProductList.filter(item => {
return item.value == form.value[father.key][child.key]
})
let options = productItem[0].paymentTerm.split(',').map(item => {
return {
label: item,
value: item
}
})
const deleteChildren = (father, childIndex) => {
if (editStatus.value) {
proxy.$message.warning('编辑状态下才能删除')
return
}
return
const processedData = JSON.parse(JSON.stringify(processedProductData.value))
for (const section of processedData) {
if (section.key == father.key) {
if (section.data) {
for (const field of section.data) {
if (field.dictType && field.dictType == 'paymentTerm') {
field.options = options
if (
props.idsObj.appointmentBizId &&
form.value[father.key][childIndex].additionalBizId &&
(props.pageSource == 'appointmentList' || props.pageSource == 'fnaList')
) {
delAdditional(form.value[father.key][childIndex].additionalBizId).then(res => {
if (res.code == 200) {
proxy.$message.success('附加险删除成功')
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].splice(childIndex, 1)
emit('handleSuccessEdit')
}
})
} else if (
props.idsObj.policyBizId &&
form.value[father.key][childIndex].id &&
props.pageSource == 'policyList'
) {
delPolicyAdditional(form.value[father.key][childIndex].id).then(res => {
if (res.code == 200) {
proxy.$message.success('附加险删除成功')
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].splice(childIndex, 1)
emit('policyEditSuccess')
}
})
} else {
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].splice(childIndex, 1)
}
if (options.length > 0) {
form.value[father.key]['paymentTerm'] = options[0].value
}
processedProductData.value = processedData
}
const handleSearchSelectChange = (key, index) => {
// 附加计划选择产品后,给供款期数下拉框赋值
if (key == 'productLaunchName') {
additionalProductForm.value.forEach(item => {
searchOptions.value['productLaunchName'].forEach(item1 => {
if (item1.value == additionalProductForm.value[index]['value']) {
item1.apiAttributeSettingDtoList.forEach(item2 => {
if (
item2.attributeSettingBizId == 'attribute_setting_okpcuc8tlXRfVIAy' &&
item.key == 'issueNumber'
) {
if (item2.value) {
item.options = item2.value
.split(/[,,;;\s]+/)
.map(item => item.trim())
.filter(item => item !== '')
.map(item => {
return { label: item, value: item }
})
if (item.options.length > 0) item.value = item.options[0].value
}
}
})
}
})
})
}
}
// 下拉框搜索方法
// 搜索方法
const searchSelectList = async (query, fieldKey) => {
......@@ -335,20 +401,24 @@ const searchSelectList = async (query, fieldKey) => {
}
}
// 可以添加其他字段的处理,可以放其他的字段得请求,目前只有accountName,以后有了其他的在填充
else if (fieldKey === 'addProductName') {
else if (fieldKey === 'productLaunchName') {
const params = {
productName: query.trim(),
pageNo: 1,
pageSize: 10
pageSize: 10,
projectBizId: userStore.projectInfo.projectBizId,
tenantBizId: userStore.projectInfo.tenantBizId,
fieldBizId: 'field_olk1qZe81qHHKXbw',
fieldValueBizId: 'field_value_yXzTigvgUdRMFpoR'
}
const response = await getAdditionalProductList(params)
const response = await secondAdditonalList(params)
if (response.code == 200) {
response.data.records = response.data.records.map(item => {
return {
...item,
label: item.productName,
value: item.additionalProductBizId
label: item.title,
value: item.productLaunchBizId
}
})
searchOptions.value[fieldKey] = response.data.records
......@@ -383,6 +453,7 @@ const processFormData = async () => {
const processedData = JSON.parse(JSON.stringify(productDomData))
for (const section of processedData) {
// anchorList.value.push({ title: section.anchorKey, name: section.fatherTitle })
if (section.fatherRequired) {
rules.value[section.key] = {}
}
......@@ -392,6 +463,13 @@ const processFormData = async () => {
} else if (section.keyType == 'Object') {
form.value[section.key] = {}
}
if (section.formItem) {
section.formItem.forEach(item => {
if (item.dictType) {
item.options = fetchDictData(item.dictType)
}
})
}
if (section.data) {
for (const formKey in form.value) {
if (section.key == formKey) {
......@@ -430,7 +508,7 @@ const processFormData = async () => {
/*
1.没有嵌套子级的也就是没有children的数据加rules,根据data中的required字段判断是否必填
*/
if (field.required && section.child == 'no') {
if (field.required) {
rules.value[section.key][field.key] = [
{ required: true, message: `${field.label}不能为空`, trigger: 'blur' }
]
......@@ -470,218 +548,16 @@ const processFormData = async () => {
// idsObj.appointmentBizId
// 证明是修改
if (props.showSubmitBtn) {
editStatus.value = true
// editStatus.value = true
// processedProductData.value = processedData
//在流程和预约的时候要调用这个方法回显修改数据
console.log('====================================')
console.log('props.apiProductPlanInfoDto', props.apiProductPlanInfoDto)
console.log('====================================')
setFormValue(props.apiProductPlanInfoDto, processedData)
} else {
editStatus.value = false
// editStatus.value = false
processedProductData.value = processedData
}
}
// 添加表单子级dom
const addChildren = father => {
if (editStatus.value) {
proxy.$message.warning('请先点击编辑')
return
}
const processedData = JSON.parse(JSON.stringify(processedProductData.value))
let obj = {
// id: Date.now() + Math.floor(Math.random() * 1000), //唯一标识
span: 24, //栅格布局份数
childTitle: '附加险',
deleteBtn: true,
children: [
{
label: '产品名称',
key: 'addProductName',
domType: 'SearchSelect',
required: true,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
labelPosition: 'top', //标签的位置
lg: 8 //栅格布局份数
},
{
label: '保额',
key: 'sumInsured',
domType: 'Input',
inputType: 'number',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保费',
key: 'premium',
domType: 'Input',
inputType: 'number',
required: true,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '保障地区',
key: 'guaranteeRegion',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '货币',
key: 'currency',
domType: 'Select',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
dictType: 'bx_currency_type',
options: fetchDictData('bx_currency_type'),
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '等级',
key: 'insuranceType',
domType: 'Input',
inputType: 'text',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '自付额',
key: 'deductibles',
domType: 'Input',
inputType: 'number',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
lg: 8 //栅格布局份数
},
{
label: '附加保障',
key: 'additionalSafeguards',
domType: 'Input',
inputType: 'textarea',
required: false,
maxLength: 300,
disabled: false,
placeholder: '请输入',
show: true,
labelPosition: 'top', //标签的位置
labelWidth: '120px', //标签宽度
sm: 24, //栅格布局份数
lg: 24 //栅格布局份数
}
]
}
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.push(obj)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].push(obj)
processedProductData.value = processedData
}
const deleteChildren = (father, childIndex) => {
if (editStatus.value) {
proxy.$message.warning('编辑状态下才能删除')
return
}
const processedData = JSON.parse(JSON.stringify(processedProductData.value))
if (
props.idsObj.appointmentBizId &&
form.value[father.key][childIndex].additionalBizId &&
(props.pageSource == 'appointmentList' || props.pageSource == 'fnaList')
) {
delAdditional(form.value[father.key][childIndex].additionalBizId).then(res => {
if (res.code == 200) {
proxy.$message.success('附加险删除成功')
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].splice(childIndex, 1)
emit('handleSuccessEdit')
}
})
} else if (
props.idsObj.policyBizId &&
form.value[father.key][childIndex].id &&
props.pageSource == 'policyList'
) {
delPolicyAdditional(form.value[father.key][childIndex].id).then(res => {
if (res.code == 200) {
proxy.$message.success('附加险删除成功')
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].splice(childIndex, 1)
emit('policyEditSuccess')
}
})
} else {
for (const section of processedData) {
if (father.key == 'apiProductPlanAdditionalInfoDtoList' && section.key == father.key) {
section.data.splice(childIndex, 1)
}
}
//更新form表单对应的数据,以便收集填写的值
form.value[father.key].splice(childIndex, 1)
}
processedProductData.value = processedData
}
// 根据联动重置表单项的显示与否
const resetShow = (childKey, status) => {
console.log(childKey, status)
......@@ -1073,16 +949,32 @@ const submitForm = saveType => {
}
})
}
const anchorList = computed(() => {
let data = []
for (const section of processedProductData.value) {
if (section.showMoudle) {
data.push({ title: section.anchorKey, name: section.fatherTitle })
}
}
return data
})
// 因为tab嵌套了两层,所以需要监听父组件的tab否则锚点的显示就会有bug
watch(
() => props.fatherTabName,
newVal => {
if (newVal) {
productRef.value = null
}
}
)
watch(
() => props.activeName,
newVal => {
productRef.value = null
tempForm.value = { ...form.value }
if (newVal === 'productPlan') {
openList.value = false
setTimeout(() => {
processFormData()
}, 500)
processFormData()
}
}
)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment