Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-csf-front
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
yuzhenWang
yd-csf-front
Commits
d4982277
Commit
d4982277
authored
Jan 12, 2026
by
yuzhenWang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'test' into 'feature-20250827wyz-写业务'
Test See merge request
!38
parents
92304c31
10d9b14a
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1269 additions
and
1073 deletions
+1269
-1073
src/api/financial/commission.js
+9
-0
src/components/SearchForm/SearchForm.vue
+122
-29
src/views/financialCenter/financialBilling.vue
+24
-19
src/views/financialCenter/financialIncome.vue
+86
-50
src/views/financialCenter/payables.vue
+47
-23
src/views/financialCenter/receivables.vue
+3
-3
src/views/sign/underwritingMain/index.vue
+362
-948
src/views/sign/underwritingMain/policyDetail.vue
+615
-0
src/views/workbench/index.vue
+1
-1
No files found.
src/api/financial/commission.js
View file @
d4982277
...
...
@@ -403,3 +403,12 @@ export function updatePayRecord(data){
data
:
data
})
}
// 应付款导出
export
function
exportPayRecord
(
data
)
{
return
request
({
url
:
'/csf/api/expectedFortune/export'
,
method
:
'post'
,
data
:
data
,
responseType
:
'blob'
})
}
src/components/SearchForm/SearchForm.vue
View file @
d4982277
<
template
>
<el-form
ref=
"formRef"
:model=
"localModel"
:rules=
"formRules"
label-width=
"auto"
v-bind=
"$attrs"
:validate-on-rule-change=
"false"
>
<el-form
ref=
"formRef"
:model=
"localModel"
:rules=
"formRules"
label-width=
"auto"
v-bind=
"$attrs"
:validate-on-rule-change=
"false"
>
<el-row
:gutter=
"20"
>
<el-col
v-for=
"item in visibleConfig"
:key=
"item.prop"
:span=
"item.span || 6"
>
<el-form-item
:label=
"item.label"
:prop=
"item.prop"
:class=
"
{ 'search-form-item': isSearch }">
<el-form-item
:label=
"item.label"
:prop=
"item.prop"
:class=
"
{ 'search-form-item': isSearch }"
:label-position="item.labelPosition || 'top'">
<!-- Input -->
<el-input
v-if=
"item.type === 'input'"
v-model=
"localModel[item.prop]"
:placeholder=
"item.placeholder || `请输入$
{item.label}`" :clearable="true"
...
...
@@ -194,25 +196,99 @@ watch(
}
}
localModel
.
value
=
initialModel
// ✅ 在这里同步 modelValue(包括 extra 字段)
localModel
.
value
=
syncModelFromProps
(
props
.
modelValue
,
internalConfig
.
value
)
},
{
immediate
:
true
}
)
console
.
log
(
'🚀 子组件 props.modelValue 初始值:'
,
props
.
modelValue
)
// 监听 modelValue(用于后续外部更新)
watch
(
()
=>
props
.
modelValue
,
(
newVal
)
=>
{
if
(
!
newVal
)
return
// 只同步存在的字段,避免污染
for
(
const
item
of
internalConfig
.
value
)
{
const
key
=
item
.
prop
if
(
newVal
.
hasOwnProperty
(
key
))
{
localModel
.
value
[
key
]
=
newVal
[
key
]
}
if
(
!
newVal
||
!
internalConfig
.
value
)
return
// ✅ 同样使用 sync 函数
localModel
.
value
=
syncModelFromProps
(
newVal
,
internalConfig
.
value
)
},
{
deep
:
true
}
)
// 提取同步逻辑
function
syncModelFromProps
(
newModelValue
,
newConfig
)
{
if
(
!
newModelValue
||
!
newConfig
)
return
{}
const
synced
=
{}
// 1. 同步主字段
for
(
const
item
of
newConfig
)
{
const
key
=
item
.
prop
if
(
newModelValue
.
hasOwnProperty
(
key
))
{
synced
[
key
]
=
newModelValue
[
key
]
}
else
if
(
item
.
multiple
||
[
'checkbox-group'
,
'daterange'
].
includes
(
item
.
type
))
{
synced
[
key
]
=
item
.
defaultValue
??
[]
}
else
{
synced
[
key
]
=
item
.
defaultValue
??
''
}
}
// 2. 同步 extra 字段(从 newModelValue 中的 sourceField 重新计算)
for
(
const
item
of
newConfig
)
{
const
sourceField
=
item
.
prop
const
extraMap
=
item
.
onChangeExtraFields
if
(
!
extraMap
||
typeof
extraMap
!==
'object'
)
continue
const
sourceObj
=
newModelValue
[
sourceField
]
if
(
sourceObj
&&
typeof
sourceObj
===
'object'
)
{
// newModelValue 中有 sourceField → 重新计算 extra
for
(
const
[
targetKey
,
subPath
]
of
Object
.
entries
(
extraMap
))
{
const
val
=
getNestedValue
(
sourceObj
,
subPath
)
if
(
val
!==
undefined
)
{
synced
[
targetKey
]
=
val
}
}
}
)
}
// 3. 保留 localModel 中的 extra 字段(仅当 newModelValue 中没有对应的 sourceField 时)
for
(
const
item
of
newConfig
)
{
const
sourceField
=
item
.
prop
const
extraMap
=
item
.
onChangeExtraFields
if
(
!
extraMap
||
typeof
extraMap
!==
'object'
)
continue
// 如果 newModelValue 中没有 sourceField,说明没有重新计算
if
(
newModelValue
[
sourceField
]
===
undefined
)
{
// 那么保留 localModel 中对应的 extra 字段
for
(
const
[
targetKey
,
subPath
]
of
Object
.
entries
(
extraMap
))
{
if
(
localModel
.
value
.
hasOwnProperty
(
targetKey
))
{
synced
[
targetKey
]
=
localModel
.
value
[
targetKey
]
}
}
}
}
// 4. 保留其他不在 config 中的字段
for
(
const
key
in
newModelValue
)
{
if
(
!
synced
.
hasOwnProperty
(
key
)
&&
!
newConfig
.
some
(
item
=>
item
.
prop
===
key
)
)
{
const
isExtraTarget
=
newConfig
.
some
(
item
=>
item
.
onChangeExtraFields
&&
item
.
onChangeExtraFields
.
hasOwnProperty
(
key
)
)
if
(
!
isExtraTarget
)
{
synced
[
key
]
=
newModelValue
[
key
]
}
}
}
return
synced
}
function
getNestedValue
(
obj
,
path
)
{
return
path
.
split
(
'.'
).
reduce
((
current
,
key
)
=>
current
?.[
key
],
obj
)
}
// 当字典加载完成时,触发同步
function
markDictLoaded
(
prop
)
{
dictLoaded
.
value
.
add
(
prop
)
...
...
@@ -222,27 +298,44 @@ function markDictLoaded(prop) {
}
}
// 2. 用户操作导致 localModel 变化时,emit(防抖可选)
function
handleModelChange
(
value
,
item
)
{
console
.
log
(
'✅ handleModelChange 被调用'
,
{
prop
:
item
?.
prop
,
value
})
// 同步额外字段
if
(
item
?.
type
===
'select'
&&
item
.
onChangeExtraFields
)
{
const
options
=
getSelectOptions
(
item
)
const
opt
=
options
.
find
(
o
=>
o
.
value
===
value
)
// ✅ 现在 value 和 o.value 类型一致
if
(
opt
)
{
for
(
const
[
targetProp
,
sourceKey
]
of
Object
.
entries
(
item
.
onChangeExtraFields
))
{
localModel
.
value
[
targetProp
]
=
opt
.
raw
[
sourceKey
]
console
.
log
(
`✅ 同步
${
targetProp
}
=`
,
opt
.
raw
[
sourceKey
])
}
}
console
.
group
(
'🔄 handleModelChange'
)
console
.
log
(
'输入 value:'
,
value
)
console
.
log
(
'item:'
,
item
)
console
.
log
(
'当前 localModel:'
,
localModel
.
value
)
const
newModel
=
{
...
localModel
.
value
,
[
item
.
prop
]:
value
}
if
(
item
?.
type
===
'select'
&&
item
.
onChangeExtraFields
)
{
const
options
=
getSelectOptions
(
item
)
console
.
log
(
'可用 options:'
,
options
)
const
opt
=
options
.
find
(
o
=>
o
.
value
===
value
)
console
.
log
(
'匹配的 opt:'
,
opt
)
if
(
opt
?.
raw
)
{
for
(
const
[
targetProp
,
sourceKey
]
of
Object
.
entries
(
item
.
onChangeExtraFields
))
{
const
extraValue
=
opt
.
raw
[
sourceKey
]
newModel
[
targetProp
]
=
extraValue
console
.
log
(
`✅ 设置
${
targetProp
}
=`
,
extraValue
)
}
}
}
// emit 更新
nextTick
(()
=>
{
if
(
!
isEqualShallow
(
props
.
modelValue
,
localModel
.
value
))
{
console
.
log
(
'准备 emit modelValue:'
,
localModel
.
value
)
emit
(
'update:modelValue'
,
{
...
localModel
.
value
})
}
})
console
.
log
(
'🆕 newModel:'
,
newModel
)
console
.
log
(
'📦 props.modelValue:'
,
props
.
modelValue
)
console
.
log
(
'isEqualShallow?'
,
isEqualShallow
(
props
.
modelValue
,
newModel
))
localModel
.
value
=
newModel
nextTick
(()
=>
{
if
(
!
isEqualShallow
(
props
.
modelValue
,
newModel
))
{
console
.
log
(
'📤 emit update:modelValue:'
,
newModel
)
emit
(
'update:modelValue'
,
newModel
)
}
else
{
console
.
log
(
'🚫 跳过 emit:认为相等'
)
}
})
console
.
groupEnd
()
}
// 辅助函数:浅比较两个对象
function
isEqualShallow
(
a
,
b
)
{
...
...
src/views/financialCenter/financialBilling.vue
View file @
d4982277
...
...
@@ -73,7 +73,7 @@
<el-table-column
prop=
"policyNo"
label=
"保单号"
width=
"120"
sortable
/>
<el-table-column
prop=
"insuranceCompany"
label=
"保险公司"
width=
"120"
sortable
/>
<el-table-column
prop=
"commissionPaidAmount"
label=
"累积已入账金额"
width=
"120"
sortable
/>
<el-table-column
prop=
"commissionPaidRatio"
label=
"累积已入账比例"
width=
"120"
sortable
/>
<el-table-column
prop=
"commissionPaidRatio"
label=
"累积已入账比例"
width=
"120"
sortable
:formatter=
"(row) => `${row.commissionPaidRatio }%`"
/>
<el-table-column
prop=
"fortuneName"
label=
"出账项目"
width=
"130"
sortable
/>
<el-table-column
prop=
"fortunePeriod"
label=
"出账期数"
width=
"130"
sortable
/>
<el-table-column
prop=
"fortuneTotalPeriod"
label=
"总期数"
width=
"120"
sortable
/>
...
...
@@ -83,14 +83,15 @@
<el-table-column
prop=
"currency"
label=
"出账币种"
width=
"130"
sortable
/>
<el-table-column
prop=
"fortunePaidAmount"
label=
"已出账金额"
width=
"120"
sortable
/>
<el-table-column
prop=
"fortuneUnpaidAmount"
label=
"剩余出账金额"
width=
"120"
sortable
/>
<el-table-column
prop=
"currentPaymentAmount"
label=
"本期出账金额"
width=
"120"
sortable
/>
<el-table-column
prop=
"fortuneUnpaidRatio"
label=
"剩余出账比例"
width=
"120"
sortable
/>
<el-table-column
prop=
"currentPaymentAmount"
label=
"本期出账金额"
width=
"120"
sortable
/>
<el-table-column
prop=
"fortuneUnpaidRatio"
label=
"剩余出账比例"
width=
"120"
sortable
:formatter=
"(row) => `${row.fortuneUnpaidRatio }%`"
/>
<el-table-column
prop=
"status"
label=
"出账状态"
width=
"120"
sortable
>
<
template
#
default=
"{ row }"
>
{{
getDictLabel
(
'csf_fortune_status'
,
row
.
status
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
/>
<el-table-column
prop=
"policyCurrency"
label=
"保单币种"
width=
"120"
sortable
/>
<el-table-column
prop=
"payoutDate"
label=
"出账日(实)"
width=
"120"
sortable
/>
<el-table-column
prop=
"remark"
label=
"备注"
width=
"120"
sortable
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
...
...
@@ -143,6 +144,7 @@ import CommonDialog from '@/components/commonDialog'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
import
{
ElMessage
}
from
'element-plus'
import
{
formatCurrency
}
from
'@/utils/number'
import
{
Select
}
from
'@element-plus/icons-vue'
// 接口
import
{
getPolicyFortuneList
,
addCheckRecordaddBatch
,
updatePayoutAmount
,
downloadPolicyFortuneAccount
}
from
'@/api/financial/commission'
import
useUserStore
from
'@/store/modules/user'
...
...
@@ -162,7 +164,8 @@ const searchConfig = ref([
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
},
{
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'出账状态'
,
...
...
@@ -209,13 +212,13 @@ const searchConfig = ref([
startPlaceholder
:
'开始时间'
,
endPlaceholder
:
'结束时间'
},
//
{
//
type: 'select',
// prop: 'status
',
//
label: '入账状态',
//
multiple: true,
//
dictType: 'csf_expected_commission_status'
// },
{
type
:
'select'
,
prop
:
'commissionStatusList
'
,
label
:
'入账状态'
,
multiple
:
true
,
dictType
:
'csf_expected_commission_status'
},
])
// 表格操作菜单
const
dropdownItems
=
[
...
...
@@ -340,7 +343,13 @@ const setPayoutAmountConfig = [
prop
:
'status'
,
label
:
'出账状态'
,
dictType
:
'csf_expected_fortune_status'
}
},
// {
// type: 'input',
// prop: 'exchangeRate',
// label: '结算汇率',
// defaultValue: 1
// }
]
...
...
@@ -370,7 +379,7 @@ const handleQuery = async () => {
const
params
=
searchFormRef
.
value
.
getFormData
()
loadTableData
(
params
)
}
const
visibleDefaultButtons
=
ref
([
'add'
,
'
import'
,
'
export'
,
'reset'
,
'query'
])
const
visibleDefaultButtons
=
ref
([
'add'
,
'export'
,
'reset'
,
'query'
])
// 按钮配置
const
operationBtnList
=
ref
([
{
...
...
@@ -378,12 +387,7 @@ const operationBtnList = ref([
direction
:
'left'
,
label
:
'新增出账'
,
click
:
handleAdd
},
{
key
:
'import'
,
direction
:
'left'
,
label
:
'导入出账'
,
click
:
handleImport
},
},
{
key
:
'export'
,
direction
:
'right'
,
...
...
@@ -481,6 +485,7 @@ const updatePayoutAmountapi = async (data) => {
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'设置本期出账金额成功'
)
loadTableData
()
setPayoutAmountDialogFlag
.
value
=
false
}
else
{
ElMessage
.
error
(
res
.
msg
||
'设置本期出账金额失败'
)
}
...
...
src/views/financialCenter/financialIncome.vue
View file @
d4982277
...
...
@@ -105,16 +105,17 @@
<el-table-column
prop=
"commissionDate"
label=
"入账日"
width=
"120"
sortable
/>
<el-table-column
prop=
"commissionExpectedStatus"
label=
"入账状态"
width=
"120"
sortable
:formatter=
"formatStatus"
/>
<el-table-column
prop=
"currentCommissionRatio"
label=
"本次入账比例"
width=
"130"
sortable
/>
<el-table-column
prop=
"p
eriodPaidRatio"
label=
"累积入账比例"
width=
"130"
sortable
/>
<el-table-column
prop=
"pe
riodPendingRatio"
label=
"待入账比例"
width=
"120"
sortable
/>
<el-table-column
prop=
"
paidAmount"
label=
"本次入账金额"
width=
"130"
sortable
/>
<el-table-column
prop=
"currentCommissionRatio"
label=
"本次入账比例"
width=
"130"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"p
aidRatio"
label=
"累积入账比例"
width=
"130"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"pe
ndingRatio"
label=
"待入账比例"
width=
"120"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"
amount"
label=
"本次入账金额"
width=
"130"
sortable
:formatter=
"formatCurrencyUtil"
/>
<el-table-column
prop=
"currency"
label=
"入账币种"
width=
"120"
sortable
/>
<el-table-column
prop=
"exchangeRate"
label=
"结算汇率(实)"
width=
"140"
sortable
/>
<el-table-column
prop=
"commissionPeriod"
label=
"本次入账期数"
width=
"130"
sortable
/>
<el-table-column
prop=
"totalPeriod"
label=
"总期数"
width=
"120"
sortable
/>
<el-table-column
prop=
"commissionName"
label=
"入账项目"
width=
"120"
sortable
/>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
/>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
:formatter=
"formatCurrencyUtil"
/>
<el-table-column
prop=
"policyCurrency"
label=
"保单币种"
width=
"120"
sortable
/>
<el-table-column
prop=
"remark"
label=
"备注"
width=
"120"
sortable
/>
<el-table-column
prop=
"isDeleted"
label=
"记录状态"
width=
"120"
sortable
>
<
template
#
default=
"{ row }"
>
...
...
@@ -131,13 +132,14 @@
</
template
>
<el-menu
@
select=
"handleSelect($event, row)"
popper-class=
"custom-menu"
>
<el-menu-item
:index=
"item.value"
v-for=
"item in dropdownItems"
:key=
"item.value"
>
<el-text
class=
"mx-1"
v-if=
"!item.confirm"
>
{{item.label}}
</el-text>
<el-popconfirm
v-if=
"item.confirm"
confirm-button-text=
"Yes"
cancel-button-text=
"No"
:icon=
"InfoFilled"
icon-color=
"#626AEF"
:title=
"item.confirm"
@
confirm=
"handleMenuConfirm(item.value, row)"
width=
"300"
placement=
"left-end"
>
<
template
#
reference
>
<el-text
class=
"mx-1"
>
{{
item
.
label
}}
</el-text>
</
template
>
</el-popconfirm>
<el-text
class=
"mx-1"
v-if=
"!item.confirm"
>
{{ item.label }}
</el-text>
<el-popconfirm
v-if=
"item.confirm"
confirm-button-text=
"Yes"
cancel-button-text=
"No"
:icon=
"InfoFilled"
icon-color=
"#626AEF"
:title=
"item.confirm"
@
confirm=
"handleMenuConfirm(item.value, row)"
width=
"300"
placement=
"left-end"
>
<
template
#
reference
>
<el-text
class=
"mx-1"
>
{{
item
.
label
}}
</el-text>
</
template
>
</el-popconfirm>
</el-menu-item>
</el-menu>
</el-popover>
...
...
@@ -147,14 +149,14 @@
<!-- 表格操作菜单 -->
<div
class=
"tableOptionContainer"
>
<el-row
justify=
"space-between"
>
<el-col
:span=
"12"
>
<el-text
type=
"danger"
>
*非关联保单应收单以及比对失败的不可生成可出账记录
</el-text>
<el-col
:span=
"12"
>
<el-text
type=
"danger"
>
*非关联保单应收单以及比对失败的不可生成可出账记录
</el-text>
</el-col>
<el-col
:span=
"4"
>
<el-button
type=
"primary"
:icon=
"Select"
:disabled=
"updatePayRollStatusDisable"
@
click=
"generateCommissionRecordapi"
>
{{ multipleSelection.length }} 条数据,生成可出账记录
</el-button>
</el-col>
</el-row>
</div>
</template>
...
...
@@ -170,7 +172,7 @@
<el-row
:gutter=
"10"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"3"
:lg=
"3"
>
<el-button
type=
"primary"
:icon=
"Plus"
:disabled=
"!checkFormData?.reconciliationYearMonth"
@
click=
"
addCheckRecordDialogFlag = true;
"
>
新增
</el-button>
@
click=
"
handleAddCheckList()
"
>
新增
</el-button>
</el-col>
<el-col
:xs=
"24"
:sm=
"24"
:md=
"3"
:lg=
"3"
>
<el-button
type=
"primary"
:icon=
"Upload"
:disabled=
"!checkFormData?.reconciliationYearMonth"
...
...
@@ -235,8 +237,8 @@
</CommonDialog>
<!-- 新增检核记录弹窗 -->
<CommonDialog
:dialogTitle=
'editStatus.value == "add" ? "新增检核记录" : "修改检核记录"'
dialogWidth=
'80%'
:openDialog=
addCheckRecordDialogFlag
:showAction=
'true'
:showClose=
'true'
@
c
lose=
'addCheckRecordDialogFlag = false;editStatus = "add"'
@
c
onfirm=
'handleAddCheckRecord()'
>
:openDialog=
addCheckRecordDialogFlag
:showAction=
'true'
:showClose=
'true'
@
close=
'closeDialog()'
@
confirm=
'handleAddCheckRecord()'
>
<el-row>
<el-col
:xs=
"24"
:sm=
"24"
:md=
"24"
:lg=
"24"
>
<SearchForm
ref=
"addCheckRecordFormRef"
:config=
"addCheckRecordConfig"
v-model=
"addReceivablesFormModel"
/>
...
...
@@ -248,7 +250,8 @@
:showClose=
'true'
@
close=
'fileUploadDialogFlag = false; files = ""'
@
confirm=
'fileUploadDialogFlag = false; files = ""'
>
<FileUpload
v-model=
"files"
:data=
"{ reconciliationYearMonth: checkFormData.reconciliationYearMonth }"
:file-type=
"['xlsx', 'xls']"
:action=
"'/csf/api/commission/upload/excel'"
:limit=
"1"
:fileSize=
"15"
@
uploadEnd=
"handleUploadEnd"
/>
:file-type=
"['xlsx', 'xls']"
:action=
"'/csf/api/commission/upload/excel'"
:limit=
"1"
:fileSize=
"15"
@
uploadEnd=
"handleUploadEnd"
/>
</CommonDialog>
<!-- 设置比对状态 -->
...
...
@@ -285,9 +288,22 @@ import {
getPolicyCommissionList
,
generateCommissionRecord
,
addPayrollCheckRecord
,
commissionExpectedRecord
,
updateCompareStatus
,
updateCommissionRecord
,
deletePolicyCommission
,
syncExpectedCommission
}
from
'@/api/financial/commission'
import
{
Plus
,
Upload
,
Select
}
from
'@element-plus/icons-vue'
import
{
InfoFilled
,
Select
,
Upload
,
Plus
}
from
'@element-plus/icons-vue'
import
FileUpload
from
'@/components/FileUpload/index.vue'
import
{
loadDicts
,
getDictLabel
}
from
'@/utils/useDict'
const
formatRatio
=
(
row
,
column
,
cellValue
,
index
)
=>
{
if
(
cellValue
==
null
||
cellValue
==
''
||
cellValue
==
0
)
{
return
'-'
}
return
cellValue
+
'%'
}
const
formatCurrencyUtil
=
(
row
,
column
,
cellValue
,
index
)
=>
{
if
(
cellValue
==
null
||
cellValue
==
''
||
cellValue
==
0
)
{
return
'-'
}
return
formatCurrency
(
cellValue
)
}
const
files
=
ref
(
''
)
// 分页相关
const
currentPage
=
ref
(
1
)
...
...
@@ -412,11 +428,11 @@ const checkConfig = ref([
])
const
checkRecordEdit
=
(
row
)
=>
{
console
.
log
(
'查看记录'
,
row
)
selectedRowCheck
.
value
=
{
...
row
}
selectedRowCheck
.
value
=
{
...
row
}
editStatus
.
value
=
'edit'
addReceivablesFormModel
.
value
=
{
...
row
}
addCheckRecordDialogFlag
.
value
=
true
// console.log('父组件赋值',
addReceivablesFormModel.value)
console
.
log
(
'父组件赋值'
,
addReceivablesFormModel
.
value
)
}
const
checkFormData
=
ref
({
...
...
@@ -469,8 +485,8 @@ onMounted(async () => {
}
})
// 格式化函数(每次渲染都会调用,所以能拿到最新字典)
const
formatStatus
=
(
row
,
column
)
=>
{
return
getDictLabel
(
'csf_expected_commission_status'
,
row
.
status
)
// 实时查缓存
const
formatStatus
=
(
row
,
column
,
cellValue
,
index
)
=>
{
return
getDictLabel
(
'csf_expected_commission_status'
,
cellValue
)
// 实时查缓存
}
// 应收单类型
const
commissionBizTypeOptions
=
[
...
...
@@ -599,34 +615,48 @@ const addCheckRecordConfig = ref([
])
const
addCheckRecordDialogFlag
=
ref
(
false
)
const
handleAddCheckRecord
=
async
()
=>
{
try
{
const
params
=
ref
({})
// ✅ 统一从子组件获取完整表单数据(含 extra 字段)
await
nextTick
()
// 确保子组件已同步
const
formData
=
addCheckRecordFormRef
.
value
.
getFormData
()
console
.
log
(
'======'
,
formData
)
let
params
if
(
editStatus
.
value
===
'edit'
)
{
params
.
value
=
{
...
addReceivablesFormModel
.
value
,
params
=
{
...
formData
,
// ←←← 使用 formData,不是 addReceivablesFormModel.value
commissionBizId
:
selectedRowCheck
.
value
.
commissionBizId
}
console
.
log
(
params
)
await
updateCommissionRecord
(
params
.
value
)
ElMessage
.
success
(
'更新检核记录成功'
)
await
updateCommissionRecord
(
params
)
}
else
{
const
addCheckSearchParams
=
addCheckRecordFormRef
.
value
.
getFormData
()
console
.
log
(
'新增检核记录'
,
addCheckSearchParams
)
params
.
value
=
{
...
addCheckSearchParams
,
params
=
{
...
formData
,
reconciliationYearMonth
:
checkFormData
.
value
.
reconciliationYearMonth
}
await
addPayrollCheckRecord
([
params
.
value
])
ElMessage
.
success
(
'新增检核记录成功'
)
addCheckRecordDialogFlag
.
value
=
false
checkRecordTableData
.
value
=
[]
await
addPayrollCheckRecord
([
params
])
}
ElMessage
.
success
(
editStatus
.
value
===
'edit'
?
'更新成功'
:
'新增成功'
)
addCheckRecordDialogFlag
.
value
=
false
resetForm
(
'addReceivablesFormModel'
)
checkRecordQuery
()
}
catch
(
error
)
{
console
.
error
(
'
新增检核记录
失败'
,
error
)
ElMessage
.
error
(
'
新增检核记录
失败'
)
console
.
error
(
'
操作
失败'
,
error
)
ElMessage
.
error
(
'
操作
失败'
)
}
}
const
resetForm
=
(
type
)
=>
{
if
(
type
===
'addReceivablesFormModel'
)
addReceivablesFormModel
.
value
=
{}
addCheckRecordFormRef
.
value
.
resetForm
()
}
const
closeDialog
=
()
=>
{
addCheckRecordDialogFlag
.
value
=
false
editStatus
.
value
=
'add'
handleQuery
()
}
// 生成可出账记录
const
generateCommissionRecordapi
=
async
()
=>
{
try
{
...
...
@@ -646,8 +676,8 @@ const generateCommissionRecordapi = async () => {
}
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'设置比对状态'
,
value
:
'setStatus'
,
confirm
:
''
},
{
label
:
'同步到应收款管理'
,
value
:
'syncToReceivable'
,
confirm
:
'确认要同步到应收款管理吗?'
},
{
label
:
'设置比对状态'
,
value
:
'setStatus'
,
confirm
:
''
},
{
label
:
'同步到应收款管理'
,
value
:
'syncToReceivable'
,
confirm
:
'确认要同步到应收款管理吗?'
},
// { label: '更新数据', value: 'editRecord' },
// { label: '查看记录', value: 'viewRecord' }
]
...
...
@@ -655,7 +685,7 @@ const handleMenuConfirm = async (action, row) => {
console
.
log
(
'点击了操作菜单'
,
action
,
row
)
if
(
action
===
'syncToReceivable'
)
{
try
{
if
(
row
.
commissionStatus
!==
'3'
)
{
if
(
row
.
commissionStatus
!==
'3'
)
{
ElMessage
.
error
(
'应收款管理已有这条记录,无需同步'
)
return
}
...
...
@@ -671,7 +701,7 @@ const handleMenuConfirm = async (action, row) => {
console
.
error
(
'同步到应收款管理失败'
,
error
)
ElMessage
.
error
(
'同步到应收款管理失败'
)
}
}
}
}
// 统计信息
...
...
@@ -803,11 +833,17 @@ const handleSelect = (e, row) => {
}
else
if
(
e
===
'viewRecord'
)
{
viewRecordDialogFlag
.
value
=
true
return
}
else
if
(
e
===
'syncToReceivable'
)
{
}
else
if
(
e
===
'syncToReceivable'
)
{
return
}
}
const
handleAddCheckList
=
()
=>
{
editStatus
.
value
=
'add'
addReceivablesFormModel
.
value
=
{
...
selectedRow
.
value
}
addCheckRecordDialogFlag
.
value
=
true
resetForm
(
'addReceivablesFormModel'
)
}
// 设置比对状态api
...
...
@@ -870,10 +906,10 @@ const handleUploadEnd = (code) => {
// 关闭弹窗后的操作
const
closthDialog
=
()
=>
{
dialogFlag
.
value
=
false
checkFormRef
.
value
.
resetForm
()
checkFormData
.
value
=
{}
checkRecordTableData
.
value
=
[]
dialogFlag
.
value
=
false
checkFormRef
.
value
.
resetForm
()
checkFormData
.
value
=
{}
checkRecordTableData
.
value
=
[]
}
</
script
>
...
...
src/views/financialCenter/payables.vue
View file @
d4982277
<
template
>
<div>
<CommonPage
:operationBtnList=
"operationBtnList"
:showSearchForm=
"true"
:show-pagination=
"true"
:total=
"pageTotal"
<CommonPage
:operationBtnList=
"operationBtnList"
:visibleDefaultButtons=
"visibleDefaultButtons"
:showSearchForm=
"true"
:show-pagination=
"true"
:total=
"pageTotal"
:current-page=
"currentPage"
:page-size=
"pageSize"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
>
<!-- 搜索区域 -->
...
...
@@ -15,8 +15,8 @@
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
:lg=
"4"
>
<el-card
shadow=
"hover"
class=
"statistics-card"
>
<div
class=
"card-content"
>
<div
class=
"card-label"
>
应出
款
总金额
</div>
<div
class=
"card-value"
>
{{
formatCurrency
(
statisticsData
.
totalAmount
)
}}
</div>
<div
class=
"card-label"
>
应出
账
总金额
</div>
<div
class=
"card-value"
>
{{
formatCurrency
(
statisticsData
.
total
Expected
Amount
)
}}
</div>
</div>
</el-card>
</el-col>
...
...
@@ -32,7 +32,7 @@
<el-card
shadow=
"hover"
class=
"statistics-card"
>
<div
class=
"card-content"
>
<div
class=
"card-label"
>
待出账金额
</div>
<div
class=
"card-value"
>
{{
formatCurrency
(
statisticsData
.
pendingP
aidAmount
)
}}
</div>
<div
class=
"card-value"
>
{{
formatCurrency
(
statisticsData
.
totalUnp
aidAmount
)
}}
</div>
</div>
</el-card>
</el-col>
...
...
@@ -56,7 +56,7 @@
<el-card
shadow=
"hover"
class=
"statistics-card"
>
<div
class=
"card-content"
>
<div
class=
"card-label"
>
总保费
</div>
<div
class=
"card-value"
>
{{
statisticsData
.
totalPolicyCount
}}
</div>
<div
class=
"card-value"
>
{{
formatCurrency
(
statisticsData
.
totalPremiumAmount
)
}}
</div>
</div>
</el-card>
</el-col>
...
...
@@ -113,9 +113,13 @@
{{
formatCurrency
(
row
.
unpaidAmount
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"broker_ratio"
label=
"持有比例"
width=
"120"
sortable
/>
<el-table-column
prop=
"insurerBizId"
label=
"保险公司"
width=
"120"
sortable
/>
<el-table-column
prop=
"productLaunchBizId"
label=
"产品计划"
width=
"120"
sortable
/>
<el-table-column
prop=
"brokerRatio"
label=
"持有比例"
width=
"120"
sortable
>
<
template
#
default=
"{ row }"
>
{{
(
row
.
brokerRatio
||
0
)
+
'%'
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"insuranceCompany"
label=
"保险公司"
width=
"120"
sortable
/>
<el-table-column
prop=
"productName"
label=
"产品计划"
width=
"120"
sortable
/>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
>
<
template
#
default=
"{ row }"
>
{{
formatCurrency
(
row
.
premium
)
}}
...
...
@@ -147,13 +151,13 @@
:showClose=
"true"
@
close=
"payRecordDialogTableVisible = false"
>
<el-table
:data=
"payRecordDialogTableData"
border
style=
"width: 100%"
>
<el-table-column
v-for=
"item in payRecordDialogTableColumns"
:key=
"item.property"
:property=
"item.property"
:label=
"item.label"
:width=
"item.width"
/>
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
</el-table>
</CommonDialog>
<!-- 新增出账记录 -->
<CommonDialog
:dialogTitle=
"editStatus === 'add' ? '新增出账记录' : '修改出账记录'"
dialogWidth=
"80%"
:openDialog=
"addPayRecordDialogVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"
addPayRecordDialogVisible = false; editStatus = 'add'
"
@
confirm=
"handleConfirmAddPayRecord"
>
@
close=
"
resetAddPayRecordForm
"
@
confirm=
"handleConfirmAddPayRecord"
>
<SearchForm
ref=
"addPayRecordFormRef"
:config=
"addPayRecordFormConfig"
v-model=
"addPayRecordFormModel"
/>
</CommonDialog>
<!-- 设置出账状态 -->
...
...
@@ -171,11 +175,12 @@ import CommonPage from '@/components/commonPage'
import
{
ref
,
reactive
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
formatCurrency
}
from
'@/utils/number'
import
{
expectedFortuneList
,
payRecordList
,
addPayRecord
,
updatePayRecord
}
from
'@/api/financial/commission'
import
{
expectedFortuneList
,
payRecordList
,
addPayRecord
,
updatePayRecord
,
exportPayRecord
}
from
'@/api/financial/commission'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
import
CommonDialog
from
'@/components/commonDialog'
import
{
loadDicts
,
getDictLabel
}
from
'@/utils/useDict'
import
useUserStore
from
'@/store/modules/user'
import
{
safeDownload
}
from
'@/utils/safeDownload'
// 设置出账状态
const
setPayRecordStatusDialogVisible
=
ref
(
false
)
const
selectedRow
=
ref
(
null
)
...
...
@@ -192,7 +197,9 @@ const setPayRecordStatusFormConfig = ref([
label
:
'修改理由'
,
},
])
const
visibleDefaultButtons
=
ref
([
'add'
,
'export'
,
'reset'
,
'query'
])
const
userStore
=
useUserStore
()
// 应收单类型
const
fortuneBizTypeOptions
=
[
...
...
@@ -297,6 +304,8 @@ const searchConfig = ref([
}
},
])
const
payRecordDialogTableVisible
=
ref
(
false
)
// 新增出账记录
const
addPayRecordFormModel
=
ref
({
...
...
@@ -419,6 +428,12 @@ const handleConfirmAddPayRecord = async () => {
}
}
// 弹窗表单重置
const
resetAddPayRecordForm
=
()
=>
{
addPayRecordFormRef
.
value
.
resetForm
()
editStatus
.
value
=
'add'
addPayRecordDialogVisible
.
value
=
false
}
const
editStatus
=
ref
(
'add'
)
...
...
@@ -433,13 +448,13 @@ const handleSelect = async (e, row) => {
payRecordDialogTableColumns
.
value
=
[
{
property
:
'broker'
,
label
:
'转介人'
,
width
:
'100'
,
},
{
property
:
'fortuneName'
,
label
:
'出账项目'
,
width
:
'150'
},
{
property
:
'
a
mount'
,
label
:
'出账金额'
,
width
:
'150'
},
{
property
:
'
currentPaymentA
mount'
,
label
:
'出账金额'
,
width
:
'150'
},
{
property
:
'currency'
,
label
:
'出账币种'
,
width
:
'150'
},
{
property
:
'
amount'
,
label
:
'出账比例'
,
width
:
'150'
},
{
property
:
'
currentCommissionRatio'
,
label
:
'待出账比例'
,
width
:
'150'
},
{
property
:
'
currentPaymentRatio'
,
label
:
'出账比例'
,
width
:
'150'
,
formatter
:
(
row
)
=>
`
${
row
.
currentPaymentRatio
}
%`
},
{
property
:
'
fortuneUnpaidRatio'
,
label
:
'待出账比例'
,
width
:
'150'
,
formatter
:
(
row
)
=>
`
${
row
.
fortuneUnpaidRatio
}
%`
},
{
property
:
'fortunePeriod'
,
label
:
'佣金期数'
,
width
:
'150'
},
{
property
:
'fortuneTotalPeriod'
,
label
:
'总期数'
,
width
:
'150'
},
{
property
:
'
updaterId
'
,
label
:
'操作人'
,
width
:
'150'
},
{
property
:
'
reconciliationOperator
'
,
label
:
'操作人'
,
width
:
'150'
},
{
property
:
'updateTime'
,
label
:
'操作时间'
,
width
:
'150'
}
]
}
else
if
(
e
===
'setStatus'
)
{
...
...
@@ -501,8 +516,17 @@ const handleImport = () => {
ElMessage
.
info
(
'点击导入按钮'
)
}
const
handleExport
=
()
=>
{
ElMessage
.
info
(
'点击导出按钮'
)
const
handleExport
=
async
()
=>
{
// 获取搜索参数
const
params
=
searchFormRef
.
value
?.
getFormData
()
||
{}
const
response
=
await
exportPayRecord
(
params
)
// 文件名设置为应收款导出_yyyy-MM-dd hh:mm:ss.xlsx,不需要-,用字符串
const
fileName
=
`应付款导出_
${
new
Date
().
toLocaleString
().
replace
(
/
\/
/g
,
''
).
replace
(
/:/g
,
''
).
replace
(
/
\s
/g
,
''
)}
.xlsx`
await
safeDownload
(
response
,
fileName
,
'application/vnd.ms-excel;charset=utf-8'
)
}
const
handleReset
=
()
=>
{
...
...
@@ -525,11 +549,11 @@ const operationBtnList = ref([
direction
:
'left'
,
click
:
handleAdd
},
{
key
:
'import'
,
direction
:
'left'
,
click
:
handleImport
},
//
{
//
key: 'import',
//
direction: 'left',
//
click: handleImport
//
},
{
key
:
'export'
,
direction
:
'right'
,
...
...
src/views/financialCenter/receivables.vue
View file @
d4982277
...
...
@@ -69,9 +69,9 @@
{{
(
row
.
pendingRatio
||
0
)
+
'%'
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"pending
Paid
Amount"
label=
"待入账金额(估)"
width=
"160"
sortable
>
<el-table-column
prop=
"pendingAmount"
label=
"待入账金额(估)"
width=
"160"
sortable
>
<
template
#
default=
"{ row }"
>
{{
numberWithCommas
(
row
.
pending
Paid
Amount
)
}}
{{
numberWithCommas
(
row
.
pendingAmount
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"currency"
label=
"入账币种"
width=
"100"
/>
...
...
@@ -618,7 +618,7 @@ const handleSelect = async (e, row) => {
{
property
:
'amount'
,
label
:
'入账金额'
,
width
:
'150'
},
{
property
:
'currentCommissionRatio'
,
label
:
'入账比例'
,
width
:
'150'
},
{
property
:
'commissionDate'
,
label
:
'入账日'
,
width
:
'150'
},
{
property
:
'
s
tatus'
,
label
:
'入账状态'
,
width
:
'150'
}
{
property
:
'
commissionS
tatus'
,
label
:
'入账状态'
,
width
:
'150'
}
]
// 加载真实数据
const
records
=
await
loadEntryRecordData
(
row
.
commissionExpectedBizId
)
...
...
src/views/sign/underwritingMain/index.vue
View file @
d4982277
<
template
>
<div
class=
"data-management-page"
>
<!-- 查询区域 -->
<el-card
class=
"search-card"
>
<!-- 第一行筛选条件 -->
<el-row
:gutter=
"20"
class=
"search-row"
>
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
保单号
</label>
<el-input
v-model=
"searchForm.policyNo"
placeholder=
"请输入"
clearable
size=
"default"
@
keyup
.
enter=
"handleSearch"
/>
</div>
</el-col>
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
客户姓名
</label>
<el-input
v-model=
"searchForm.customerName"
placeholder=
"请输入"
clearable
size=
"default"
@
keyup
.
enter=
"handleSearch"
/>
</div>
</el-col>
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
新单状态
</label>
<el-select
v-model=
"searchForm.status"
placeholder=
"请选择"
clearable
size=
"default"
>
<!-- 增加全部,默认传空字符串 -->
<el-option
label=
"全部"
value=
" "
/>
<el-option
v-for=
"item in policyFollowStatusList"
:key=
"item.itemValue"
:label=
"item.itemLabel"
:value=
"item.itemValue"
/>
</el-select>
</div>
</el-col>
</el-row>
<!-- 第二行筛选条件 -->
<el-row
:gutter=
"20"
class=
"search-row"
>
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
签单时间
</label>
<el-date-picker
v-model=
"searchForm.signDateRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
size=
"default"
/>
</div>
</el-col>
<!-- :icon="Search" -->
<el-col
:span=
"8"
class=
"search-buttons"
>
<el-button
type=
"primary"
@
click=
"handleSearch"
size=
"default"
class=
"search-btn"
>
查询
</el-button>
<!-- :icon="RefreshLeft" -->
<el-button
@
click=
"resetForm"
size=
"default"
>
重置
</el-button>
</el-col>
</el-row>
</el-card>
<!-- Excel导入区域 -->
<div
class=
"import-area"
>
<el-card
class=
"import-card"
>
<div
class=
"import-content"
>
<div
class=
"import-actions"
>
<el-upload
class=
"upload-excel"
:auto-upload=
"false"
:on-change=
"handleFileChange"
:show-file-list=
"false"
accept=
".xlsx, .xls"
>
<el-button
type=
"success"
size=
"default"
>
上传Excel文件
</el-button>
</el-upload>
<el-button
text
@
click=
"downloadTemplate"
size=
"default"
class=
"download-template-btn"
>
下载模板
</el-button>
</div>
<!-- 文件信息显示 -->
<div
v-if=
"selectedFile"
class=
"file-info"
>
<div
class=
"file-info-content"
>
<el-icon><document
/></el-icon>
<span
class=
"file-name"
>
{{
selectedFile
.
name
}}
</span>
<span
class=
"file-size"
>
(
{{
formatFileSize
(
selectedFile
.
size
)
}}
)
</span>
</div>
<el-button
type=
"primary"
@
click=
"handleImport"
size=
"default"
:loading=
"importLoading"
class=
"confirm-import-btn"
>
确认导入
</el-button>
</div>
</div>
</el-card>
</div>
<!-- 列表区域 -->
<el-card
class=
"table-card"
>
<div
class=
"table-actions"
>
<el-button
type=
"primary"
@
click=
"handleUpdateToPolicyLib"
>
更新至保单库
</el-button>
<!--
<el-text
class=
"mx-1"
size=
"large"
>
新单首期保费缴费完成后,勾选并点击更新至保单库,可前往保单中心查询
</el-text>
-->
</div>
<el-table
v-loading=
"tableLoading"
:data=
"tableData"
border
style=
"width: 100%"
height=
"350"
@
selection-change=
"handleSelectionChange"
@
sort-change=
"handleSortChange"
:row-class-name=
"tableRowClassName"
>
<el-table-column
type=
"selection"
width=
"55"
align=
"center"
/>
<!-- 新单状态需要通过policyFollowStatusList和value匹配,显示label -->
<el-table-column
prop=
"status"
label=
"新单状态"
width=
"100"
align=
"center"
sortable
>
<template
#
default=
"scope"
>
<span>
{{
convertStatusToDict
(
1
,
scope
.
row
.
status
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"coolingOffEndDate"
label=
"冷静期结束日期"
width=
"150"
align=
"center"
>
<
template
#
default=
"scope"
>
<span>
{{
scope
.
row
.
coolingOffEndDate
?
parseTime
(
scope
.
row
.
coolingOffEndDate
)
:
'--'
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"coolingOffDays"
label=
"冷静期天数"
width=
"150"
align=
"center"
>
</el-table-column>
<el-table-column
prop=
"policyNo"
label=
"保单号"
width=
"150"
align=
"center"
sortable
/>
<el-table-column
prop=
"customerName"
label=
"客户名称"
width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"signDate"
label=
"签单日期"
width=
"150"
align=
"center"
sortable
>
<
template
#
default=
"scope"
>
<span>
{{
parseTime
(
scope
.
row
.
signDate
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"signer"
label=
"签单人"
width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"paymentTerm"
label=
"供款年期"
width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"productName"
label=
"产品名称"
width=
"150"
align=
"center"
sortable
/>
<el-table-column
prop=
"insurer"
label=
"保险公司"
width=
"150"
align=
"center"
sortable
/>
<el-table-column
prop=
"reconciliationCompany"
label=
"对账公司"
width=
"150"
align=
"center"
sortable
/>
<el-table-column
prop=
"policyHolder"
label=
"保单持有人"
width=
"150"
align=
"center"
sortable
/>
<el-table-column
prop=
"insured"
label=
"受保人"
width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"currency"
label=
"币种"
width=
"100"
align=
"center"
sortable
>
<
template
#
default=
"scope"
>
<dict-tag
:options=
"currencyTypeOptions"
:value=
"scope.row.currency"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"initialPremium"
label=
"首期保费"
width=
"150"
align=
"center"
sortable
>
<
template
#
default=
"scope"
>
{{
numberWithCommas
(
scope
.
row
.
initialPremium
)
}}
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
width=
"200"
class-name=
"small-padding fixed-width"
fixed=
"right"
>
<
template
#
default=
"scope"
>
<div
class=
"btnCon"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"handleReport(scope.row)"
>
生成签约单完成报告
</el-button>
<el-dropdown
placement=
"bottom"
style=
"margin-left: 10px"
>
<el-button
type=
"primary"
link
size=
"small"
>
更多
<el-icon><ArrowDown
/></el-icon
></el-button>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
@
click=
"handleView(scope.row)"
>
查看
</el-dropdown-item>
<el-dropdown-item
@
click=
"handleStatus(scope.row)"
>
跟进
</el-dropdown-item>
<el-dropdown-item
@
click=
"handleEditStatus(scope.row)"
>
修改状态
</el-dropdown-item
>
</el-dropdown-menu>
<div>
<CommonPage
:operationBtnList=
'operationBtnList'
:visibleDefaultButtons=
"visibleDefaultButtons"
:showSearchForm=
'true'
:show-pagination=
'true'
:total=
'pageTotal'
:current-page=
'currentPage'
:page-size=
'pageSize'
@
size-change=
'handleSizeChange'
@
current-change=
'handleCurrentChange'
>
<!-- 搜索区域 -->
<template
#
searchForm
>
<SearchForm
ref=
"searchFormRef"
:config=
"searchConfig"
/>
</
template
>
<!-- 列表区域 -->
<
template
#
table
>
<el-table
:data=
"tableData"
height=
"500"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
prop=
"policyNo"
label=
"保单号"
width=
"200"
sortable
/>
<el-table-column
prop=
"status"
label=
"新单状态"
width=
"120"
sortable
>
<template
#
default=
"
{ row }">
{{
getDictLabel
(
'csf_policy_follow_status'
,
row
.
status
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"appointmentNo"
label=
"预约编号"
width=
"200"
sortable
/>
<el-table-column
prop=
"signDate"
label=
"签单日"
width=
"200"
sortable
/>
<el-table-column
prop=
"policyBizId"
label=
"最晚缴费日"
width=
"200"
sortable
/>
<el-table-column
prop=
"policyHolder"
label=
"投保人"
width=
"150"
sortable
/>
<el-table-column
prop=
"policyNo"
label=
"受保人"
width=
"150"
sortable
/>
<el-table-column
prop=
"insuranceCompany"
label=
"保险公司"
width=
"200"
sortable
/>
<el-table-column
prop=
"productName"
label=
"产品计划"
width=
"200"
sortable
/>
<el-table-column
prop=
"paymentTerm"
label=
"缴费年期"
width=
"120"
sortable
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"80"
>
<
template
#
default=
"{ row }"
>
<el-popover
placement=
"right"
:width=
"200"
trigger=
"click"
>
<template
#
reference
>
<el-icon>
<MoreFilled
/>
</el-icon>
</
template
>
</el-dropdown>
</div>
<!-- <el-button text size="primary" @click="handleView(scope.row)"> 查看 </el-button> -->
<!-- <el-button text size="primary" @click="handleStatus(scope.row)"> 跟进 </el-button>
<el-button text type="warning" @click="handleEditStatus(scope.row)">
修改状态
</el-button> -->
<el-menu
@
select=
"handleSelect($event, row)"
popper-class=
"custom-menu"
>
<el-menu-item
:index=
"item.value"
v-for=
"item in dropdownItems"
:key=
"item.value"
>
{{
item.label
}}
</el-menu-item>
</el-menu>
</el-popover>
</template>
</el-table-column>
</el-table>
</template>
</CommonPage>
<!-- 弹窗-->
<CommonDialog
dialogTitle=
'修改状态'
dialogWidth=
'80%'
:openDialog=
editStatusDialogFlag
:showAction=
'true'
:showClose=
'true'
@
close=
'editStatusDialogFlag = false'
@
confirm=
'handleEditStatusSubmit'
>
<SearchForm
ref=
"editStatusFormRef"
:config=
"editStatusFormConfig"
v-model=
"editStatusFormData"
/>
</CommonDialog>
<!-- 查看关联记录 -->
<CommonDialog
dialogTitle=
'查看关联记录'
dialogWidth=
'80%'
:openDialog=
viewRelatedDialogFlag
:showAction=
'false'
:showClose=
'true'
@
close=
'viewRelatedDialogFlag = false'
>
<el-table
:data=
"relateRecordTableData"
style=
"width: 100%"
>
<el-table-column
fixed
prop=
"followDate"
label=
"流程编号"
width=
"150"
/>
<el-table-column
prop=
"name"
label=
"客户姓名"
width=
"120"
/>
<el-table-column
prop=
"state"
label=
"创建时间"
width=
"120"
sortable
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"viewRelatedDetail(row)"
>
查看
</el-button>
<el-button
link
type=
"danger"
size=
"small"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</CommonDialog>
<!-- 查看详情、更新数据 -->
<CommonDialog
:dialogTitle=
'mode === "viewDetail" ? "查看详情" : "更新数据"'
dialogWidth=
'80%'
:openDialog=
viewDetailDialogFlag
:showAction=
'false'
:showClose=
'true'
@
close=
'viewDetailDialogFlag = false'
@
confirm=
'handleUpdateSubmit'
>
<PolicyDetail
v-model=
"policyDetailFormData"
@
submit=
"onSubmit"
@
cancel=
"showDialog = false"
/>
</CommonDialog>
<!-- 分页 -->
<div
class=
"pagination"
>
<el-pagination
v-model:current-page=
"pagination.currentPage"
v-model:page-size=
"pagination.pageSize"
:page-sizes=
"[10, 20, 50, 100]"
:total=
"pagination.total"
layout=
"total, sizes, prev, pager, next, jumper"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
/>
</div>
</el-card>
<!-- 使用查看数据详情组件 -->
<PolicyDetailDialog
:visible=
"viewDialogVisible"
:detail-data=
"currentRow"
:policy-follow-status-list=
"policyFollowStatusList"
title=
"新单跟进详情"
:expected-commission-list=
"expectedCommissionList"
:policy-fortune-list=
"policyFortuneList"
@
close=
"handleDetailClose"
/>
<el-dialog
title=
"修改新单状态"
v-model=
"editStatus"
width=
"500px"
append-to-body
>
<div
style=
"height: 10vh"
>
<el-form>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"状态"
>
<el-select
v-model=
"form.status"
placeholder=
"请选择"
>
<el-option
v-for=
"item in currentPolicyRow.nextStatusList"
:label=
"item.itemLabel"
:value=
"item.itemValue"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<
template
#
footer
>
<div
class=
"dialog-footer"
>
<el-button
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"canelEdit"
>
取 消
</el-button>
</div>
</
template
>
</el-dialog>
</div>
</template>
<!-- {
"code": 200,
"msg": "生成预计发佣正在处理....,稍后查看预计发佣列表",
"data": null
} -->
<
script
setup
>
import
{
ref
,
reactive
,
onMounted
}
from
'vue'
import
{
ref
,
reactive
,
computed
,
watch
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
axios
from
'axios'
import
CommonPage
from
'@/components/commonPage'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
import
CommonDialog
from
'@/components/commonDialog'
import
{
loadDicts
,
getDictLabel
}
from
'@/utils/useDict'
import
useUserStore
from
'@/store/modules/user'
import
{
safeDownload
}
from
'@/utils/safeDownload'
import
{
getPolicyFollowList
,
getExpectedCommissionList
,
changePolicyStatus
,
policyFollowReport
}
from
'@/api/sign/underwritingMain'
import
{
getToken
}
from
'@/utils/auth'
import
{
listType
}
from
'@/api/system/dict/type'
import
date
from
'@/utils/date'
import
PolicyDetailDialog
from
'@/components/PolicyDetailDialog/index.vue'
import
{
numberWithCommas
}
from
'@/utils/index.js'
import
{
getPolicyFortuneList
}
from
'@/api/financial/commission'
const
{
proxy
}
=
getCurrentInstance
()
const
router
=
useRouter
()
// 通过dictType=csf_policy_follow_status获取新单状态字典值,获取对象中的dictItemList
const
policyFollowStatusList
=
ref
([])
const
commissionStatusList
=
ref
([])
const
fortuneStatusList
=
ref
([])
const
currencyTypeOptions
=
ref
([])
const
currentPolicyRow
=
ref
({})
//当前保单
const
editStatus
=
ref
(
false
)
//新单信息状态
const
data
=
reactive
({
form
:
{}
})
const
{
form
}
=
toRefs
(
data
)
const
canelEdit
=
()
=>
{
editStatus
.
value
=
false
form
.
value
=
{}
}
// 修改新单状态
const
submitForm
=
()
=>
{
let
obj
=
{
policyBizId
:
currentPolicyRow
.
value
.
policyBizId
,
status
:
form
.
value
.
status
}
changePolicyStatus
(
obj
).
then
(
response
=>
{
if
(
response
.
code
==
200
)
{
proxy
.
$modal
.
msgSuccess
(
'新单状态修改成功'
)
editStatus
.
value
=
false
form
.
value
=
{}
fetchTableData
()
}
})
}
const
getLists
=
()
=>
{
listType
({
typeList
:
[
'csf_policy_follow_status'
,
'csf_expected_commission_status'
,
'csf_fortune_status'
,
'bx_currency_type'
]
})
.
then
(
res
=>
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
statusData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'csf_policy_follow_status'
)
policyFollowStatusList
.
value
=
statusData
?.
dictItemList
||
[]
const
commissionStatusData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'csf_expected_commission_status'
)
commissionStatusList
.
value
=
commissionStatusData
?.
dictItemList
||
[]
const
fortuneStatusData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'csf_fortune_status'
)
fortuneStatusList
.
value
=
fortuneStatusData
?.
dictItemList
||
[]
// 处理币种字典值
const
currencyData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'bx_currency_type'
)
if
(
currencyData
)
{
currencyData
?.
dictItemList
.
forEach
(
item
=>
{
item
.
value
=
item
.
itemValue
item
.
label
=
item
.
itemLabel
})
}
currencyTypeOptions
.
value
=
currencyData
?.
dictItemList
||
[]
}
else
{
policyFollowStatusList
.
value
=
[]
commissionStatusList
.
value
=
[]
fortuneStatusList
.
value
=
[]
currencyTypeOptions
.
value
=
[]
}
})
.
catch
(
error
=>
{
console
.
error
(
'获取状态列表失败:'
,
error
)
policyFollowStatusList
.
value
=
[]
})
}
// 返回数据中状态需要转换为字典值
const
convertStatusToDict
=
(
type
=
1
,
status
)
=>
{
const
arr
=
type
===
1
?
policyFollowStatusList
:
type
===
2
?
commissionStatusList
:
fortuneStatusList
const
dictItem
=
arr
.
value
.
find
(
item
=>
item
.
itemValue
==
status
)
return
dictItem
?.
itemLabel
??
status
}
const
uploadUrl
=
ref
(
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/csf/api/policy_follow/upload/excel'
)
// 搜索表单数据
const
searchForm
=
reactive
({
policyBizId
:
''
,
// 新单编号(对应接口的policyBizId)
policyNo
:
''
,
// 保单编号
customerName
:
''
,
// 客户姓名
customerBizId
:
''
,
// 客户编号(对应接口的customerBizId)
signDateRange
:
[],
// 签单时间范围
status
:
''
,
// 新单状态(对应接口的status)
// 高级筛选字段
insurer
:
''
,
// 保险公司
productCode
:
''
// 产品代码(对应接口的productCode)
})
// 预计来佣列表
const
expectedCommissionList
=
ref
([])
const
policyFortuneList
=
ref
([])
const
getPolicyFortuneLists
=
async
policyNo
=>
{
import
PolicyDetail
from
'./policyDetail.vue'
const
policyDetailFormData
=
ref
({})
const
userStore
=
useUserStore
()
// 分页相关
const
currentPage
=
ref
(
1
)
const
pageSize
=
ref
(
10
)
const
pageTotal
=
ref
(
0
)
const
loading
=
ref
(
false
)
// 搜索表单数据
const
searchFormData
=
reactive
({})
const
selectedRow
=
ref
(
null
)
// 弹窗相关
const
editStatusDialogFlag
=
ref
(
false
)
// 修改状态
const
editStatusFormData
=
ref
({})
const
editStatusFormRef
=
ref
(
null
)
const
editStatusFormConfig
=
ref
([
{
type
:
'select'
,
prop
:
'status'
,
label
:
'新单状态'
,
dictType
:
'csf_policy_follow_status'
},
{
type
:
'date'
,
prop
:
'policyEffectiveDate'
,
label
:
'保单生效日'
,
},
{
type
:
'date'
,
prop
:
'policyInsureDate'
,
label
:
'保单核保日'
,
},
])
// 查看关联记录
const
viewRelatedDialogFlag
=
ref
(
false
)
const
relateRecordTableData
=
ref
([])
const
viewRelatedDetail
=
(
row
)
=>
{
ElMessage
.
info
(
`查看关联记录详情:
${
JSON
.
stringify
(
row
)}
`
)
}
// 提交修改状态
const
handleEditStatusSubmit
=
async
()
=>
{
try
{
const
response
=
await
getPolicyFortuneList
({
policyNo
})
if
(
response
.
code
===
200
&&
response
.
data
)
{
policyFortuneList
.
value
=
response
.
data
.
records
||
[]
policyFortuneList
.
value
.
forEach
(
item
=>
{
item
.
fortuneStatusLabel
=
convertStatusToDict
(
3
,
item
.
status
)
})
await
editStatusFormRef
.
value
.
validate
()
const
res
=
await
changePolicyStatus
({
policyBizId
:
selectedRow
.
value
.
policyBizId
,
...
editStatusFormData
.
value
})
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'修改状态成功'
)
editStatusDialogFlag
.
value
=
false
loadTableData
()
}
else
{
policyFortuneList
.
value
=
[]
ElMessage
.
error
(
res
.
msg
||
'修改状态失败'
)
}
}
catch
(
error
)
{
console
.
error
(
'获取预计来佣列表失败:'
,
error
)
policyFortuneList
.
value
=
[]
console
.
error
(
'修改状态失败'
,
error
)
}
}
// 表格数据
const
tableData
=
ref
([])
const
tableLoading
=
ref
(
false
)
const
selectedRows
=
ref
([])
// 查看详情弹窗相关
const
viewDialogVisible
=
ref
(
false
)
const
currentRow
=
ref
({})
// 分页数据
const
pagination
=
reactive
({
currentPage
:
1
,
// 当前页码(对应接口的pageNo)
pageSize
:
10
,
// 每页条数(对应接口的pageSize)
total
:
0
,
// 总条数
sortField
:
''
,
// 排序字段
sortOrder
:
''
// 排序方向
})
// 查看详情、更新数据
const
viewDetailDialogFlag
=
ref
(
false
)
// 处理查看
const
handleView
=
async
row
=>
{
console
.
log
(
'查看详情:'
,
row
)
currentRow
.
value
=
{
...
row
}
viewDialogVisible
.
value
=
true
fetchExpectedCommissionList
(
row
.
policyNo
)
getPolicyFortuneLists
(
row
.
policyNo
)
const
onSubmit
=
(
data
)
=>
{
console
.
log
(
'提交的数据:'
,
data
)
// 调用 API 保存
alert
(
'提交成功!'
)
viewDetailDialogFlag
.
value
=
false
}
const
handleReport
=
async
row
=>
{
try
{
const
res
=
await
policyFollowReport
(
row
.
policyBizId
)
console
.
log
(
'pdf请求'
,
res
)
// 创建 Blob 对象
const
blob
=
new
Blob
([
res
],
{
type
:
'application/pdf'
})
// 创建对象 URL
const
url
=
window
.
URL
.
createObjectURL
(
blob
)
// 在新窗口打开
window
.
open
(
url
,
'_blank'
)
//下载得方式
// const blob = new Blob([res], { type: 'application/pdf' })
// const url = window.URL.createObjectURL(blob)
// // 创建下载链接
// const link = document.createElement('a')
// link.href = url
// link.download = '签约单.pdf' // 设置文件名
// link.click()
// // 清理 URL 对象
// window.URL.revokeObjectURL(url)
const
handleClose
=
()
=>
{
// 可选:清空数据
}
// 获取新单状态,字典值转化方法
onMounted
(
async
()
=>
{
try
{
await
loadDicts
([
'csf_policy_follow_status'
])
}
catch
(
error
)
{
console
.
error
(
'导出失败:'
,
error
)
console
.
error
(
'字典加载失败'
,
error
)
}
finally
{
loading
.
value
=
false
}
}
// 处理详情弹窗关闭
const
handleDetailClose
=
()
=>
{
viewDialogVisible
.
value
=
false
console
.
log
(
'详情弹窗已关闭'
)
}
// Excel导入相关
const
selectedFile
=
ref
(
null
)
const
importLoading
=
ref
(
false
)
// 页面加载时获取数据
onMounted
(()
=>
{
fetchTableData
()
getLists
()
})
// 按钮事件处理
const
handleAdd
=
()
=>
{
ElMessage
.
info
(
'点击新增按钮'
)
}
const
handleImport
=
()
=>
{
ElMessage
.
info
(
'点击导入按钮'
)
}
const
handleExport
=
()
=>
{
ElMessage
.
info
(
'点击导出按钮'
)
}
const
handleReset
=
()
=>
{
// 重置搜索表单
searchFormRef
.
value
.
resetForm
()
searchParams
.
value
=
{}
console
.
log
(
'表单已重置'
)
// 重新加载数据
loadTableData
()
}
const
handleQuery
=
async
()
=>
{
loadTableData
()
}
const
visibleDefaultButtons
=
ref
([
'reset'
,
'query'
])
// 按钮配置
const
operationBtnList
=
ref
([
{
key
:
'reset'
,
direction
:
'right'
,
click
:
handleReset
},
{
key
:
'query'
,
direction
:
'right'
,
click
:
handleQuery
}
])
// 获取列表数据
const
fetchTableData
=
async
()
=>
{
tableLoading
.
value
=
true
try
{
// 构造接口请求参数
const
params
=
{
pageNo
:
pagination
.
currentPage
,
// 注意:如果后端是从0开始的页码,需要减1
pageSize
:
pagination
.
pageSize
,
sortField
:
pagination
.
sortField
,
sortOrder
:
pagination
.
sortOrder
,
status
:
searchForm
.
status
,
policyBizId
:
searchForm
.
policyBizId
,
policyNo
:
searchForm
.
policyNo
,
customerName
:
searchForm
.
customerName
,
customerBizId
:
searchForm
.
customerBizId
,
insurer
:
searchForm
.
insurer
,
productCode
:
searchForm
.
productCode
,
// 签单时间范围需要根据后端要求的参数名进行调整
// 例如:如果后端需要startSignDate和endSignDate
...(
searchForm
.
signDateRange
&&
searchForm
.
signDateRange
.
length
===
2
&&
{
startSignDate
:
date
.
formatToDate
(
searchForm
.
signDateRange
[
0
])
+
' 00:00:00'
,
endSignDate
:
date
.
formatToDate
(
searchForm
.
signDateRange
[
1
])
+
' 23:59:59'
})
// 分页事件
const
handleSizeChange
=
(
val
)
=>
{
pageSize
.
value
=
val
loadTableData
()
}
const
handleCurrentChange
=
(
val
)
=>
{
currentPage
.
value
=
val
loadTableData
()
}
// 表格数据
const
tableData
=
ref
([])
const
searchFormRef
=
ref
(
null
)
const
searchParams
=
ref
({})
const
searchConfig
=
ref
([
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
},
{
type
:
'select'
,
prop
:
'status'
,
label
:
'新单状态'
,
dictType
:
'csf_policy_follow_status'
},
{
type
:
'input'
,
prop
:
'appointmentNo'
,
label
:
'预约编号'
},
{
type
:
'daterange'
,
prop
:
'signDate'
,
label
:
'签单日'
,
startPlaceholder
:
'开始时间'
,
endPlaceholder
:
'结束时间'
},
{
type
:
'date'
,
prop
:
'latestPaymentDate'
,
label
:
'最晚缴费日'
,
placeholder
:
'请选择'
},
{
type
:
'select'
,
prop
:
'insuranceCompanyBizIdList'
,
label
:
'保险公司'
,
api
:
'/insurance/base/api/insuranceCompany/page'
,
keywordField
:
'queryContent'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入保险公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
valueKey
:
'insuranceCompanyBizId'
,
labelKey
:
'abbreviation'
,
multiple
:
true
,
transform
:
(
res
)
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
}
// 调用后台接口
const
response
=
await
getPolicyFollowList
(
params
)
// 处理接口响应
if
(
response
.
code
===
200
)
{
const
result
=
response
.
data
// 将接口返回的数据映射到表格
tableData
.
value
=
result
.
records
.
map
(
record
=>
({
...
record
}))
// console.log('tableData',tableData.value)
// 更新分页信息
pagination
.
total
=
result
.
total
pagination
.
currentPage
=
result
.
current
||
pagination
.
currentPage
pagination
.
pageSize
=
result
.
size
||
pagination
.
pageSize
}
else
{
// 接口返回错误信息
ElMessage
.
error
(
`获取数据失败:
${
response
.
data
.
msg
||
'未知错误'
}
`
)
tableData
.
value
=
[]
pagination
.
total
=
0
},
{
type
:
'select'
,
prop
:
'productLaunchBizIdList'
,
label
:
'产品计划'
,
api
:
'/product/api/relProjectProductLaunch/parameter/page'
,
keywordField
:
'productName'
,
requestParams
:
{
tenantBizId
:
userStore
.
projectInfo
.
tenantBizId
||
''
,
projectBizId
:
userStore
.
projectInfo
.
projectBizId
||
''
,
fieldBizId
:
'field_olk1qZe81qHHKXbw'
,
fieldValueBizId
:
'field_value_uOfJH5ucA2YwJpbn'
,
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入产品计划名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
valueKey
:
'productLaunchBizId'
,
labelKey
:
'productName'
,
multiple
:
true
,
transform
:
(
res
)
=>
{
return
res
?.
data
.
records
||
[]
}
}
catch
(
error
)
{
// 捕获网络或其他异常
console
.
error
(
'请求失败:'
,
error
)
ElMessage
.
error
(
'网络异常,请稍后重试'
)
tableData
.
value
=
[]
pagination
.
total
=
0
}
finally
{
tableLoading
.
value
=
false
}
,
{
type
:
'input'
,
prop
:
'paymentTerm'
,
label
:
'缴费年期'
,
inputType
:
'decimal'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
}
}
// 获取预计来佣列表
const
fetchExpectedCommissionList
=
async
(
policyNo
,
pageNo
=
1
,
pageSize
=
100
)
=>
{
])
const
loadTableData
=
async
()
=>
{
loading
.
value
=
true
searchParams
.
value
=
searchFormRef
.
value
.
getFormData
()
||
{}
console
.
log
(
searchParams
.
value
)
try
{
// 构造接口请求参数
const
params
=
{
pageNo
:
pageNo
,
// 注意:如果后端是从0开始的页码,需要减1
pageSize
:
pageSize
,
policyNo
:
policyNo
}
// 调用后台接口
const
response
=
await
getExpectedCommissionList
(
params
)
// 处理接口响应
if
(
response
.
code
===
200
)
{
const
result
=
response
.
data
// 将接口返回的数据映射到表格
expectedCommissionList
.
value
=
result
.
records
.
map
(
record
=>
({
...
record
,
commissionStatusLabel
:
convertStatusToDict
(
2
,
record
.
status
)
}))
}
else
{
// 接口返回错误信息
ElMessage
.
error
(
`获取数据失败:
${
response
.
data
.
msg
||
'未知错误'
}
`
)
expectedCommissionList
.
value
=
[]
...
searchParams
.
value
,
signDateStart
:
searchParams
.
value
?.
signDate
[
0
]
||
undefined
,
signDateEnd
:
searchParams
.
value
?.
signDate
[
1
]
||
undefined
,
signDate
:
undefined
,
pageNo
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
}
const
response
=
await
getPolicyFollowList
(
params
)
tableData
.
value
=
response
.
data
.
records
pageTotal
.
value
=
response
.
data
.
total
pageSize
.
value
=
response
.
data
.
size
}
catch
(
error
)
{
// 捕获网络或其他异常
console
.
error
(
'请求失败:'
,
error
)
ElMessage
.
error
(
'网络异常,请稍后重试'
)
expectedCommissionList
.
value
=
[]
ElMessage
.
error
(
error
.
message
||
'查询失败'
)
}
finally
{
loading
.
value
=
false
}
}
// 增加通过表格排序,排序字段sortField,升降序sortOrder
const
handleSortChange
=
column
=>
{
pagination
.
sortField
=
column
.
prop
pagination
.
sortOrder
=
column
.
order
===
'ascending'
?
'ascend'
:
'descend'
fetchTableData
()
}
// 处理查询
const
handleSearch
=
()
=>
{
pagination
.
currentPage
=
1
fetchTableData
()
ElMessage
.
success
(
'查询成功'
)
}
// 重置表单
const
resetForm
=
()
=>
{
searchForm
.
name
=
''
searchForm
.
status
=
''
searchForm
.
policyBizId
=
''
searchForm
.
policyNo
=
''
searchForm
.
customerName
=
''
searchForm
.
customerBizId
=
''
searchForm
.
insurer
=
''
searchForm
.
productCode
=
''
searchForm
.
signDateRange
=
[]
}
// 处理分页大小变化
const
handleSizeChange
=
val
=>
{
pagination
.
pageSize
=
val
fetchTableData
()
}
// 处理分页页码变化
const
handleCurrentChange
=
val
=>
{
pagination
.
currentPage
=
val
fetchTableData
()
}
// 处理表格选择变化
const
handleSelectionChange
=
rows
=>
{
selectedRows
.
value
=
rows
}
// 表格行样式
const
tableRowClassName
=
({
row
})
=>
{
return
row
.
status
===
'inactive'
?
'row-inactive'
:
''
}
// 处理文件选择
const
handleFileChange
=
file
=>
{
selectedFile
.
value
=
file
.
raw
}
// 处理导入 - 调整为multipart/form-data格式
const
handleImport
=
async
()
=>
{
if
(
!
selectedFile
.
value
)
{
ElMessage
.
warning
(
'请先选择文件'
)
return
}
// 二次确认
ElMessageBox
.
confirm
(
`确定要导入"
${
selectedFile
.
value
.
name
}
"吗?`
,
'导入确认'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'info'
})
.
then
(
async
()
=>
{
importLoading
.
value
=
true
try
{
// 创建FormData对象,用于multipart/form-data格式
const
formData
=
new
FormData
()
// 将文件添加到FormData,注意参数名要与后端保持一致
formData
.
append
(
'file'
,
selectedFile
.
value
)
// 可以添加其他参数(如果后端需要)
// formData.append('otherParam', 'value')
// 调用上传接口
const
response
=
await
axios
.
post
(
uploadUrl
.
value
,
formData
,
{
headers
:
{
'Content-Type'
:
'multipart/form-data'
,
// 指定内容类型,
Authorization
:
'Bearer '
+
getToken
()
}
})
// 处理接口响应
if
(
response
.
data
.
code
===
200
)
{
ElMessage
.
success
(
'导入成功'
)
selectedFile
.
value
=
null
// 重新获取表格数据
fetchTableData
()
}
else
{
ElMessage
.
error
(
`导入失败:
${
response
.
data
.
msg
||
'未知错误'
}
`
)
// 如果有错误详情,可以展示
if
(
response
.
data
.
msg
)
{
console
.
error
(
'导入错误详情:'
,
response
.
data
.
msg
)
}
}
}
catch
(
error
)
{
console
.
error
(
'上传失败:'
,
error
)
ElMessage
.
error
(
'文件上传失败,请稍后重试'
)
}
finally
{
importLoading
.
value
=
false
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'查看详情'
,
value
:
'viewDetail'
},
{
label
:
'更新数据'
,
value
:
'updateData'
},
{
label
:
'生成签单报告'
,
value
:
'generateReport'
},
{
label
:
'设置新单状态'
,
value
:
'setNewSingleStatus'
},
{
label
:
'查看关联'
,
value
:
'viewRelated'
},
// { label: '查看记录', value: 'viewRecord' },
]
const
mode
=
ref
(
'viewDetail'
)
const
handleSelect
=
async
(
e
,
row
)
=>
{
selectedRow
.
value
=
{
...
row
}
mode
.
value
=
e
console
.
log
(
e
,
row
)
switch
(
e
)
{
case
'viewDetail'
:
// ElMessage.info('查看详情')
viewDetailDialogFlag
.
value
=
true
// viewDetailFormData.value = JSON.parse(JSON.stringify(mockEditData))
// 赋值已有数据(深拷贝避免引用问题)
// Object.assign(formData, JSON.parse(JSON.stringify(mockEditData)))
break
case
'updateData'
:
ElMessage
.
info
(
'更新数据'
)
break
case
'setNewSingleStatus'
:
// ElMessage.info('设置新单状态')
editStatusDialogFlag
.
value
=
true
editStatusFormData
.
value
=
{
status
:
row
.
status
}
})
.
catch
(()
=>
{
// 用户取消导入
ElMessage
.
info
(
'已取消导入'
)
})
}
// 下载模板
const
downloadTemplate
=
()
=>
{
// 下载地址
const
templateUrl
=
'https://yd-ali-oss.oss-cn-shanghai-finance-1-pub.aliyuncs.com/xlsx/2025/10/14/54ce715eabab4f1abd8652ba0fca0c51.xlsx'
// 修改下载文件名
const
fileName
=
'保单导入模板.xlsx'
// 下载文件
window
.
open
(
templateUrl
,
'_blank'
,
`download=
${
fileName
}
-
${
new
Date
().
getTime
()}
`
)
}
import
{
updateToPolicyLib
}
from
'@/api/sign/underwritingMain'
// 处理更新至保单库
const
handleUpdateToPolicyLib
=
()
=>
{
ElMessageBox
.
confirm
(
`确定要更新选中的
${
selectedRows
.
value
.
length
}
条数据至保单库吗?`
,
'更新确认'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}
)
.
then
(()
=>
{
// 调用更新至保单库接口
updateToPolicyLib
({
policyNoList
:
selectedRows
.
value
.
map
(
row
=>
row
.
policyNo
)
}).
then
(
response
=>
{
if
(
response
.
code
===
200
)
{
ElMessage
.
success
(
'更新成功'
)
}
else
{
ElMessage
.
error
(
`更新失败:
${
response
.
msg
||
'未知错误'
}
`
)
}
})
})
.
catch
(()
=>
{
ElMessage
({
type
:
'info'
,
message
:
'取消更新至保单库'
})
})
}
// 格式化文件大小
const
formatFileSize
=
bytes
=>
{
if
(
bytes
===
0
)
return
'0 B'
const
k
=
1024
const
sizes
=
[
'B'
,
'KB'
,
'MB'
,
'GB'
]
const
i
=
Math
.
floor
(
Math
.
log
(
bytes
)
/
Math
.
log
(
k
))
return
parseFloat
((
bytes
/
Math
.
pow
(
k
,
i
)).
toFixed
(
2
))
+
' '
+
sizes
[
i
]
}
// 新单跟进详情
const
handleStatus
=
row
=>
{
router
.
push
({
path
:
'/sign/underwritingMain/followUpDetail'
,
query
:
{
policyBizId
:
row
.
policyBizId
,
policyNo
:
row
.
policyNo
,
type
:
'edit'
,
source
:
'policyList'
,
embed
:
true
,
appointmentNo
:
row
.
appointmentNo
,
appointmentBizId
:
row
.
appointmentBizId
}
})
}
const
handleEditStatus
=
row
=>
{
currentPolicyRow
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
row
))
editStatus
.
value
=
true
}
</
script
>
<
style
scoped
>
.btnCon
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
.data-management-page
{
padding
:
20px
;
/* max-width: 1600px; */
margin
:
0
auto
;
}
.page-header
{
margin-bottom
:
20px
;
}
.search-card
{
margin-bottom
:
20px
;
padding
:
15px
20px
;
}
.search-buttons
{
display
:
flex
;
gap
:
10px
;
}
.import-area
{
margin-bottom
:
20px
;
}
.import-card
{
padding
:
10px
;
background-color
:
#f6ffed
;
border
:
1px
solid
#b7eb8f
;
}
.import-content
{
display
:
flex
;
flex-direction
:
column
;
gap
:
15px
;
}
.import-actions
{
display
:
flex
;
align-items
:
center
;
gap
:
10px
;
}
.upload-excel
{
display
:
inline-block
;
}
/* 文件信息显示样式 */
.file-info
{
margin-top
:
15px
;
padding
:
12px
16px
;
background-color
:
#f5f7fa
;
border-radius
:
4px
;
border
:
1px
solid
#e4e7ed
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
}
.file-info-content
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
}
.file-info-content
.el-icon
{
color
:
#409eff
;
font-size
:
16px
;
}
.file-name
{
font-weight
:
500
;
color
:
#303133
;
}
.file-size
{
color
:
#909399
;
font-size
:
12px
;
}
.confirm-import-btn
{
margin-left
:
12px
;
}
/* 下载模板按钮样式 */
.download-template-btn
{
color
:
#409eff
;
font-size
:
12px
;
padding
:
8px
12px
;
}
.download-template-btn
:hover
{
background-color
:
#ecf5ff
;
}
.table-card
{
padding
:
15px
20px
;
}
.table-actions
{
margin-bottom
:
15px
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
}
.pagination
{
margin-top
:
15px
;
text-align
:
right
;
}
/* 禁用状态行样式 */
::v-deep
.row-inactive
{
background-color
:
#f5f5f5
;
color
:
#9e9e9e
;
}
.form-item
{
display
:
flex
;
flex-direction
:
column
;
gap
:
6px
;
}
.form-label
{
font-size
:
14px
;
color
:
#4e5969
;
font-weight
:
500
;
line-height
:
1
;
padding-left
:
2px
;
}
.search-row
{
margin-bottom
:
18px
;
}
.search-row
:last-child
{
margin-bottom
:
0
;
}
.search-buttons
{
display
:
flex
;
gap
:
10px
;
justify-content
:
flex-start
;
align-items
:
flex-end
;
padding-bottom
:
2px
;
}
.advanced-search
{
margin-top
:
18px
;
border-top
:
1px
dashed
#e5e7eb
;
padding-top
:
18px
;
}
.el-collapse-item__content
{
padding-top
:
15px
!important
;
}
/* 转介人详情样式 */
.broker-details
{
max-height
:
200px
;
overflow-y
:
auto
;
}
.broker-item
{
padding
:
8px
0
;
}
.broker-item
p
{
margin
:
4px
0
;
font-size
:
12px
;
line-height
:
1.4
;
}
.broker-item
strong
{
color
:
#606266
;
}
.no-broker
{
color
:
#909399
;
font-size
:
12px
;
break
case
'viewRelated'
:
// ElMessage.info('查看关联')
viewRelatedDialogFlag
.
value
=
true
break
case
'generateReport'
:
generateReport
(
row
)
break
case
'viewRecord'
:
ElMessage
.
info
(
'查看记录'
)
break
default
:
break
}
}
/* 响应式调整 */
@media
(
max-width
:
1200px
)
{
.import-actions
{
flex-wrap
:
wrap
;
const
generateReport
=
async
(
row
)
=>
{
if
(
!
selectedRow
.
value
)
{
ElMessage
.
warning
(
'请选择要生成报告的新单'
)
return
}
.download-template-btn
{
margin-top
:
10px
;
try
{
const
response
=
await
policyFollowReport
(
row
.
policyBizId
)
// 文件名设置为应收款导出_yyyy-MM-dd hh:mm:ss.xlsx,不需要-,用字符串
const
fileName
=
`签单报告_
${
new
Date
().
toLocaleString
().
replace
(
/
\/
/g
,
''
).
replace
(
/:/g
,
''
).
replace
(
/
\s
/g
,
''
)}
.pdf`
await
safeDownload
(
response
,
fileName
,
'application/pdf;charset=utf-8'
)
ElMessage
.
success
(
'报告生成成功'
)
// 可以添加下载报告的逻辑
}
catch
(
error
)
{
ElMessage
.
error
(
error
.
message
||
'报告生成失败'
)
}
}
.file-info
{
flex-direction
:
column
;
align-items
:
flex-start
;
gap
:
12px
;
const
handleUpdateSubmit
=
async
()
=>
{
if
(
!
selectedRow
.
value
)
{
ElMessage
.
warning
(
'请选择要更新的新单'
)
return
}
.confirm-import-btn
{
margin-left
:
0
;
align-self
:
flex-end
;
try
{
const
response
=
await
updatePolicyFollow
(
selectedRow
.
value
)
ElMessage
.
success
(
'更新成功'
)
// 刷新当前页数据
loadTableData
()
// 关闭弹窗
viewDetailDialogFlag
.
value
=
false
}
catch
(
error
)
{
ElMessage
.
error
(
error
.
message
||
'更新失败'
)
}
}
@media
(
max-width
:
992px
)
{
.search-card
.el-row
{
row-gap
:
15px
;
}
.search-card
.el-col
{
flex
:
0
0
50%
;
max-width
:
50%
;
}
.search-buttons
{
justify-content
:
flex-start
;
}
}
@media
(
max-width
:
768px
)
{
.search-card
.el-col
{
flex
:
0
0
100%
;
max-width
:
100%
;
}
.table-actions
{
flex-direction
:
column
;
align-items
:
flex-start
;
gap
:
10px
;
}
.import-actions
{
flex-direction
:
column
;
align-items
:
flex-start
;
}
.download-template-btn
{
margin-top
:
10px
;
}
}
/* 防止表头换行 */
::v-deep
.el-table
.el-table__header-wrapper
.el-table__cell
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
</
script
>
/* 表头单元格内容不换行 */
::v-deep
.el-table
.el-table__header-wrapper
.el-table__cell
.cell
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
</
style
>
<
style
scoped
></
style
>
\ No newline at end of file
src/views/sign/underwritingMain/policyDetail.vue
0 → 100644
View file @
d4982277
<!-- components/FormPage.vue -->
<
template
>
<div
class=
"form-page"
>
<el-form
ref=
"formRef"
:model=
"localData"
label-width=
"120px"
size=
"default"
>
<!-- Tabs -->
<el-tabs
v-model=
"activeTab"
@
tab-click=
"handleTabClick"
>
<el-tab-pane
label=
"基础信息"
name=
"basic"
></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>
<el-tab-pane
label=
"附件"
name=
"attachment"
></el-tab-pane>
</el-tabs>
<!-- 基础信息 Tab 内容 -->
<div
v-if=
"activeTab === 'basic'"
class=
"tab-content"
>
<!-- 签单信息 -->
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
基础信息
</h3>
<SearchForm
ref=
"basicInfoFormRef"
:config=
"basicInfoFormConfig"
v-model=
"basicInfoFormData"
/>
</div>
<!-- 保单信息 -->
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
保单信息
</h3>
<SearchForm
ref=
"policyInfoFormRef"
:config=
"policyInfoFormConfig"
v-model=
"policyInfoFormData"
/>
</div>
<!-- 基本计划 -->
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
基本计划
</h3>
<SearchForm
ref=
"basicPlanFormRef"
:config=
"basicPlanFormConfig"
v-model=
"basicPlanFormData"
/>
</div>
<!-- 附加计划(可编辑表格) -->
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
附加计划
</h3>
<el-button
type=
"primary"
size=
"default"
@
click=
"addAdditionalPlan"
>
+ 新增
</el-button>
<el-table
:data=
"localData.additionalPlans || []"
style=
"width: 100%; margin-top: 10px"
border
>
<el-table-column
prop=
"product"
label=
"产品名称"
width=
"180"
>
<template
#
default=
"
{ row }">
<el-input
v-model=
"row.product"
size=
"default"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"frequency"
label=
"付款频率"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-select
v-model=
"row.frequency"
size=
"default"
placeholder=
"选择"
>
<el-option
label=
"月付"
value=
"monthly"
/>
<el-option
label=
"年付"
value=
"yearly"
/>
</el-select>
</
template
>
</el-table-column>
<el-table-column
prop=
"term"
label=
"保障期限"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.term"
size=
"default"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"periods"
label=
"供款期数"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.periods"
size=
"default"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"currency"
label=
"保单币种"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.currency"
size=
"default"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"premium"
label=
"每期保费"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.premium"
size=
"default"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"fee"
label=
"保单征费"
width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.fee"
size=
"default"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"120"
>
<
template
#
default=
"{ $index }"
>
<el-button
size=
"default"
type=
"danger"
@
click=
"deleteRow($index)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
</div>
<!-- 首期缴费 Tab 内容 -->
<div
v-else-if=
"activeTab === 'firstPayment'"
class=
"tab-content"
>
<!-- 签单信息 -->
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
缴费信息
</h3>
<SearchForm
ref=
"firstPremiumFormRef"
:config=
"firstPremiumFormConfig"
v-model=
"firstPremiumFormData"
/>
<h3
class=
"sectionTitle"
>
首期对账信息
</h3>
<el-table
:data=
"firstPremiumTableData"
border
style=
"width: 100%"
>
<el-table-column
prop=
"date"
label=
"申请对账日期"
width=
"180"
/>
<el-table-column
prop=
"name"
label=
"对账状态"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"缴费方式"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"汇款币种"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"汇款日期"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"认定金额"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"认定币种"
width=
"180"
/>
</el-table>
</div>
</div>
<!-- 介绍人 Tab 内容 -->
<div
v-else-if=
"activeTab === 'introducer'"
class=
"tab-content"
>
<!-- 签单信息 -->
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
介绍人信息
</h3>
<h5>
第一位默认是客户主要负责人,客户资料出现在介绍人(主)账号下,其他介绍人不会看到客户信息
</h5>
<el-button
type=
"primary"
>
<el-icon
class=
"el-icon--right"
>
<Upload
/>
</el-icon>
新增
</el-button>
<el-table
:data=
"firstPremiumTableData"
border
style=
"width: 100%"
>
<el-table-column
prop=
"date"
label=
"介绍人姓名"
width=
"180"
/>
<el-table-column
prop=
"name"
label=
"性别"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"内部编号"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"所属团队"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"分配比例"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"备注"
width=
"180"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"handleClick"
>
Detail
</el-button>
<el-button
link
type=
"primary"
size=
"small"
>
Edit
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
</div>
<!-- 邮寄信息 Tab 内容 -->
<div
v-else-if=
"activeTab === 'postal'"
class=
"tab-content"
>
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
邮寄信息
</h3>
<SearchForm
ref=
"postalFormRef"
:config=
"postalFormConfig"
v-model=
"postalFormData"
/>
</div>
</div>
<!-- 关联记录 Tab 内容 -->
<div
v-else-if=
"activeTab === 'related'"
class=
"tab-content"
>
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
关联记录
</h3>
<el-table
:data=
"relatedTableData"
border
style=
"width: 100%"
>
<el-table-column
prop=
"date"
label=
"流程编号"
width=
"180"
/>
<el-table-column
prop=
"name"
label=
"客户姓名"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"创建时间"
width=
"180"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"handleClick"
>
Detail
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
</div>
<!-- 附件 Tab 内容 -->
<div
v-else-if=
"activeTab === 'attachment'"
class=
"tab-content"
>
<div
class=
"section"
>
<h3
class=
"sectionTitle"
>
附件
</h3>
<el-button
type=
"primary"
>
<el-icon
class=
"el-icon--right"
>
<Upload
/>
</el-icon>
上传附件
</el-button>
<el-table
:data=
"attachmentTableData"
border
style=
"width: 100%"
>
<el-table-column
prop=
"date"
label=
"文件名"
width=
"180"
/>
<el-table-column
prop=
"name"
label=
"文件类型"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"上传时间"
width=
"180"
/>
<el-table-column
prop=
"address"
label=
"上传人"
width=
"180"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"handleClick"
>
修改
</el-button><el-button
link
type=
"danger"
size=
"small"
@
click=
"handleClick"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
</div>
<!-- 其他 Tab 占位(你可以按需填充) -->
<div
v-else
class=
"tab-placeholder"
>
<el-empty
description=
"该 Tab 内容待开发"
/>
</div>
<!-- 底部按钮 -->
<div
class=
"form-footer"
>
<el-button
size=
"default"
@
click=
"handleCancel"
>
取消
</el-button>
<el-button
type=
"primary"
size=
"default"
@
click=
"handleSubmit"
>
确认
</el-button>
</div>
</el-form>
</div>
</template>
<
script
setup
>
import
{
ref
,
reactive
,
watch
,
nextTick
}
from
'vue'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
import
{
Delete
,
Edit
,
Search
,
Share
,
Upload
}
from
'@element-plus/icons-vue'
const
basicInfoFormRef
=
ref
()
const
basicInfoFormData
=
ref
({})
const
basicInfoFormConfig
=
ref
([
{
type
:
'date'
,
prop
:
'signDate'
,
label
:
'签单日'
,
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'签单员'
,
dictType
:
'bx_currency_type'
,
},
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'签单员执业编号'
,
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'签单地点'
,
dictType
:
'bx_currency_type'
},
])
// 保单信息
const
policyInfoFormRef
=
ref
()
const
policyInfoFormData
=
ref
({})
const
policyInfoFormConfig
=
ref
([
{
type
:
'date'
,
prop
:
'endDate'
,
label
:
'保单号'
,
},
{
type
:
'date'
,
prop
:
'effectiveDate'
,
label
:
'保单生效日'
,
},
{
type
:
'date'
,
prop
:
'effectiveDate'
,
label
:
'保单截止日'
,
},
{
type
:
'date'
,
prop
:
'underwritingDate'
,
label
:
'保单核保日'
,
},
{
type
:
'date'
,
prop
:
'underwritingDate'
,
label
:
'保单回执日'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'回执状态'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'是否开通直接支付'
,
},
{
type
:
'input'
,
prop
:
'insurer'
,
label
:
'保单持有人'
,
},
{
type
:
'input'
,
prop
:
'insurer'
,
label
:
'保单受保人'
,
},
{
type
:
'select'
,
prop
:
'insuranceType'
,
label
:
'受保人年龄'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'宽限期'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'是否参加递增保障权益'
,
},
])
// 基本计划
const
basicPlanFormRef
=
ref
()
const
basicPlanFormData
=
ref
({})
const
basicPlanFormConfig
=
ref
([
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'保险公司'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'保险险种'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'产品名称'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'付款频率'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'保障期限'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'保额(重疾险)'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'供款期数'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'保单币种'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'每期保费'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'保单征费'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'是否预缴'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'是否追溯'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'回溯日期'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'首期付款方式'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'续期付款方式'
,
},
{
type
:
'select'
,
prop
:
'paymentFrequency'
,
label
:
'红利付款方式'
,
},
])
// 首期保费
const
firstPremiumTableData
=
ref
([])
const
firstPremiumFormRef
=
ref
()
const
firstPremiumFormData
=
ref
({})
const
firstPremiumFormConfig
=
ref
([
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'首期保费'
,
inputType
:
'decimal'
,
decimalDigits
:
2
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,2})?
$/
,
message
:
'最多两位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'保单征费'
,
inputType
:
'decimal'
,
decimalDigits
:
2
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,2})?
$/
,
message
:
'最多两位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'首期缴费方式'
,
dictType
:
'bx_currency_type'
},
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'首期已缴保费'
,
inputType
:
'decimal'
,
decimalDigits
:
2
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,2})?
$/
,
message
:
'最多两位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'首期待缴保费'
,
inputType
:
'decimal'
,
decimalDigits
:
2
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,2})?
$/
,
message
:
'最多两位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'首期缴费总额'
,
inputType
:
'decimal'
,
decimalDigits
:
2
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,2})?
$/
,
message
:
'最多两位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'缴费状态'
,
multiple
:
true
,
dictType
:
'csf_fortune_status'
},
{
type
:
'date'
,
prop
:
'commissionDate'
,
label
:
'最晚缴费日'
,
placeholder
:
'请选择'
},
{
type
:
'textarea'
,
prop
:
'policyNo'
,
label
:
'首期保费优惠'
},
])
// 邮寄信息
const
postalFormRef
=
ref
(
null
)
const
postalFormData
=
ref
({})
const
postalFormConfig
=
ref
([
{
type
:
'input'
,
prop
:
'postalCode'
,
label
:
'寄送方式'
,
},
{
type
:
'input'
,
prop
:
'address'
,
label
:
'快递单号'
,
},
{
type
:
'date'
,
prop
:
'address'
,
label
:
'我司签收日'
,
rules
:
[
{
required
:
true
,
message
:
'请输入我司签收日'
,
trigger
:
'blur'
}
]
},
{
type
:
'date'
,
prop
:
'address'
,
label
:
'客户签收日'
,
rules
:
[
{
required
:
true
,
message
:
'请输入客户签收日'
,
trigger
:
'blur'
}
]
},
])
// 关联记录
const
relatedTableData
=
ref
([])
const
attachmentTableData
=
ref
([])
// ===== Props & Emits =====
const
props
=
defineProps
({
modelValue
:
{
type
:
Object
,
default
:
()
=>
({})
}
})
const
emit
=
defineEmits
([
'update:modelValue'
,
'submit'
,
'cancel'
])
// ===== 本地响应式数据 =====
const
defaultFormData
=
()
=>
({
signDate
:
''
,
agentId
:
''
,
location
:
''
,
policyNo
:
''
,
effectiveDate
:
''
,
endDate
:
''
,
underwritingDate
:
''
,
insurer
:
''
,
insuranceType
:
''
,
productName
:
''
,
paymentFrequency
:
''
,
additionalPlans
:
[]
})
// ✅ 使用 ref 而不是 reactive
const
localData
=
ref
(
defaultFormData
())
// ✅ 只在挂载时初始化一次(避免 watch 形成闭环)
onMounted
(()
=>
{
if
(
props
.
modelValue
)
{
// 深拷贝 + 合并默认值,防止缺失字段
localData
.
value
=
{
...
defaultFormData
(),
...
props
.
modelValue
}
}
})
// ✅ 监听 localData 变化,emit 出去(用于 v-model)
watch
(
()
=>
localData
.
value
,
(
newVal
)
=>
{
emit
(
'update:modelValue'
,
newVal
)
},
{
deep
:
true
}
)
// ===== 表单引用 & 验证规则 =====
const
formRef
=
ref
()
const
activeTab
=
ref
(
'basic'
)
// ===== 添加附加险计划方法 =====
const
addAdditionalPlan
=
()
=>
{
localData
.
additionalPlans
.
push
({
product
:
''
,
frequency
:
''
,
term
:
''
,
periods
:
''
,
currency
:
''
,
premium
:
''
,
fee
:
''
})
}
const
deleteRow
=
(
index
)
=>
{
localData
.
additionalPlans
.
splice
(
index
,
1
)
}
const
handleTabClick
=
(
tab
)
=>
{
console
.
log
(
'切换到 Tab:'
,
tab
.
name
)
}
const
handleSubmit
=
()
=>
{
formRef
.
value
?.
validate
((
valid
)
=>
{
if
(
valid
)
{
emit
(
'submit'
,
{
...
localData
})
}
})
}
const
handleCancel
=
()
=>
{
emit
(
'cancel'
)
}
const
handleClick
=
(
tab
)
=>
{
activeTab
.
value
=
tab
.
name
}
// 如果外部 modelValue 更新(比如重新加载数据),同步到 localData
watch
(
()
=>
props
.
modelValue
,
(
newVal
)
=>
{
if
(
newVal
)
{
Object
.
assign
(
localData
,
defaultFormData
(),
newVal
)
}
},
{
deep
:
true
}
)
</
script
>
<
style
scoped
>
.form-page
{
padding
:
10px
;
background
:
#fff
;
border-radius
:
4px
;
padding-top
:
0
;
}
.tab-placeholder
{
padding
:
40px
0
;
}
.form-footer
{
text-align
:
center
;
margin-top
:
30px
;
}
.sectionTitle
{
margin
:
0
0
15px
0
;
font-size
:
16px
;
line-height
:
1
;
position
:
relative
;
padding-left
:
16px
;
}
.sectionTitle
::before
{
content
:
''
;
position
:
absolute
;
left
:
0
;
top
:
50%
;
transform
:
translateY
(
-50%
);
width
:
6px
;
height
:
20px
;
background-color
:
#007bff
;
border-radius
:
5px
;
}
.section
h5
{
margin
:
0
0
15px
0
;
font-size
:
14px
;
line-height
:
1
;
position
:
relative
;
background-color
:
rgba
(
0
,
119
,
238
,
0.05
);
color
:
#383838
;
padding
:
15px
10px
;
border-radius
:
4px
;
}
</
style
>
\ No newline at end of file
src/views/workbench/index.vue
View file @
d4982277
...
...
@@ -5,7 +5,7 @@
<el-col
:sm=
"12"
:lg=
"12"
:xs=
"24"
>
<div
class=
"headerLeft"
>
<div
class=
"top"
>
欢迎!
</div>
<div
class=
"bottom"
>
王力群
,wangliqun@bytedance.com
</div>
<div
class=
"bottom"
>
王力群
</div>
</div>
</el-col>
<el-col
:sm=
"12"
:lg=
"12"
:xs=
"24"
class=
"right"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment