Commit f59a3091 by yuzhenWang

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

Test

See merge request !73
parents 896b2ebf c7fa0242
......@@ -579,7 +579,7 @@ async function loadRemoteOptionsForInit(item) {
// ==================== 加载远程 API 选项(首次 focus 时加载,无搜索词) ====================
async function loadRemoteOptions(item) {
const { prop, api, requestParams, keywordField, debounceWait, ...rest } = item
if (!api || remoteOptions.value[prop]?.length > 0) return
if (!api ) return
try {
remoteLoading.value[prop] = true
......@@ -728,6 +728,43 @@ defineExpose({
})
localModel.value = { ...resetData }
nextTick(() => formRef.value?.clearValidate())
},
// ✅ 新增:强制刷新某个字段的远程选项
async refreshRemoteOptions(targetProp) {
console.log(`[SearchForm] 收到刷新请求: ${targetProp}`)
// 1. 查找配置项
const item = internalConfig.value.find(i => i.prop === targetProp)
if (!item) {
console.warn(`[SearchForm] 未找到 prop 为 ${targetProp} 的配置项`)
return
}
if (item.type !== 'select' || !item.api) {
console.warn(`[SearchForm] 字段 ${targetProp} 不是远程 Select 或没有 API`)
return
}
console.log(`[SearchForm] 开始强制加载 ${targetProp} 的数据,API: ${item.api}`)
// 2. 关键:在调用前,先清空旧数据,防止子组件内部的 "已加载则跳过" 逻辑生效
// 如果你的 loadRemoteOptions 里有 "if (remoteOptions.value[prop]?.length > 0) return"
// 这里必须先清空
remoteOptions.value[targetProp] = []
remoteLoading.value[targetProp] = true // 手动开启 loading
try {
// 3. 调用内部加载函数
// 注意:直接调用 loadRemoteOptions,它会读取最新的 requestParams
await loadRemoteOptions(item)
console.log(`[SearchForm] ${targetProp} 加载完成`)
} catch (error) {
console.error(`[SearchForm] ${targetProp} 加载失败`, error)
throw error
} finally {
remoteLoading.value[targetProp] = false
}
}
})
</script>
......
const fnaForm = [
// 介绍人信息
{
fatherTitle: '转介人信息',
keyType: 'Array',
key: 'brokerList',
anchorKey: 'brokerList',
moudleType: 'brokerList',
dataLength: 1,
showMoudle: true,
showTable: true,
addChildren: true,
addChildrenTxt: '转介人',
fatherRequired: false,
isOpen: false,
// 新增表格列配置
columns: [
{
label: '姓名',
prop: 'brokerName',
type: 'remoteSelect',
searchType: 'brokerName',
placeholder: '请输入关键词搜索',
required: false
},
{
label: '性别',
prop: 'brokerGender',
type: 'select',
dictType: 'sys_gender',
placeholder: '请选择',
required: false
},
{
label: '内部编号',
prop: 'brokerNumber',
type: 'input',
placeholder: '请输入',
required: false
},
{
label: '所属团队',
prop: 'brokerTeam',
type: 'remoteSelect',
searchType: 'brokerTeam',
placeholder: '请输入关键词搜索',
required: false
},
{
label: '分配比例',
prop: 'brokerRatio',
type: 'inputNumber',
placeholder: '请输入',
required: true
},
{
label: '备注',
prop: 'remark',
type: 'input',
placeholder: '请输入',
required: false
}
],
data: [
// {
// brokerName: '',
// brokerGender: '',
// brokerNumber: '',
// brokerTeam: '',
// brokerRatio: '',
// remark: ''
// }
]
},
// {
// fatherTitle: '转介人信息',
// keyType: 'Array',
// key: 'brokerList',
// anchorKey: 'brokerList',
// moudleType: 'brokerList',
// dataLength: 1,
// showMoudle: true,
// showTable: true,
// addChildren: true,
// addChildrenTxt: '转介人',
// fatherRequired: false,
// isOpen: false,
// // 新增表格列配置
// columns: [
// {
// label: '姓名',
// prop: 'brokerName',
// type: 'remoteSelect',
// searchType: 'brokerName',
// placeholder: '请输入关键词搜索',
// required: false
// },
// {
// label: '性别',
// prop: 'brokerGender',
// type: 'select',
// dictType: 'sys_gender',
// placeholder: '请选择',
// required: false
// },
// {
// label: '内部编号',
// prop: 'brokerNumber',
// type: 'input',
// placeholder: '请输入',
// required: false
// },
// {
// label: '所属团队',
// prop: 'brokerTeam',
// type: 'remoteSelect',
// searchType: 'brokerTeam',
// placeholder: '请输入关键词搜索',
// required: false
// },
// {
// label: '分配比例',
// prop: 'brokerRatio',
// type: 'inputNumber',
// placeholder: '请输入',
// required: true
// },
// {
// label: '备注',
// prop: 'remark',
// type: 'input',
// placeholder: '请输入',
// required: false
// }
// ],
// data: [
// // {
// // brokerName: '',
// // brokerGender: '',
// // brokerNumber: '',
// // brokerTeam: '',
// // brokerRatio: '',
// // remark: ''
// // }
// ]
// },
// 受供养人信息
{
fatherTitle: '受供养人信息',
......
......@@ -9,6 +9,20 @@ const productPlan = [
fatherRequired: true, //父级必填,代表个人资料这个模块有必填项
data: [
{
label: '出单经纪公司',
key: 'reconciliationCompanyName',
domType: 'SearchSelect',
required: false,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
labelPosition: 'top', //标签的位置
lg: 8 //栅格布局份数
},
{
label: '保险公司',
key: 'companyName',
domType: 'SearchSelect',
......@@ -253,20 +267,6 @@ const productPlan = [
lg: 8 //栅格布局份数
},
{
label: '出单经纪公司',
key: 'reconciliationCompanyName',
domType: 'SearchSelect',
required: false,
maxLength: 30,
disabled: false,
placeholder: '请输入',
show: true,
labelWidth: '120px', //标签宽度
sm: 12, //栅格布局份数
labelPosition: 'top', //标签的位置
lg: 8 //栅格布局份数
},
{
label: '保单额度(重疾)',
key: 'sumInsured',
domType: 'Input',
......
import { ElMessage } from 'element-plus'
export function copyToClipboard(text) {
// 方案1:使用现代 Clipboard API
if (navigator.clipboard && navigator.clipboard.writeText) {
return navigator.clipboard.writeText(text).catch((err) => {
console.error('Clipboard API 写入失败:', err);
ElMessage.error('复制失败')
// 降级到传统方案
fallbackCopyText(text);
});
}
// 方案2:降级使用传统方法
else {
fallbackCopyText(text);
}
}
// 传统复制方法
function fallbackCopyText(text, typeName = '内容') {
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
try {
textarea.select();
textarea.setSelectionRange(0, 99999); // 对于移动设备
document.execCommand('copy');
console.log('传统方法复制成功');
ElMessage.success(`${typeName}已复制`)
} catch (err) {
console.error('传统方法复制失败:', err)
ElMessage.error('复制失败');
} finally {
document.body.removeChild(textarea);
}
}
export default {
copyToClipboard
}
......@@ -615,10 +615,10 @@ const addCheckRecordConfig = ref([
prop: 'exchangeRate',
label: '结算汇率(实)',
inputType: 'decimal',
decimalDigits: 2,
decimalDigits: 4,
rules: [
{ required: true, message: '请输入金额', trigger: 'blur' },
{ pattern: /^\d+(\.\d{1,2})?$/, message: '最多两位小数', trigger: 'blur' }
{ pattern: /^\d+(\.\d{1,4})?$/, message: '最多四位小数', trigger: 'blur' }
]
},
])
......
......@@ -215,23 +215,24 @@ const detailDialogVisible = ref(false)
// 应付明细列表
const payableReportListTableColumns = ref([
{ prop: 'fortuneBizType', label: '应付款类型', sortable: true, width: '120', formatter: (row) => getFortuneBizTypeLabel(row.fortuneBizType) || '-' },
{ prop: 'payableNo', label: '应付账款编号', sortable: true, width: '120', formatter: (row) => row.payableNo || '-' },
{ prop: 'policyNo', label: '保单号', sortable: true, width: '120', formatter: (row) => row.policyNo || '-' },
// { prop: 'fortuneBizType', label: '应付款类型', sortable: true, width: '120', formatter: (row) => getFortuneBizTypeLabel(row.fortuneBizType) || '-' },
// { prop: 'payableNo', label: '应付账款编号', sortable: true, width: '120', formatter: (row) => row.payableNo || '-' },
{ prop: 'policyNo', label: '保单号', sortable: true, width: '130', formatter: (row) => row.policyNo || '-' },
{ prop: 'broker', label: '转介人', sortable: true, width: '120', formatter: (row) => row.broker || '-' },
{ prop: 'fortuneName', label: '出账项目', sortable: true, width: '120', formatter: (row) => row.fortuneName || '-' },
{ prop: 'status', label: '出账状态', sortable: true, width: '120', formatter: (row) => getDictLabel('csf_expected_fortune_status', row.status) || '-' },
{ prop: 'currency', label: '出账币种', sortable: true, width: '120', formatter: (row) => row.currency || '-' },
{ prop: 'fortunePeriod', label: '出账期数', sortable: true, width: '120', formatter: (row) => row.fortunePeriod || '-' },
{ prop: 'fortuneTotalPeriod', label: '出账总期数', sortable: true, width: '120', formatter: (row) => row.fortuneTotalPeriod || '-' },
{ prop: 'currency', label: '出账币种', sortable: true, width: '100', formatter: (row) => row.currency || '-' },
{ prop: 'fortunePeriod', label: '出账期数', sortable: true, width: '100', formatter: (row) => row.fortunePeriod || '-' },
{ prop: 'fortuneTotalPeriod', label: '出账总期数', sortable: true, width: '100', formatter: (row) => row.fortuneTotalPeriod || '-' },
{ prop: 'payoutDate', label: '出账日(估)', sortable: true, width: '120', formatter: (row) => row.payoutDate || '-' },
{ prop: 'actualPayoutDate', label: '出账日(实)', sortable: true, width: '120', formatter: (row) => row.actualPayoutDate || '-' },
{ prop: 'commissionRatio', label: '出账比例', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) + '%' || '-' },
{ prop: 'amount', label: '应出账金额(估)', sortable: true, width: '120', formatter: (row) => formatCurrency(row.amount || 0) },
{ prop: 'commissionRatio', label: '发佣率(对应职级)', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) + '%' || '-' },
{ prop: 'hkdAmount', label: '应出账金额(估)', sortable: true, width: '120', formatter: (row) => formatCurrency(row.hkdAmount || 0) },
{ prop: 'paidRatio', label: '已出账比例', sortable: true, width: '120', formatter: (row) => (row.paidRatio || 0) + '%' || '-' },
{ prop: 'paidAmount', label: '已出账金额', sortable: true, width: '120', formatter: (row) => formatCurrency(row.paidAmount || 0) },
{ prop: 'unpaidRatio', label: '待出账比例', sortable: true, width: '120', formatter: (row) => (row.unpaidRatio || 0) + '%' || '-' },
{ prop: 'unpaidAmount', label: '待出账金额(估)', sortable: true, width: '120', formatter: (row) => formatCurrency(row.unpaidAmount || 0) },
{ prop: 'brokerRatio', label: '持有比例', sortable: true, width: '120', formatter: (row) => (row.brokerRatio || 0) + '%' || '-' },
{ prop: 'brokerRatio', label: '持有比例', sortable: true, width: '100', formatter: (row) => (row.brokerRatio || 0) + '%' || '-' },
{ prop: 'premium', label: '期交保费', sortable: true, width: '120', formatter: (row) => formatCurrency(row.premium || 0) },
{ prop: 'insuranceCompany', label: '保险公司', sortable: true, width: '120', formatter: (row) => row.insuranceCompany || '-' },
{ prop: 'productName', label: '产品计划', sortable: true, width: '120', formatter: (row) => row.productName || '-' },
......
......@@ -32,7 +32,7 @@
<!-- 应收款管理列表 -->
<el-table :data="tableData" height="400" border highlight-current-row style="width: 100%"
v-loading="loading">
<el-table-column v-for="(column, index) in receivableReportTableColumns" :key="index"
<el-table-column v-for="(column, index) in receivableReportTableColumns" :key="index" :fixed="column.fixed"
:prop="column.prop" :label="column.label" :width="column.width" :sortable="column.sortable"
:formatter="column.formatter" />
<el-table-column fixed="right" label="操作" min-width="120">
......@@ -106,7 +106,7 @@
</div>
<el-table :data="receivableReportTableData" border style="width: 100%;margin-bottom: 10px;min-height: 300px;">
<el-table-column v-for="item in receivableReportItemTableColumns" :key="item.property" :prop="item.prop"
:label="item.label" :width="item.width" />
:label="item.label" :width="item.width" :formatter="item.formatter" />
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="{ row }">
<el-popover placement="right" :width="200" trigger="click">
......@@ -744,27 +744,27 @@ onMounted(async () => {
}
})
// 格式化函数(每次渲染都会调用,所以能拿到最新字典)
const formatStatus = (row, column) => {
const formatStatus = (row,column) => {
return getDictLabel('csf_expected_commission_status', row.status) // 实时查缓存
}
const detailDialogVisible = ref(false)
const receivableReportTableData = ref([])
const receivableReportTableColumns = ref([
{ prop: 'policyNo', label: '保单号', sortable: true, width: '150', formatter: (row) => row.policyNo || '-' },
{ prop: 'policyNo', label: '保单号', sortable: true, width: '150',fixed:'left', formatter: (row) => row.policyNo || '-' },
{ prop: 'reconciliationCompany', label: '对账公司', sortable: true, width: '150', formatter: (row) => row.reconciliationCompany || '-' },
{ prop: 'commissionPeriod', label: '入账期数', sortable: true, width: '120', formatter: (row) => row.commissionPeriod || '-' },
{ prop: 'totalPeriod', label: '入账总期数', sortable: true, width: '120', formatter: (row) => row.totalPeriod || '-' },
{ prop: 'commissionDate', label: '入账日(估)', sortable: true, width: '130', },
{ prop: 'commissionRatio', label: '预估入账比例', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) + '%' || '-' },
{ prop: 'commissionRatio', label: '产品对应来佣率', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) + '%' || '-' },
{ prop: 'hkdAmount', label: '预估入账金额HKD', sortable: true, width: '120', formatter: (row) => formatCurrency(row.hkdAmount || 0) },
{ prop: 'paidRatio', label: '已入账比例', sortable: true, width: '120', formatter: (row) => (row.paidRatio || 0) + '%' || '-' },
{ prop: 'paidAmount', label: '已入账金额HKD', sortable: true, width: '120', formatter: (row) => formatCurrency(row.paidAmount || 0) },
{ prop: 'unpaidRatio', label: '待入账比例', sortable: true, width: '120', formatter: (row) => (row.unpaidRatio || 0) + '%' || '-' },
{ prop: 'unpaidAmount', label: '待入账金额HKD', sortable: true, width: '120', formatter: (row) => formatCurrency(row.unpaidAmount || 0) },
{ prop: 'exchangeRate', label: '结算汇率(估)', sortable: true, width: '120', formatter: (row) => formatCurrency(row.exchangeRate || 0) },
{ prop: 'exchangeRate', label: '结算汇率(估)', sortable: true, width: '120'},
{ prop: 'insuranceCompany', label: '保险公司', sortable: true, width: '120', formatter: (row) => row.insuranceCompany || '-' },
{ prop: 'productName', label: '产品计划', sortable: true, width: '120', formatter: (row) => row.productName || '-' },
{ prop: 'premium', label: '期交保费', sortable: true, width: '120', formatter: (row) => row.productName || '-' },
{ prop: 'premium', label: '期交保费', sortable: true, width: '120', formatter: (row) => row.premium || '-' },
{ prop: 'policyCurrency', label: '保单币种', sortable: true, width: '120', formatter: (row) => row.policyCurrency || '-' },
])
const receivableReportItemTableColumns = ref([
......@@ -772,18 +772,18 @@ const receivableReportItemTableColumns = ref([
{ prop: 'receivableNo', label: '应收款编号', sortable: true, width: '150', formatter: (row) => row.receivableNo || '-' },
{ prop: 'policyNo', label: '保单号', sortable: true, width: '150', formatter: (row) => row.policyNo || '-' },
{ prop: 'reconciliationCompany', label: '对账公司', sortable: true, width: '150', formatter: (row) => row.reconciliationCompany || '-' },
{ prop: 'status', label: '入账状态', sortable: true, width: '120', formatter: (row) => formatStatus(row.status) || '-' },
{ prop: 'status', label: '入账状态', sortable: true, width: '120', formatter: (row) => formatStatus(row) || '-' },
{ prop: 'commissionPeriod', label: '入账期数', sortable: true, width: '120', formatter: (row) => row.commissionPeriod || '-' },
{ prop: 'totalPeriod', label: '入账总期数', sortable: true, width: '120', formatter: (row) => row.totalPeriod || '-' },
{ prop: 'commissionName', label: '入账项目', sortable: true, width: '130', formatter: (row) => row.commissionName || '-' },
{ prop: 'commissionDate', label: '入账日(估)', sortable: true, width: '130', formatter: (row) => row.commissionDate || '-' },
{ prop: 'commissionRatio', label: '预估入账比例', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) + '%' || '-' },
{ prop: 'commissionRatio', label: '产品对应来佣率', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) + '%' || '-' },
{ prop: 'expectedAmount', label: '预估入账金额', sortable: true, width: '120', formatter: (row) => formatCurrency(row.expectedAmount || 0) },
{ prop: 'paidRatio', label: '已入账比例', sortable: true, width: '120', formatter: (row) => (row.paidRatio || 0) + '%' || '-' },
{ prop: 'paidAmount', label: '已入账金额', sortable: true, width: '120', formatter: (row) => formatCurrency(row.paidAmount || 0) },
{ prop: 'pendingRatio', label: '待入账比例', sortable: true, width: '120', formatter: (row) => (row.pendingRatio || 0) + '%' || '-' },
{ prop: 'pendingAmount', label: '待入账金额', sortable: true, width: '120', formatter: (row) => formatCurrency(row.pendingAmount || 0) },
{ prop: 'defaultExchangeRate', label: '结算汇率(估)', sortable: true, width: '120', formatter: (row) => formatCurrency(row.defaultExchangeRate || 0) },
{ prop: 'defaultExchangeRate', label: '结算汇率(估)', sortable: true, width: '120'},
{ prop: 'insuranceCompany', label: '保险公司', sortable: true, width: '120', formatter: (row) => row.insuranceCompany || '-' },
{ prop: 'productName', label: '产品计划', sortable: true, width: '120', formatter: (row) => row.productName || '-' },
{ prop: 'premium', label: '期交保费', sortable: true, width: '120', formatter: (row) => formatCurrency(row.premium || 0) },
......
......@@ -446,7 +446,7 @@ const searchSelectList = async (query, fieldKey, row) => {
const params5 = {
pageNo: 1,
pageSize: 10,
queryContent: queryString
realName: queryString
}
const response5 = await getUserSaleExpandList(params5)
if (response5.code == 200) {
......
......@@ -75,9 +75,21 @@
border
max-height="380px"
>
<el-table-column type="index" width="60" label="序号" />
<el-table-column label="客户姓名" align="center" prop="customerName" width="100" />
<el-table-column label="中文姓名" align="center" prop="customerNameCn" width="100" />
<el-table-column type="index" width="100" label="序号" />
<el-table-column label="客户姓名" align="center" prop="customerName" width="180" >
<template #default="scope">
<el-button link size="default">
<span @click="copyToClipboard(scope.row.customerName,'客户姓名')">{{ scope.row.customerName }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="中文姓名" align="center" prop="customerNameCn" width="180" >
<template #default="scope">
<el-button link size="default">
<span @click="copyToClipboard(scope.row.customerNameCn,'中文姓名')">{{ scope.row.customerNameCn }}</span>
</el-button>
</template>
</el-table-column>
<!-- <el-table-column label="状态" align="center" prop="status" width="100" :formatter="getDictLabel('csf_fna_status')"/> -->
<el-table-column label="流程状态" sortable align="center" prop="status" width="200">
<template #default="scope">
......@@ -88,18 +100,29 @@
label="流程编号"
align="center"
prop="fnaNo"
width="200"
show-overflow-tooltip
/>
width="240"
show-overflow-tooltip>
<template #default="scope">
<el-button link size="default">
<span @click="copyToClipboard(scope.row.fnaNo,'流程编号')">{{ scope.row.fnaNo }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column
label="预约编号"
align="center"
prop="appointmentNo"
width="200"
width="240"
show-overflow-tooltip
/>
<el-table-column label="新单编号" align="center" prop="policyId" />
<el-table-column label="保单号" align="center" prop="policyNo" width="150" />
>
<template #default="scope">
<el-button link size="default">
<span @click="copyToClipboard(scope.row.appointmentNo,'预约编号')">{{ scope.row.appointmentNo }}</span>
</el-button>
</template>
</el-table-column>
<!-- <el-table-column label="新单编号" align="center" prop="policyId" /> -->
<el-table-column label="保单号" align="center" prop="policyNo" width="180" />
<el-table-column label="创建时间" sortable align="center" prop="createTime" width="200">
<template #default="scope">
......@@ -107,7 +130,7 @@
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="80" align="center">
<el-table-column fixed="right" label="操作" width="150" align="center">
<template #default="{ row }">
<el-popover placement="left" :width="160" trigger="click">
<template #reference>
......@@ -158,6 +181,7 @@ import { getFnaList, deleteFna, subProcess } from '@/api/sign/fna'
import useUserStore from '@/store/modules/user'
import { MoreFilled, InfoFilled } from '@element-plus/icons-vue'
import useDictStore from '@/store/modules/dict'
import copyToClipboard from '@/utils/copyToClipboard';
const dictStore = useDictStore()
const userStore = useUserStore()
const router = useRouter()
......
......@@ -70,7 +70,13 @@
prop="appointmentNo"
width="200"
fixed="left"
/>
>
<template #default="scope">
<el-button link size="default">
<span @click="copyToClipboard(scope.row.appointmentNo,'预约编号')">{{ scope.row.appointmentNo }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column label="预约状态" align="center" prop="status" fixed="left" width="100">
<template #default="scope">
<dict-tag :options="csf_ap_status" :value="scope.row.status" />
......@@ -94,16 +100,11 @@
<el-table-column label="投保人" align="center" prop="policyholder" width="150" />
<el-table-column label="受保人" align="center" prop="insurant" width="150" />
<!-- <el-table-column label="供款频率" align="center" prop="paymentFrequency" width="100">
<!-- <el-table-column label="供款频率" align="center" width="150" prop="paymentFrequency">
<template #default="scope">
<dict-tag :options="csf_ap_frequency" :value="scope.row.paymentFrequency" />
</template>
</el-table-column> -->
<el-table-column label="供款频率" align="center" width="150" prop="paymentFrequency">
<template #default="scope">
<dict-tag :options="csf_ap_frequency" :value="scope.row.paymentFrequency" />
</template>
</el-table-column>
<el-table-column label="供款期数" align="center" prop="paymentTerm" width="100" />
<el-table-column label="每期保费" align="center" prop="eachIssuePremium" width="100" />
......@@ -212,6 +213,7 @@ import {
getItineraryExprot
} from '@/api/sign/appointment'
import useUserStore from '@/store/modules/user'
import {copyToClipboard} from '@/utils/copyToClipboard'
const dictStore = useDictStore()
const userStore = useUserStore()
const router = useRouter()
......@@ -270,7 +272,7 @@ const { bx_currency_type, csf_ap_status, csf_ap_meeting_point, csf_ap_frequency
const baseDropdownItems = [
{ label: '修改', value: 'edit', confirm: '' },
{
label: '生成行程单',
label: '确认生成行程单',
value: 'viewItinerary',
confirm: '',
// 只有当 row.status == 1 时才显示
......
......@@ -593,8 +593,6 @@ const remittanceConfig = [
validator: (rule, value, callback) => {
if (value === '' || value == null) {
callback(new Error('请输入付款金额'))
} else if (!/^\d+$/.test(String(value))) {
callback(new Error('只能输入正整数'))
} else {
callback()
}
......@@ -636,7 +634,7 @@ const remittanceConfig = [
label: '付款银行',
api: '/base/api/bank/page',
keywordField: 'policyNo',
requestParams: { pageNo: 1, pageSize: 20 },
requestParams: { pageNo: 1, pageSize: 50 },
debounceWait: 500, // 自定义防抖时间
valueKey: 'bankBizId',
......
<template>
<div>
<CommonPage :operationBtnList='operationBtnList' :visibleDefaultButtons="visibleDefaultButtons"
<CommonPage :operationBtnList='operationBtnList' :visibleDefaultButtons="visibleDefaultButtons" v-loading.fullscreen.lock="statusLoading"
:showSearchForm='true' :show-pagination='true' :total='pageTotal' :current-page='currentPage'
:page-size='pageSize' @size-change='handleSizeChange' @current-change='handleCurrentChange'>
<!-- 搜索区域 -->
......@@ -69,7 +69,7 @@
<!-- 查看详情、更新数据 -->
<CommonDialog :dialogTitle='mode === "viewDetail" ? "查看详情" : "更新数据"' dialogWidth='80%'
:openDialog=viewDetailDialogFlag :showAction='false' :showClose='true' @close='viewDetailDialogFlag = false'
:openDialog=viewDetailDialogFlag :showAction='false' :showClose='true' @close='viewDetailDialogFlag=false'
@confirm='handleUpdateSubmit'>
<PolicyDetail v-model="policyDetailFormData" :policyBizId="selectedRow.policyBizId" :mode="mode"
ref="policyDetailFormRef" @submit="onSubmit" @cancel="viewDetailDialogFlag = false"
......@@ -82,7 +82,7 @@
<script setup>
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import CommonPage from '@/components/commonPage'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import CommonDialog from '@/components/commonDialog'
......@@ -94,9 +94,9 @@ import {
getExpectedCommissionList,
changePolicyStatus,
policyFollowReport,
saveMailingInfo, updatePolicyfollow, batchSaveBrokers, saveInitialPayment
saveMailingInfo, updatePolicyfollow, batchSaveBrokers, saveInitialPayment,updatePolicyProduct
} from '@/api/sign/underwritingMain'
import {copyToClipboard} from '@/utils/copyToClipboard'
import PolicyDetail from './policyDetail.vue'
const policyDetailFormRef = ref(null)
const policyDetailFormData = ref({})
......@@ -106,11 +106,13 @@ const currentPage = ref(1)
const pageSize = ref(10)
const pageTotal = ref(0)
const loading = ref(false)
const statusLoading = ref(false)
// 搜索表单数据
const searchFormData = reactive({})
const selectedRow = ref(null)
// 弹窗相关
const editStatusDialogFlag = ref(false)
// 修改状态
const editStatusFormData = ref({})
const editStatusFormRef = ref(null)
......@@ -139,6 +141,7 @@ const viewRelatedDetail = (row) => {
}
// 提交修改状态
const handleEditStatusSubmit = async () => {
statusLoading.value = true;
try {
await editStatusFormRef.value.validate()
const res = await changePolicyStatus({
......@@ -146,13 +149,16 @@ const handleEditStatusSubmit = async () => {
...editStatusFormData.value
})
if (res.code === 200) {
statusLoading.value = false;
ElMessage.success('修改状态成功')
editStatusDialogFlag.value = false
loadTableData()
} else {
statusLoading.value = false;
ElMessage.error(res.msg || '修改状态失败')
}
} catch (error) {
statusLoading.value = false;
console.error('修改状态失败', error)
}
}
......@@ -177,7 +183,7 @@ const onSubmit = async (data) => {
} else {
ElMessage.error(res.msg || '保存邮寄信息失败')
}
} else if (data.activeTab === 'basic' || data.activeTab === 'productPlan') {
} else if (data.activeTab === 'basic') {
params = {
policyBizId: selectedRow.value.policyBizId,
...data,
......@@ -186,10 +192,25 @@ const onSubmit = async (data) => {
const res = await updatePolicyfollow(params)
if (res.code === 200) {
ElMessage.success(data.activeTab === 'basic' ? '保存基本信息成功' : '保存产品计划成功')
loadTableData()
// viewDetailDialogFlag.value = false
} else {
ElMessage.error(res.msg || (data.activeTab === 'basic' ? '保存基本信息失败' : '保存产品计划失败'))
}
} else if (data.activeTab === 'productPlan') {
params = {
policyBizId: selectedRow.value.policyBizId,
...data,
activeTab: undefined
}
const res = await updatePolicyProduct(params)
if (res.code === 200) {
ElMessage.success('保存产品计划成功')
loadTableData()
// viewDetailDialogFlag.value = false
} else {
ElMessage.error(res.msg || ('保存产品计划失败'))
}
} else if (data.activeTab === 'introducer') {
params = {
policyBizId: selectedRow.value.policyBizId,
......@@ -433,7 +454,9 @@ const handleSelect = async (e, row) => {
}
editStatusDialogFlag.value = true
editStatusFormData.value = {
status: row.status
status: row.status,
effectiveDate:row.effectiveDate,
underwritingDate:row.underwritingDate
}
break
case 'viewRelated':
......
......@@ -6,7 +6,7 @@
<el-tabs v-model="activeTab" @tab-click="handleTabClick" :before-leave="handleBeforeLeave">
<el-tab-pane label="基础信息" name="basic"></el-tab-pane>
<el-tab-pane label="产品计划" name="productPlan"></el-tab-pane>
<el-tab-pane label="首期缴费" name="firstPayment"></el-tab-pane>
<!-- <el-tab-pane label="首期缴费" name="firstPayment"></el-tab-pane> -->
<el-tab-pane label="介绍人" name="introducer"></el-tab-pane>
<el-tab-pane label="邮寄信息" name="postal"></el-tab-pane>
<el-tab-pane label="关联记录" name="related"></el-tab-pane>
......@@ -51,7 +51,7 @@
</div>
<!-- 附加计划(可编辑表格) -->
<div class="section">
<!-- <div class="section">
<h3 class="sectionTitle">附加计划</h3>
<EditableTable
v-model="localData.additionalPlans"
......@@ -59,11 +59,10 @@
@batch-save="handleBatchSave"
:disabled="props.mode === 'viewDetail'"
/>
</div>
</div> -->
</div>
<!-- 首期缴费 Tab 内容 -->
<div v-else-if="activeTab === 'firstPayment'" class="tab-content">
<!-- 签单信息 -->
<div class="section">
<h3 class="sectionTitle">缴费信息</h3>
<SearchForm
......@@ -280,14 +279,14 @@ const introducerConfig = [
label: '转介人',
api: '/insurance/base/api/userSaleExpand/page',
keywordField: 'realName',
requestParams: { pageNo: 1, pageSize: 20 },
requestParams: { pageNo: 1, pageSize: 500 },
placeholder: '输入转介人名称搜索',
debounceWait: 500, // 自定义防抖时间
onChangeExtraFields: {
broker: 'realName', // 选中后自动填 broker = raw.realName
brokerName: 'realName',
internalCode: 'code',
team: 'teamName',
internalCode: 'internalNumber',
team: 'deptName',
phone: 'phone'
},
transform: res => {
......@@ -298,7 +297,13 @@ const introducerConfig = [
}))
}
},
{
type: 'input',
prop: 'brokerName',
label: '转介人姓名',
span: 4,
disabled: true
},
// {
// type: 'select',
// prop: 'gender',
......@@ -480,6 +485,53 @@ const policyInfoFormConfig = ref([
prop: 'policyNo',
label: '保单号'
},
{
type: 'select',
prop: 'reconciliationCompanyBizId',
label: '出单经纪公司',
api: '/insurance/base/api/insuranceReconciliationCompany/page',
keywordField: 'queryContent',
requestParams: { pageNo: 1, pageSize: 500 },
placeholder: '输入公司名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'reconciliationCompanyBizId',
labelKey: 'name',
transform: res => {
return res?.data.records || []
},
onChangeExtraFields: {
reconciliationCompany: 'name',
reconciliationCode:'code',
},
rules: [{ required: true, message: '请选择出单经纪公司', trigger: 'blur' }],
},
{
type: 'input',
prop: 'coolingOffDays',
label: '冷静期(天)',
inputType: 'decimal',
rules: [{ pattern: /^\d+$/, message: '只能输入正整数', trigger: 'blur' }]
},
{
type: 'date',
prop: 'coolingOffEndDate',
label: '冷静期结束日期'
},
{
type: 'date',
prop: 'latestPaymentDate',
label: '最晚缴费日'
},
{
type: 'select',
prop: 'policyTpye',
label: '保单类型',
options:[
{label:'电子保单',value:'1'},
{label:'纸质保单',value:'2'}
]
},
{
type: 'date',
prop: 'effectiveDate',
......@@ -567,11 +619,11 @@ const basicPlanFormConfig = ref([
{
type: 'select',
prop: 'productCate',
label: '保险险种',
label: '保险种类',
api: '/insurance/base/api/insuranceCategory/page',
keywordField: 'name',
requestParams: { pageNo: 1, pageSize: 20 },
placeholder: '输入保险险种名称搜索',
placeholder: '输入保险种类名称搜索',
debounceWait: 500, // 自定义防抖时间
valueKey: 'insuranceCategoryBizId',
labelKey: 'name',
......@@ -604,7 +656,7 @@ const basicPlanFormConfig = ref([
valueKey: 'productName',
labelKey: 'productName',
transform: res => {
console.log('======子组件选择选项后,父组件接收的值 :', res?.data.records || [])
console.log('======子组件选择选项后,父组件接收的值产品名称:', res?.data.records || [])
return res?.data.records || []
},
onChangeExtraFields: {
......@@ -622,6 +674,12 @@ const basicPlanFormConfig = ref([
},
{
type: 'input',
prop: 'issueNumber',
label: '供款期数',
inputType: 'decimal'
},
{
type: 'input',
prop: 'guaranteePeriod',
label: '保障期限'
},
......@@ -631,12 +689,6 @@ const basicPlanFormConfig = ref([
label: '保额(重疾险)'
},
{
type: 'input',
prop: 'issueNumber',
label: '供款期数',
inputType: 'decimal'
},
{
type: 'select',
prop: 'policyCurrency',
label: '保单币种',
......@@ -648,7 +700,6 @@ const basicPlanFormConfig = ref([
label: '每期保费',
inputType: 'decimal',
decimalDigits: 2,
visible: formData => formData.commissionBizType == 'R',
rules: [
{ required: true, message: '请输入金额', trigger: 'blur' },
{ pattern: /^\d+(\.\d{1,2})?$/, message: '最多两位小数', trigger: 'blur' }
......@@ -660,7 +711,6 @@ const basicPlanFormConfig = ref([
label: '保单征费',
inputType: 'decimal',
decimalDigits: 2,
visible: formData => formData.commissionBizType == 'R',
rules: [
{ required: true, message: '请输入金额', trigger: 'blur' },
{ pattern: /^\d+(\.\d{1,2})?$/, message: '最多两位小数', trigger: 'blur' }
......@@ -673,6 +723,13 @@ const basicPlanFormConfig = ref([
dictType: 'sys_no_yes'
},
{
type: 'input',
prop: 'prepaymentPeriod',
label: '预缴年期',
inputType: 'decimal',
visible: formData => formData.isPrepay == '1'
},
{
type: 'select',
prop: 'isTraceable',
label: '是否追溯',
......@@ -681,7 +738,8 @@ const basicPlanFormConfig = ref([
{
type: 'date',
prop: 'retroactiveDate',
label: '回溯日期'
label: '回溯日期',
visible: formData => formData.isTraceable == '1'
},
{
type: 'select',
......@@ -1153,21 +1211,47 @@ const viewRecordDetail = e => {
})
}
const handleSelectChange = async (prop, value, item, type) => {
await nextTick()
// console.log('======子组件选择选项后,父组件接收的值 :', basicPlanFormData.value)
console.log('🔔 父组件收到 selectChange:', prop, value, type)
await nextTick() // 确保 DOM 和响应式数据更新
if (type === 'basicPlan') {
const params = {
tenantBizId: userStore.projectInfo.tenantBizId,
projectBizId: userStore.projectInfo.projectBizId,
fieldBizId: 'field_olk1qZe81qHHKXbw',
fieldValueBizId: 'field_value_uOfJH5ucA2YwJpbn',
insuranceCompanyBizIdList: [basicPlanFormData.value.insuranceCompanyBizId],
categoryCodeList: [basicPlanFormData.value.insuranceCategoryCode],
pageNo: 1,
pageSize: 100
// 只有当改变的是“保险公司”时,才刷新“产品名称”
if (prop === 'insuranceCompanyBizId') {
console.log('🔄 检测到保险公司变更,准备刷新产品列表...')
// 1. 检查 Ref 是否存在
if (!basicPlanFormRef.value) {
console.error('❌ basicPlanFormRef 为空,无法调用方法')
return
}
// 2. 检查方法是否存在
if (typeof basicPlanFormRef.value.refreshRemoteOptions !== 'function') {
console.error('❌ refreshRemoteOptions 方法未暴露或不存在')
console.log('当前暴露的方法:', Object.keys(basicPlanFormRef.value))
return
}
try {
// 3. 可选:先清空产品字段的值,避免选中了旧公司的产品
basicPlanFormData.value.productName = ''
basicPlanFormData.value.productLaunchBizId = ''
basicPlanFormData.value.insuranceCategoryCode = '' // 如果分类也依赖公司,可能也要清空
console.log('🚀 正在调用子组件 refreshRemoteOptions...')
// 4. 调用刷新
await basicPlanFormRef.value.refreshRemoteOptions('productName')
console.log('✅ 产品列表刷新指令执行完毕')
// ElMessage.success('产品列表已更新')
} catch (err) {
console.error('💥 刷新产品列表出错:', err)
ElMessage.error('产品列表更新失败,请重试')
}
}
console.log('====父组件拿到值,去调用产品列表查询接口', params)
getProductLists(params)
}
}
......
......@@ -5,7 +5,7 @@
<el-col :sm="12" :lg="12" :xs="24">
<div class="headerLeft">
<div class="top">欢迎!</div>
<div class="bottom">王力群</div>
<div class="bottom">CSF-HK</div>
</div>
</el-col>
<el-col :sm="12" :lg="12" :xs="24" class="right">
......@@ -180,14 +180,14 @@ const headerList = ref([
id: '1',
title: '总保费(HKD)',
icon: 'icon-zongbaofei',
count: '392.52',
count: '--',
url: '/todo'
},
{
id: '2',
title: '有效保单数',
icon: 'icon-youxiaobaodan',
count: '0.00',
count: '--',
url: '/todo'
},
......@@ -195,7 +195,7 @@ const headerList = ref([
id: '3',
title: '待来佣保单',
icon: 'icon-daijiesuan',
count: '10',
count: '--',
url: '/todo'
}
])
......@@ -275,7 +275,7 @@ const staticList = ref([
id: '1',
title: '财务需求分析数',
icon: 'icon-xiexian',
count: '3735',
count: '--',
unit: '条',
url: '/todo',
color: '#F53F3F'
......@@ -284,7 +284,7 @@ const staticList = ref([
id: '2',
title: '预约单数',
icon: 'icon-xiexian',
count: '12',
count: '--',
unit: '单',
url: '/todo',
color: '#0FC6C2'
......@@ -293,7 +293,7 @@ const staticList = ref([
id: '3',
title: '新单数',
icon: 'icon-xiexian',
count: '12',
count: '--',
unit: '单',
url: '/todo',
color: '#165DFF'
......@@ -302,7 +302,7 @@ const staticList = ref([
id: '4',
title: '续期保单数',
icon: 'icon-xiexian',
count: '13',
count: '--',
unit: '份',
url: '/todo',
color: '#0FC6C2'
......@@ -312,22 +312,22 @@ const infoList = ref([
{
id: '1',
title: '产品优惠',
subTitle: 'XXXXX第四季度优惠政策'
subTitle: '暂未开放'
},
{
id: '2',
title: '产品培训',
subTitle: 'XXXXX产品培训回放'
subTitle: '暂未开放'
},
{
id: '3',
title: '重要通知',
subTitle: 'XXXXX保单未续费'
subTitle: '暂未开放'
},
{
id: '4',
title: '系统消息',
subTitle: 'FNA导出成功!'
subTitle: '暂未开放!'
}
])
const timeList = ref([
......@@ -351,21 +351,21 @@ const workList = ref([
{
id: '1',
title: '新单跟进',
subTitle: '张三预约单待录入',
subTitle: '暂未开放',
unit: 'Q',
color: '#7BC616'
},
{
id: '2',
title: '续费提醒',
subTitle: 'bug fix',
subTitle: '暂未开放',
unit: 'Y',
color: '#14C9C9'
},
{
id: '3',
title: '预约单生成',
subTitle: '车险预约单已生成',
subTitle: '暂未开放',
unit: 'N',
color: '#168CFF'
}
......
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