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
352e73d1
Commit
352e73d1
authored
Jan 07, 2026
by
Sweet Zhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新单跟进对接
parent
b3a13b17
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
260 additions
and
985 deletions
+260
-985
src/views/financialCenter/financialBilling.vue
+17
-15
src/views/financialCenter/payables.vue
+2
-0
src/views/financialCenter/receivables.vue
+2
-2
src/views/sign/underwritingMain/index.vue
+239
-968
No files found.
src/views/financialCenter/financialBilling.vue
View file @
352e73d1
...
...
@@ -162,7 +162,8 @@ const searchConfig = ref([
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
},
{
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'出账状态'
,
...
...
@@ -209,13 +210,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
=
[
...
...
@@ -370,7 +371,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 +379,13 @@ const operationBtnList = ref([
direction
:
'left'
,
label
:
'新增出账'
,
click
:
handleAdd
},
{
key
:
'import'
,
direction
:
'left'
,
label
:
'导入出账'
,
click
:
handleImport
},
},
// {
// key: 'import',
// direction: 'left',
// label: '导入出账',
// click: handleImport
// },
{
key
:
'export'
,
direction
:
'right'
,
...
...
src/views/financialCenter/payables.vue
View file @
352e73d1
...
...
@@ -304,6 +304,8 @@ const searchConfig = ref([
}
},
])
const
payRecordDialogTableVisible
=
ref
(
false
)
// 新增出账记录
const
addPayRecordFormModel
=
ref
({
...
...
src/views/financialCenter/receivables.vue
View file @
352e73d1
...
...
@@ -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"
/>
...
...
src/views/sign/underwritingMain/index.vue
View file @
352e73d1
<
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=
"400"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
prop=
"policyNo"
label=
"保单号"
width=
"120"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"policyNo"
label=
"新单状态"
width=
"120"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"appointmentNo"
label=
"预约编号"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"signDate"
label=
"签单日"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"policyBizId"
label=
"最晚缴费日"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"policyHolder"
label=
"投保人"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"policyNo"
label=
"受保人"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"insuranceCompany"
label=
"保险公司"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"productName"
label=
"产品计划"
width=
"150"
fixed=
"left"
sortable
/>
<el-table-column
prop=
"paymentNumber"
label=
"缴费年期"
width=
"150"
fixed=
"left"
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> -->
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<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>
<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>
</el-dialog>
</CommonPage>
<!-- 弹窗-->
<CommonDialog
dialogTitle=
'弹窗'
dialogWidth=
'80%'
:openDialog=
dialogFlag
:showAction=
'false'
:showClose=
'true'
@
close=
'dialogFlag = false'
>
内容
</CommonDialog>
</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
=>
{
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
dialogFlag
=
ref
(
false
)
// 获取新单状态,字典值转化方法
onMounted
(
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
)
})
}
else
{
policyFortuneList
.
value
=
[]
}
await
loadDicts
([
'csf_policy_follow_status'
])
}
catch
(
error
)
{
console
.
error
(
'获取预计来佣列表失败:'
,
error
)
policyFortuneList
.
value
=
[]
console
.
error
(
'字典加载失败'
,
error
)
}
finally
{
loading
.
value
=
false
}
}
// 表格数据
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
handleView
=
async
row
=>
{
console
.
log
(
'查看详情:'
,
row
)
currentRow
.
value
=
{
...
row
}
viewDialogVisible
.
value
=
true
fetchExpectedCommissionList
(
row
.
policyNo
)
getPolicyFortuneLists
(
row
.
policyNo
)
}
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)
}
catch
(
error
)
{
console
.
error
(
'导出失败:'
,
error
)
// 按钮事件处理
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
handleSizeChange
=
(
val
)
=>
{
pageSize
.
value
=
val
loadTableData
()
}
// 处理详情弹窗关闭
const
handleDetailClose
=
()
=>
{
viewDialogVisible
.
value
=
false
console
.
log
(
'详情弹窗已关闭'
)
const
handleCurrentChange
=
(
val
)
=>
{
currentPage
.
value
=
val
loadTableData
()
}
// Excel导入相关
const
selectedFile
=
ref
(
null
)
const
importLoading
=
ref
(
false
)
// 页面加载时获取数据
onMounted
(()
=>
{
fetchTableData
()
getLists
()
})
// 获取列表数据
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
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
const
searchParams
=
searchFormRef
.
value
.
getFormData
()
||
{}
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
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'查看详情'
,
value
:
'viewDetail'
},
{
label
:
'更新数据'
,
value
:
'updateData'
},
{
label
:
'设置新单状态'
,
value
:
'setNewSingleStatus'
},
{
label
:
'查看关联'
,
value
:
'viewRelated'
},
{
label
:
'生成签单报告'
,
value
:
'generateReport'
},
{
label
:
'更新记录'
,
value
:
'updateRecord'
},
]
const
handleSelect
=
async
(
e
,
row
)
=>
{
selectedRow
.
value
=
{
...
row
}
console
.
log
(
e
,
row
)
switch
(
e
)
{
case
'viewDetail'
:
ElMessage
.
info
(
'查看详情'
)
break
case
'updateData'
:
ElMessage
.
info
(
'更新数据'
)
break
case
'setNewSingleStatus'
:
ElMessage
.
info
(
'设置新单状态'
)
break
case
'viewRelated'
:
ElMessage
.
info
(
'查看关联'
)
break
case
'generateReport'
:
ElMessage
.
info
(
'生成签单报告'
)
break
case
'updateRecord'
:
ElMessage
.
info
(
'更新记录'
)
break
default
:
break
}
// 二次确认
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
}
})
.
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
;
}
/* 响应式调整 */
@media
(
max-width
:
1200px
)
{
.import-actions
{
flex-wrap
:
wrap
;
}
.download-template-btn
{
margin-top
:
10px
;
}
.file-info
{
flex-direction
:
column
;
align-items
:
flex-start
;
gap
:
12px
;
}
.confirm-import-btn
{
margin-left
:
0
;
align-self
:
flex-end
;
}
}
@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
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