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
08e9e2d3
Commit
08e9e2d3
authored
Apr 28, 2026
by
yuzhenWang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
用户体验优化1
parent
634376d0
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
4501 additions
and
1432 deletions
+4501
-1432
src/api/financial/commission.js
+32
-1
src/api/sign/policy.js
+7
-0
src/api/sign/underwritingMain.js
+1
-0
src/components/SearchForm/SearchForm.vue
+435
-181
src/components/Table/editTable.vue
+959
-0
src/components/commonDialog/filePreviewDialog.vue
+159
-0
src/utils/validate.js
+37
-1
src/views/financialCenter/financialBilling.vue
+480
-39
src/views/financialCenter/financialIncome.vue
+332
-144
src/views/financialCenter/financialSalary.vue
+44
-23
src/views/financialCenter/payables.vue
+576
-179
src/views/financialCenter/payroll.vue
+5
-5
src/views/financialCenter/receivables.vue
+1116
-729
src/views/sign/FnaList/edit.vue
+6
-3
src/views/sign/FnaList/index.vue
+42
-24
src/views/sign/policyReceipts/premiumRecon.vue
+124
-21
src/views/sign/underwritingMain/index.vue
+146
-82
No files found.
src/api/financial/commission.js
View file @
08e9e2d3
...
...
@@ -490,7 +490,6 @@ export function billBatchSave(data) {
})
}
// 拆分出账查询-计算目标金额
export
function
billCalculateToAmount
(
data
)
{
return
request
({
...
...
@@ -508,3 +507,35 @@ export function CommissionExpectedChangeStatus(data) {
data
:
data
})
}
// 出账检核--分期出账
export
function
billSplitApi
(
data
)
{
return
request
({
url
:
'csf/api/fortune/split'
,
method
:
'post'
,
data
:
data
})
}
//用保单查询结算汇率
export
function
commissionExchangeRateApi
(
data
)
{
return
request
({
url
:
'csf/api/commission/commission_exchange_rate'
,
method
:
'post'
,
data
:
data
})
}
//出账检核--设置出账年月(单个)
export
function
actualPayoutDateApi
(
data
)
{
return
request
({
url
:
'csf/api/fortune/edit/actual_payout_date'
,
method
:
'post'
,
data
:
data
})
}
//出账检核--修改结算汇率
export
function
editExchangeRateApi
(
data
)
{
return
request
({
url
:
'csf/api/fortune/edit/exchange_rate'
,
method
:
'post'
,
data
:
data
})
}
src/api/sign/policy.js
View file @
08e9e2d3
...
...
@@ -139,3 +139,10 @@ export function addSinglePremiumRemittance(data) {
data
:
data
})
}
// 保单详情
export
function
policyDetail
(
policyNo
)
{
return
request
({
url
:
`/csf/api/policy_follow/detail?policyNo=
${
policyNo
}
`
,
method
:
'get'
})
}
src/api/sign/underwritingMain.js
View file @
08e9e2d3
...
...
@@ -256,3 +256,4 @@ export function getProductList(data) {
data
:
data
})
}
src/components/SearchForm/SearchForm.vue
View file @
08e9e2d3
<!-- searchForm -->
<
template
>
<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 }"
: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"
:disabled="item.disabled"
@input="val => handleNumberInput(val, item)"
@change="val => handleModelChange(val, item)"
:formatter="value => {
if (!item.inputType || !value) return value;
const str = String(value);
// 如果包含小数点
if (str.indexOf('.') > -1) {
const [int, dec] = str.split('.');
// 只格式化整数部分,保留小数部分原样
return int.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + '.' + dec;
}
// 如果没有小数点,直接格式化
return str.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}"
:parser="value => value.replace(/\$\s?|(,*)/g, '')"
/>
<!-- Select (支持 dictType / api / options) -->
<el-select
v-else-if=
"item.type === 'select'"
v-model=
"localModel[item.prop]"
:multiple=
"!!item.multiple"
:placeholder=
"item.placeholder || `请选择$
{item.label}`"
:clearable="true"
filterable
:disabled="item.disabled"
:loading="remoteLoading[item.prop] || false"
@change="val => handleModelChange(val, item)"
@focus="() => loadRemoteOptions(item)"
@filter-change="keyword => handleFilterChange(keyword, item)"
<div>
<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 }"
:label-position="item.labelPosition || 'top'"
>
<el-option
v-for=
"opt in getSelectOptions(item)"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
<!-- Input -->
<el-input
v-if=
"item.type === 'input'"
v-model=
"localModel[item.prop]"
:placeholder=
"item.placeholder || `请输入$
{item.label}`"
:clearable="true"
:disabled="item.disabled"
@input="val => handleNumberInput(val, item)"
@change="val => handleModelChange(val, item)"
:formatter="
value => {
if (!item.inputType || !value) return value
const str = String(value)
// 如果包含小数点
if (str.indexOf('.') > -1) {
const [int, dec] = str.split('.')
// 只格式化整数部分,保留小数部分原样
return int.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + '.' + dec
}
// 如果没有小数点,直接格式化
return str.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
"
:parser="value => value.replace(/\$\s?|(,*)/g, '')"
/>
</el-select>
<!-- Date -->
<el-date-picker
v-else-if=
"item.type === 'date'"
v-model=
"localModel[item.prop]"
type=
"date"
:placeholder=
"`选择$
{item.label}`"
:disabled="item.disabled"
:value-format="item.valueFormat || 'YYYY-MM-DD'"
style="width: 100%"
:disabled-date="getDisabledDateFn(item)"
@change="val => handleModelChange(val, item)"
/>
<!-- Month -->
<el-date-picker
v-else-if=
"item.type === 'month'"
v-model=
"localModel[item.prop]"
type=
"month"
:placeholder=
"`选择$
{item.label}`"
:value-format="item.valueFormat || 'YYYY-MM'"
style="width: 100%"
:disabled="item.disabled"
:disabled-date="getDisabledDateFn(item)"
@change="val => handleModelChange(val, item)"
/>
<!-- Daterange -->
<el-date-picker
v-else-if=
"item.type === 'daterange'"
v-model=
"localModel[item.prop]"
type=
"daterange"
range-separator=
"至"
:start-placeholder=
"item.startPlaceholder || '开始日期'"
:end-placeholder=
"item.endPlaceholder || '结束日期'"
:value-format=
"item.valueFormat || 'YYYY-MM-DD'"
:disabled=
"item.disabled"
:disabled-date=
"getDisabledDateFn(item)"
style=
"width: 100%"
@
change=
"val => handleModelChange(val, item)"
/>
<!-- Monthrange (新增) -->
<el-date-picker
v-else-if=
"item.type === 'monthrange'"
v-model=
"localModel[item.prop]"
type=
"monthrange"
range-separator=
"至"
:start-placeholder=
"item.startPlaceholder || '开始月份'"
:end-placeholder=
"item.endPlaceholder || '结束月份'"
:value-format=
"item.valueFormat || 'YYYY-MM'"
:disabled=
"item.disabled"
:disabled-date=
"getDisabledDateFn(item)"
style=
"width: 100%"
@
change=
"val => handleModelChange(val, item)"
/>
<!-- Checkbox Group -->
<el-checkbox-group
v-else-if=
"item.type === 'checkbox-group'"
v-model=
"localModel[item.prop]"
:disabled=
"item.disabled"
@
change=
"val => handleModelChange(val, item)"
>
<el-checkbox
v-for=
"opt in getSelectOptions(item)"
:key=
"opt.value"
:label=
"opt.value"
>
{{
opt
.
label
}}
</el-checkbox>
</el-checkbox-group>
<!-- textarea -->
<el-input
v-else-if=
"item.type === 'textarea'"
v-model=
"localModel[item.prop]"
style=
"width: 240px"
autosize
:disabled=
"item.disabled"
type=
"textarea"
placeholder=
"请输入"
:clearable=
"true"
@
change=
"val => handleModelChange(val, item)"
/>
<!-- Upload 回显值得时候数据格式至少是[
{url: '必须要传', name: 'name不是必须的根据需要传值'}]-->
<el-upload
v-else-if=
"item.type === 'upload'"
v-model:file-list=
"localModel[item.prop]"
:action=
"item.action"
:headers=
"item.headers"
:multiple=
"!!item.multiple"
:limit=
"item.limit || (item.multiple ? 999 : 1)"
:accept=
"item.accept"
:list-type=
"item.listType || 'text'"
:disabled=
"item.disabled"
:auto-upload=
"true"
:show-file-list=
"item.showFileList"
:on-exceed=
"handleExceed"
:before-upload=
"file => beforeUpload(file, item)"
:on-success=
"(res, file, fileList) => handleUploadSuccess(res, file, fileList, item)"
:on-error=
"(err, file, fileList) => handleUploadError(err, file, fileList, item)"
:on-remove=
"(file, fileList) => handleUploadRemove(file, fileList, item)"
>
<el-icon
class=
"iconStyle"
:size=
"20"
v-if=
"item.uploadType === 'image'"
>
<Upload
/>
</el-icon>
<el-button
v-else
size=
"small"
type=
"primary"
:link=
"item.link"
<!-- Select (支持 dictType / api / options) -->
<el-select
v-else-if=
"item.type === 'select'"
v-model=
"localModel[item.prop]"
:multiple=
"!!item.multiple"
:placeholder=
"item.placeholder || `请选择$
{item.label}`"
:clearable="true"
filterable
:disabled="item.disabled"
:loading="remoteLoading[item.prop] || false"
@change="val => handleModelChange(val, item)"
@focus="() => loadRemoteOptions(item)"
@filter-change="keyword => handleFilterChange(keyword, item)"
>
{{
'点击上传文件'
}}
</el-button>
<template
#
tip
v-if=
"item.maxSize || item.accept"
>
<div
class=
"el-upload__tip"
>
<span
v-if=
"item.maxSize"
>
大小不超过
{{
formatFileSize
(
item
.
maxSize
)
}}
</span>
<span
v-if=
"item.accept"
>
支持格式:
{{
item
.
accept
}}
</span>
<el-option
v-for=
"opt in getSelectOptions(item)"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
/>
</el-select>
<!-- Date -->
<el-date-picker
v-else-if=
"item.type === 'date'"
v-model=
"localModel[item.prop]"
type=
"date"
:placeholder=
"`选择$
{item.label}`"
:disabled="item.disabled"
:value-format="item.valueFormat || 'YYYY-MM-DD'"
style="width: 100%"
:disabled-date="getDisabledDateFn(item)"
@change="val => handleModelChange(val, item)"
/>
<!-- Month -->
<el-date-picker
v-else-if=
"item.type === 'month'"
v-model=
"localModel[item.prop]"
type=
"month"
:placeholder=
"`选择$
{item.label}`"
:value-format="item.valueFormat || 'YYYY-MM'"
style="width: 100%"
:disabled="item.disabled"
:disabled-date="getDisabledDateFn(item)"
@change="val => handleModelChange(val, item)"
/>
<!-- Daterange -->
<el-date-picker
v-else-if=
"item.type === 'daterange'"
v-model=
"localModel[item.prop]"
type=
"daterange"
range-separator=
"至"
:start-placeholder=
"item.startPlaceholder || '开始日期'"
:end-placeholder=
"item.endPlaceholder || '结束日期'"
:value-format=
"item.valueFormat || 'YYYY-MM-DD'"
:disabled=
"item.disabled"
:disabled-date=
"getDisabledDateFn(item)"
style=
"width: 100%"
@
change=
"val => handleModelChange(val, item)"
/>
<!-- Monthrange (新增) -->
<el-date-picker
v-else-if=
"item.type === 'monthrange'"
v-model=
"localModel[item.prop]"
type=
"monthrange"
range-separator=
"至"
:start-placeholder=
"item.startPlaceholder || '开始月份'"
:end-placeholder=
"item.endPlaceholder || '结束月份'"
:value-format=
"item.valueFormat || 'YYYY-MM'"
:disabled=
"item.disabled"
:disabled-date=
"getDisabledDateFn(item)"
style=
"width: 100%"
@
change=
"val => handleModelChange(val, item)"
/>
<!-- Checkbox Group -->
<el-checkbox-group
v-else-if=
"item.type === 'checkbox-group'"
v-model=
"localModel[item.prop]"
:disabled=
"item.disabled"
@
change=
"val => handleModelChange(val, item)"
>
<el-checkbox
v-for=
"opt in getSelectOptions(item)"
:key=
"opt.value"
:label=
"opt.value"
>
{{
opt
.
label
}}
</el-checkbox>
</el-checkbox-group>
<!-- textarea -->
<el-input
v-else-if=
"item.type === 'textarea'"
v-model=
"localModel[item.prop]"
style=
"width: 240px"
autosize
:disabled=
"item.disabled"
type=
"textarea"
placeholder=
"请输入"
:clearable=
"true"
@
change=
"val => handleModelChange(val, item)"
/>
<!-- Upload 回显值得时候数据格式至少是[
{url: '必须要传', name: 'name不是必须的根据需要传值'}]-->
<!--
<el-upload
v-else-if=
"item.type === 'upload'"
v-model:file-list=
"localModel[item.prop]"
:action=
"item.action"
:headers=
"item.headers"
:multiple=
"!!item.multiple"
:limit=
"item.limit || (item.multiple ? 999 : 1)"
:accept=
"item.accept"
:list-type=
"item.listType || 'text'"
:disabled=
"item.disabled"
:auto-upload=
"true"
:show-file-list=
"item.showFileList"
:on-exceed=
"handleExceed"
:before-upload=
"file => beforeUpload(file, item)"
:on-success=
"(res, file, fileList) => handleUploadSuccess(res, file, fileList, item)"
:on-error=
"(err, file, fileList) => handleUploadError(err, file, fileList, item)"
:on-remove=
"(file, fileList) => handleUploadRemove(file, fileList, item)"
>
<el-icon
class=
"iconStyle"
:size=
"20"
v-if=
"item.uploadType === 'image'"
>
<Upload
/>
</el-icon>
<el-button
v-else
size=
"small"
type=
"primary"
:link=
"item.link"
:disabled=
"item.disabled"
>
{{
'点击上传文件'
}}
</el-button>
<template
#
tip
v-if=
"item.maxSize || item.accept"
>
<div
class=
"el-upload__tip"
>
<span
v-if=
"item.maxSize"
>
大小不超过
{{
formatFileSize
(
item
.
maxSize
)
}}
</span>
<span
v-if=
"item.accept"
>
支持格式:
{{
item
.
accept
}}
</span>
</div>
</
template
>
</el-upload>
-->
<!-- Upload 回显值时数据格式至少是 [{url: '必须', name: '可选'}] -->
<
template
v-else-if=
"item.type === 'upload'"
>
<!-- 🔽 默认模式:完整使用 el-upload(含自带文件列表) -->
<el-upload
v-if=
"!item.customFileList"
v-model:file-list=
"localModel[item.prop]"
:action=
"item.action"
:headers=
"item.headers"
:multiple=
"!!item.multiple"
:limit=
"item.limit || (item.multiple ? 999 : 1)"
:accept=
"item.accept"
:list-type=
"item.listType || 'text'"
:disabled=
"item.disabled"
:auto-upload=
"true"
:show-file-list=
"item.showFileList !== false"
:on-exceed=
"handleExceed"
:before-upload=
"file => beforeUpload(file, item)"
:on-success=
"
(res, file, fileList) => handleUploadSuccess(res, file, fileList, item)
"
:on-error=
"(err, file, fileList) => handleUploadError(err, file, fileList, item)"
:on-remove=
"(file, fileList) => handleUploadRemove(file, fileList, item)"
>
<el-icon
class=
"iconStyle"
:size=
"20"
v-if=
"item.uploadType === 'image'"
>
<Upload
/>
</el-icon>
<el-button
v-else
size=
"small"
type=
"primary"
:link=
"item.link"
:disabled=
"item.disabled"
>
点击上传文件
</el-button>
<template
#
tip
v-if=
"item.maxSize || item.accept"
>
<div
class=
"el-upload__tip"
>
<span
v-if=
"item.maxSize"
>
大小不超过
{{
formatFileSize
(
item
.
maxSize
)
}}
</span>
<span
v-if=
"item.accept"
>
支持格式:
{{
item
.
accept
}}
</span>
</div>
</
template
>
</el-upload>
<!-- 🔽 自定义列表模式:只保留上传触发器,自己渲染文件列表 -->
<div
v-else
class=
"custom-upload-wrapper"
>
<el-upload
v-model:file-list=
"localModel[item.prop]"
:action=
"item.action"
:headers=
"item.headers"
:multiple=
"!!item.multiple"
:limit=
"item.limit || (item.multiple ? 999 : 1)"
:accept=
"item.accept"
:disabled=
"item.disabled"
:auto-upload=
"true"
:show-file-list=
"false"
:on-exceed=
"handleExceed"
:before-upload=
"file => beforeUpload(file, item)"
:on-success=
"
(res, file, fileList) => handleUploadSuccess(res, file, fileList, item)
"
:on-error=
"(err, file, fileList) => handleUploadError(err, file, fileList, item)"
:on-remove=
"(file, fileList) => handleUploadRemove(file, fileList, item)"
>
<el-button
type=
"primary"
size=
"small"
:disabled=
"item.disabled"
>
{{ item.customUploadButtonText || '点击上传文件' }}
</el-button>
<
template
#
tip
v-if=
"item.maxSize || item.accept"
>
<div
class=
"el-upload__tip"
>
<span
v-if=
"item.maxSize"
>
大小不超过
{{
formatFileSize
(
item
.
maxSize
)
}}
</span>
<span
v-if=
"item.accept"
>
支持格式:
{{
item
.
accept
}}
</span>
</div>
</
template
>
</el-upload>
<!-- 自定义文件列表 -->
<div
v-if=
"(localModel[item.prop] || []).length"
class=
"custom-file-list"
>
<div
v-for=
"(file, idx) in localModel[item.prop]"
:key=
"file.uid || idx"
class=
"file-item"
>
<span
class=
"file-name"
:title=
"file.name"
>
{{ file.name }}
</span>
<div
class=
"file-actions"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"previewFile(file, item)"
>
查看
</el-button>
<el-button
link
type=
"danger"
size=
"small"
@
click=
"removeFile(file, item)"
>
删除
</el-button>
</div>
</div>
</div>
</div>
</template>
</el-upload>
<span
v-else
>
不支持的类型: {{ item.type }}
</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
<span
v-else
>
不支持的类型: {{ item.type }}
</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 文件预览弹窗(页面内查看,不打开新窗口) -->
<el-dialog
v-model=
"previewDialogVisible"
:title=
"previewFileName"
width=
"70%"
:close-on-click-modal=
"false"
destroy-on-close
@
close=
"previewUrl = ''"
>
<div
class=
"preview-container"
>
<!-- 图片预览 -->
<div
v-if=
"previewFileType === 'image'"
class=
"preview-image-wrapper"
>
<img
:src=
"previewUrl"
class=
"preview-image"
alt=
"预览图片"
/>
</div>
<!-- PDF 预览(使用 iframe 内嵌) -->
<iframe
v-else-if=
"previewFileType === 'pdf'"
:src=
"previewUrl"
class=
"preview-pdf"
frameborder=
"0"
></iframe>
<!-- 不支持预览的文件类型 -->
<div
v-else-if=
"previewFileType === 'unsupported'"
class=
"preview-unsupported"
>
<el-icon
:size=
"48"
color=
"#909399"
><Document
/></el-icon>
<p>
暂不支持预览此类型文件
</p>
<el-button
type=
"primary"
@
click=
"previewDialogVisible = false"
>
关闭
</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<
script
setup
>
import
{
ref
,
watch
,
onMounted
,
nextTick
,
computed
}
from
'vue'
import
{
ElMessage
}
from
'element-plus'
import
{
Upload
}
from
'@element-plus/icons-vue'
import
{
Upload
,
Document
}
from
'@element-plus/icons-vue'
// 🔑 引入你的字典方法
import
useDictStore
from
'@/store/modules/dict'
import
{
getDicts
}
from
'@/api/system/dict/data'
import
request
from
'@/utils/request'
import
dayjs
from
'dayjs'
// ==================== 上传文件 ====================
// ==================== 文件预览弹窗 ====================
const
previewDialogVisible
=
ref
(
false
)
const
previewUrl
=
ref
(
''
)
const
previewFileName
=
ref
(
''
)
const
previewFileType
=
ref
(
''
)
// 'image', 'pdf', 'unsupported'
//新增文件上传自定义方法开始
// 预览文件(支持图片和PDF)
// 预览文件(页面内弹窗,不打开新窗口)
function
previewFile
(
file
,
item
)
{
const
url
=
file
.
url
||
file
.
response
?.
data
?.
url
if
(
!
url
)
{
ElMessage
.
warning
(
'文件地址不存在'
)
return
}
const
ext
=
(
file
.
name
||
''
).
split
(
'.'
).
pop
().
toLowerCase
()
previewUrl
.
value
=
url
previewFileName
.
value
=
file
.
name
||
'文件'
if
([
'jpg'
,
'jpeg'
,
'png'
,
'webp'
,
'gif'
,
'bmp'
,
'svg'
].
includes
(
ext
))
{
previewFileType
.
value
=
'image'
previewDialogVisible
.
value
=
true
}
else
if
(
ext
===
'pdf'
)
{
previewFileType
.
value
=
'pdf'
previewDialogVisible
.
value
=
true
}
else
{
// 不支持预览的文件类型,弹窗显示提示
previewFileType
.
value
=
'unsupported'
previewDialogVisible
.
value
=
true
}
}
// 删除文件(复用原有删除逻辑)
function
removeFile
(
file
,
item
)
{
const
fileList
=
localModel
.
value
[
item
.
prop
]
||
[]
const
newList
=
fileList
.
filter
(
f
=>
f
.
uid
!==
file
.
uid
)
handleUploadRemove
(
file
,
newList
,
item
)
// 调用原有的删除处理函数
}
//新增文件上传自定义方法结束
// 文件大小格式化
function
formatFileSize
(
bytes
)
{
if
(
bytes
===
0
)
return
'0 Bytes'
...
...
@@ -336,7 +510,13 @@ const props = defineProps({
isSearch
:
{
type
:
Boolean
,
default
:
false
}
})
const
emit
=
defineEmits
([
'update:modelValue'
,
'update'
,
'selectChange'
,
'uploadSuccess'
])
const
emit
=
defineEmits
([
'update:modelValue'
,
'update'
,
'selectChange'
,
'uploadSuccess'
,
'inputChange'
])
// ==================== Refs ====================
const
formRef
=
ref
(
null
)
...
...
@@ -382,7 +562,10 @@ watch(
// 优先用父传值,否则用默认值
if
(
props
.
modelValue
?.[
key
]
!==
undefined
)
{
initialModel
[
key
]
=
props
.
modelValue
[
key
]
}
else
if
(
item
.
multiple
||
[
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
))
{
}
else
if
(
item
.
multiple
||
[
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
)
)
{
initialModel
[
key
]
=
item
.
defaultValue
??
[]
}
else
{
initialModel
[
key
]
=
item
.
defaultValue
??
''
...
...
@@ -419,7 +602,7 @@ function syncModelFromProps(newModelValue, newConfig) {
const
key
=
item
.
prop
if
(
newModelValue
.
hasOwnProperty
(
key
))
{
synced
[
key
]
=
newModelValue
[
key
]
}
else
if
(
item
.
multiple
||
[
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
))
{
}
else
if
(
item
.
multiple
||
[
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
))
{
synced
[
key
]
=
item
.
defaultValue
??
[]
}
else
{
synced
[
key
]
=
item
.
defaultValue
??
''
...
...
@@ -543,6 +726,8 @@ function handleModelChange(value, item) {
}
else
if
(
item
.
type
==
'upload'
)
{
// 传给父组件最新的上传值newModel
emit
(
'uploadSuccess'
,
item
.
prop
,
newModel
)
}
else
if
(
item
.
type
==
'input'
)
{
emit
(
'inputChange'
,
item
.
prop
,
value
,
item
)
}
console
.
groupEnd
()
}
...
...
@@ -594,7 +779,7 @@ onMounted(async () => {
if
(
localModel
.
value
[
key
]
==
null
)
{
if
(
item
.
multiple
)
{
initialData
[
key
]
=
item
.
defaultValue
??
[]
}
else
if
([
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
))
{
}
else
if
([
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
))
{
initialData
[
key
]
=
item
.
defaultValue
??
[]
}
else
{
initialData
[
key
]
=
item
.
defaultValue
??
''
...
...
@@ -908,7 +1093,7 @@ defineExpose({
const
resetData
=
{}
internalConfig
.
value
.
forEach
(
item
=>
{
const
key
=
item
.
prop
if
([
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
)
||
item
.
multiple
)
{
if
([
'checkbox-group'
,
'daterange'
,
'monthrange'
].
includes
(
item
.
type
)
||
item
.
multiple
)
{
resetData
[
key
]
=
item
.
defaultValue
??
[]
}
else
if
(
item
.
type
===
'upload'
)
{
resetData
[
key
]
=
item
.
defaultValue
??
[]
// upload 也是数组
...
...
@@ -960,6 +1145,75 @@ defineExpose({
</
script
>
<
style
scoped
>
/* 预览弹窗样式 */
.preview-container
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
min-height
:
400px
;
}
.preview-image-wrapper
{
text-align
:
center
;
}
.preview-image
{
max-width
:
100%
;
max-height
:
70vh
;
object-fit
:
contain
;
}
.preview-pdf
{
width
:
100%
;
height
:
70vh
;
}
.preview-unsupported
{
text-align
:
center
;
padding
:
40px
;
}
.preview-unsupported
p
{
margin
:
16px
0
;
color
:
#909399
;
}
.custom-upload-wrapper
{
width
:
100%
;
}
.custom-file-list
{
margin-top
:
12px
;
border
:
1px
solid
#dcdfe6
;
border-radius
:
4px
;
background-color
:
#fff
;
}
.file-item
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
padding
:
8px
12px
;
border-bottom
:
1px
solid
#ebeef5
;
}
.file-item
:last-child
{
border-bottom
:
none
;
}
.file-name
{
flex
:
1
;
font-size
:
14px
;
color
:
#606266
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
margin-right
:
16px
;
}
.file-actions
{
display
:
flex
;
gap
:
12px
;
}
.formBox
{
box-sizing
:
border-box
;
}
...
...
src/components/Table/editTable.vue
0 → 100644
View file @
08e9e2d3
<
template
>
<div
class=
"common-table"
>
<div
class=
"addBox"
>
<el-button
v-if=
"showAdd"
type=
"primary"
@
click=
"addTableData"
>
{{
addBtnTxt
}}
</el-button>
</div>
<el-table
v-loading=
"loading"
:data=
"tableData"
border
style=
"width: 100%"
v-bind=
"$attrs"
>
<!-- 动态列 -->
<el-table-column
v-for=
"col in visibleColumns"
:key=
"col.prop"
:prop=
"col.prop"
:width=
"col.width"
:min-width=
"col.minWidth"
:fixed=
"col.fixed"
:align=
"col.align || 'left'"
:show-overflow-tooltip=
"col.showOverflowTooltip"
>
<!-- 自定义表头:显示必填红色星号 -->
<template
#
header
>
<span
v-if=
"checkColumnRequired(col)"
class=
"required-star"
>
*
</span>
<span>
{{
col
.
label
}}
</span>
</
template
>
<
template
#
default=
"{ row, $index }"
>
<!-- 可编辑列:始终显示编辑组件 -->
<div
v-if=
"col.editable !== false"
>
<el-form-item
:rules=
"getColumnRules(col)"
:error=
"getRowError(row, col.prop)"
style=
"margin-bottom: 0"
>
<!-- 输入框(文本/数字/textarea) -->
<el-input
v-if=
"col.editType === 'input'"
:model-value=
"getInputDisplayValue(row, col)"
:placeholder=
"col.placeholder || `请输入$
{col.label}`"
:clearable="true"
:type="col.inputType === 'textarea' ? 'textarea' : 'text'"
:rows="col.rows || 2"
:disabled="col.disabled"
@update:model-value="val => handleInputChange(row, col, val, $index)"
@blur="handleInputBlur(row, col, $index)"
/>
<!-- 下拉选择 -->
<el-select
v-else-if=
"col.editType === 'select'"
:model-value=
"row[col.prop]"
:placeholder=
"col.placeholder || `请选择$
{col.label}`"
:clearable="true"
filterable
:allow-create="col.allowCreate"
:default-first-option="col.allowCreate"
:remote="!!col.api"
:remote-method="keyword => handleRemoteSearch(keyword, col)"
:loading="remoteLoading[col.prop]"
:disabled="col.disabled"
@update:model-value="val => handleSelectChange(row, col, val, $index)"
@focus="() => loadRemoteOptions(col)"
>
<el-option
v-for=
"opt in getSelectOptions(col)"
:key=
"opt.value"
:label=
"opt.label"
:value=
"opt.value"
/>
</el-select>
<!-- 日期选择器 -->
<el-date-picker
v-else-if=
"col.editType === 'date'"
:model-value=
"row[col.prop]"
type=
"date"
:placeholder=
"`选择$
{col.label}`"
:value-format="col.valueFormat || 'YYYY-MM-DD'"
style="width: 100%"
:disabled="col.disabled"
:disabled-date="getDisabledDateFn(col)"
@update:model-value="val => handleCellChange(row, col, val, $index)"
/>
<!-- 月份选择器 -->
<el-date-picker
v-else-if=
"col.editType === 'month'"
:model-value=
"row[col.prop]"
type=
"month"
:placeholder=
"`选择$
{col.label}`"
:value-format="col.valueFormat || 'YYYY-MM'"
style="width: 100%"
:disabled="col.disabled"
:disabled-date="getDisabledDateFn(col)"
@update:model-value="val => handleCellChange(row, col, val, $index)"
/>
<!-- 日期范围 -->
<el-date-picker
v-else-if=
"col.editType === 'daterange'"
:model-value=
"row[col.prop]"
type=
"daterange"
range-separator=
"至"
:start-placeholder=
"col.startPlaceholder || '开始日期'"
:end-placeholder=
"col.endPlaceholder || '结束日期'"
:value-format=
"col.valueFormat || 'YYYY-MM-DD'"
style=
"width: 100%"
:disabled=
"col.disabled"
:disabled-date=
"getDisabledDateFn(col)"
@
update:model-value=
"val => handleCellChange(row, col, val, $index)"
/>
<!-- 月份范围 -->
<el-date-picker
v-else-if=
"col.editType === 'monthrange'"
:model-value=
"row[col.prop]"
type=
"monthrange"
range-separator=
"至"
:start-placeholder=
"col.startPlaceholder || '开始月份'"
:end-placeholder=
"col.endPlaceholder || '结束月份'"
:value-format=
"col.valueFormat || 'YYYY-MM'"
style=
"width: 100%"
:disabled=
"col.disabled"
:disabled-date=
"getDisabledDateFn(col)"
@
update:model-value=
"val => handleCellChange(row, col, val, $index)"
/>
<!-- 上传组件 -->
<div
v-else-if=
"col.editType === 'upload'"
class=
"table-upload-wrapper"
>
<el-upload
:file-list=
"getFileListDisplay(row[col.prop])"
:action=
"col.action || '/api/upload'"
:headers=
"col.headers"
:multiple=
"col.multiple || false"
:limit=
"col.limit || 1"
:accept=
"col.accept"
:disabled=
"col.disabled"
:auto-upload=
"true"
:show-file-list=
"false"
:before-upload=
"file => beforeUpload(file, col)"
:on-success=
"
(res, file, fileList) => handleUploadSuccess(row, col, res, file, fileList)
"
:on-error=
"
(err, file, fileList) => handleUploadError(row, col, err, file, fileList)
"
>
<el-button
size=
"small"
type=
"primary"
>
点击上传
</el-button>
</el-upload>
<div
class=
"upload-file-list"
v-if=
"getFileListDisplay(row[col.prop]).length"
>
<div
v-for=
"(file, idx) in getFileListDisplay(row[col.prop])"
:key=
"idx"
class=
"file-item"
>
<span
class=
"file-name"
>
{{
file
.
name
||
file
.
url
}}
</span>
<el-button
link
type=
"danger"
size=
"small"
@
click=
"removeFile(row, col, idx)"
>
删除
</el-button
>
</div>
</div>
</div>
<!-- 自定义渲染(插槽) -->
<slot
v-else
:name=
"`edit-$
{col.prop}`"
:row="row"
:column="col"
:updateValue="val => handleCellChange(row, col, val, $index)"
/>
</el-form-item>
</div>
<!-- 不可编辑列:只读显示 -->
<div
v-else
>
<slot
:name=
"`column-$
{col.prop}`" :row="row" :column="col" :value="row[col.prop]">
<span
v-if=
"col.editType === 'select'"
>
{{
getSelectLabel
(
col
,
row
[
col
.
prop
])
}}
</span>
<span
v-else-if=
"col.editType === 'upload' && row[col.prop]"
>
<span
v-for=
"(file, idx) in getFileListDisplay(row[col.prop])"
:key=
"idx"
>
<el-link
type=
"primary"
@
click=
"previewFile(file)"
>
{{
file
.
name
||
file
.
url
}}
</el-link>
<span
v-if=
"idx
<
getFileListDisplay
(
row
[
col
.
prop
]).
length
-
1
"
>
,
</span>
</span>
</span>
<span
v-else-if=
"col.formatter"
>
{{
col
.
formatter
(
row
[
col
.
prop
],
row
)
}}
</span>
<span
v-else
>
{{
row
[
col
.
prop
]
||
'-'
}}
</span>
</slot>
</div>
</
template
>
</el-table-column>
<!-- 操作栏 -->
<el-table-column
v-if=
"showOperation"
:label=
"operationLabel"
:width=
"operationWidth"
:fixed=
"operationFixed"
align=
"center"
>
<
template
#
default=
"{ row, $index }"
>
<div
class=
"operation-buttons"
>
<slot
name=
"operation"
:row=
"row"
:index=
"$index"
>
<el-button
link
type=
"danger"
size=
"small"
@
click=
"handleDelete(row)"
>
删除
</el-button>
</slot>
</div>
</
template
>
</el-table-column>
<!-- 额外插槽列 -->
<slot
name=
"append"
/>
</el-table>
<!-- 分页组件 -->
<div
v-if=
"showPagination"
class=
"table-pagination"
>
<el-pagination
v-model:current-page=
"currentPage"
v-model:page-size=
"pageSize"
:page-sizes=
"pageSizes"
:background=
"paginationBackground"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"total"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
/>
</div>
<!-- 文件预览弹窗 -->
<el-dialog
v-model=
"previewDialogVisible"
:title=
"previewFileName"
width=
"60%"
destroy-on-close
>
<div
class=
"preview-container"
>
<img
v-if=
"previewFileType === 'image'"
:src=
"previewUrl"
style=
"max-width: 100%"
/>
<iframe
v-else-if=
"previewFileType === 'pdf'"
:src=
"previewUrl"
style=
"width: 100%; height: 70vh"
></iframe>
<div
v-else
class=
"preview-unsupported"
>
暂不支持预览此类型文件
</div>
</div>
</el-dialog>
</div>
</template>
<
script
setup
>
import
{
ref
,
computed
,
watch
,
onMounted
}
from
'vue'
import
{
ElMessage
}
from
'element-plus'
import
{
getDicts
}
from
'@/api/system/dict/data'
import
useDictStore
from
'@/store/modules/dict'
import
request
from
'@/utils/request'
import
dayjs
from
'dayjs'
// ==================== Props ====================
const
props
=
defineProps
({
tableData
:
{
type
:
Array
,
default
:
()
=>
[]
},
columns
:
{
type
:
Array
,
default
:
()
=>
[]
},
rowIdKey
:
{
type
:
String
,
default
:
'id'
},
showOperation
:
{
type
:
Boolean
,
default
:
true
},
operationLabel
:
{
type
:
String
,
default
:
'操作'
},
operationWidth
:
{
type
:
String
,
default
:
'120'
},
operationFixed
:
{
type
:
String
,
default
:
'right'
},
showPagination
:
{
type
:
Boolean
,
default
:
false
},
total
:
{
type
:
Number
,
default
:
0
},
page
:
{
type
:
Number
,
default
:
1
},
limit
:
{
type
:
Number
,
default
:
20
},
pageSizes
:
{
type
:
Array
,
default
:
()
=>
[
10
,
20
,
30
,
50
]
},
paginationBackground
:
{
type
:
Boolean
,
default
:
true
},
loading
:
{
type
:
Boolean
,
default
:
false
},
showAdd
:
{
type
:
Boolean
,
default
:
true
},
addBtnTxt
:
{
type
:
String
,
default
:
'新增'
}
})
const
emit
=
defineEmits
([
'update:page'
,
'update:limit'
,
'update:tableData'
,
'delete'
,
'selectChange'
,
'uploadSuccess'
,
'add'
,
'cell-change'
])
// ==================== 内部状态 ====================
// 行级错误信息 { [rowId]: { [prop]: errorMsg } }
const
rowErrors
=
ref
({})
// 远程选项存储
const
remoteOptions
=
ref
({})
const
remoteLoading
=
ref
({})
// 字典加载标记
const
dictLoaded
=
ref
(
new
Set
())
// 当前页码/每页条数
const
currentPage
=
ref
(
props
.
page
)
const
pageSize
=
ref
(
props
.
limit
)
// 预览弹窗状态
const
previewDialogVisible
=
ref
(
false
)
const
previewUrl
=
ref
(
''
)
const
previewFileName
=
ref
(
''
)
const
previewFileType
=
ref
(
''
)
// ==================== 计算属性 ====================
const
visibleColumns
=
computed
(()
=>
{
return
props
.
columns
.
filter
(
col
=>
{
if
(
typeof
col
.
visible
===
'function'
)
return
col
.
visible
()
return
col
.
visible
!==
false
})
})
// 检查列是否必填
function
checkColumnRequired
(
col
)
{
if
(
col
.
required
===
true
)
return
true
if
(
col
.
rules
&&
Array
.
isArray
(
col
.
rules
))
{
return
col
.
rules
.
some
(
rule
=>
rule
.
required
===
true
)
}
return
false
}
// 获取行的错误信息
function
getRowError
(
row
,
prop
)
{
const
rowId
=
row
[
props
.
rowIdKey
]
return
rowErrors
.
value
[
rowId
]?.[
prop
]
||
''
}
// 获取列校验规则
function
getColumnRules
(
col
)
{
if
(
col
.
rules
)
return
col
.
rules
if
(
col
.
required
)
{
return
[{
required
:
true
,
message
:
`
${
col
.
label
}
不能为空`
,
trigger
:
'blur'
}]
}
return
[]
}
// 获取 Select 选项列表
function
getSelectOptions
(
col
)
{
const
key
=
col
.
prop
if
(
col
.
dictType
)
{
const
dictStore
=
useDictStore
()
const
dictOpts
=
dictStore
.
getDict
(
col
.
dictType
)
||
[]
return
dictOpts
.
map
(
opt
=>
({
value
:
opt
.
value
,
label
:
opt
.
label
,
raw
:
opt
}))
}
if
(
col
.
api
)
{
return
(
remoteOptions
.
value
[
key
]
||
[]).
map
(
opt
=>
({
value
:
opt
.
value
,
label
:
opt
.
label
,
raw
:
opt
.
raw
}))
}
if
(
col
.
options
)
{
return
col
.
options
.
map
(
opt
=>
({
value
:
opt
.
value
,
label
:
opt
.
label
,
raw
:
opt
.
raw
}))
}
return
[]
}
// 获取 Select 选中项的 label
function
getSelectLabel
(
col
,
value
)
{
const
options
=
getSelectOptions
(
col
)
if
(
value
===
undefined
||
value
===
null
)
return
'-'
if
(
col
.
multiple
&&
Array
.
isArray
(
value
))
{
return
value
.
map
(
v
=>
options
.
find
(
opt
=>
opt
.
value
===
v
)?.
label
||
v
).
join
(
', '
)
}
const
found
=
options
.
find
(
opt
=>
opt
.
value
===
value
)
return
found
?
found
.
label
:
value
}
// ==================== 数字输入格式化与解析 ====================
// 修改 getInputDisplayValue:所有类型优先使用临时编辑值
function
getInputDisplayValue
(
row
,
col
)
{
const
rowId
=
row
[
props
.
rowIdKey
]
const
editingKey
=
`
${
rowId
}
_
${
col
.
prop
}
`
// 1. 正在编辑中 → 显示临时输入值
if
(
editingTempValue
.
value
[
editingKey
]
!==
undefined
)
{
return
editingTempValue
.
value
[
editingKey
]
}
const
{
inputType
}
=
col
let
rawValue
=
row
[
col
.
prop
]
// 2. 非数字类型直接返回原始值
if
(
!
[
'integer'
,
'decimalNumber'
,
'decimal'
].
includes
(
inputType
))
{
return
rawValue
??
''
}
// 3. 数字类型:失焦状态下格式化显示(千分位 + 小数位)
if
(
rawValue
===
undefined
||
rawValue
===
null
)
return
''
let
num
=
typeof
rawValue
===
'number'
?
rawValue
:
parseFloat
(
rawValue
)
if
(
isNaN
(
num
))
return
''
const
{
decimalDigits
=
2
}
=
col
num
=
parseFloat
(
num
.
toFixed
(
decimalDigits
))
const
parts
=
num
.
toString
().
split
(
'.'
)
parts
[
0
]
=
parts
[
0
].
replace
(
/
\B(?=(\d{3})
+
(?!\d))
/g
,
','
)
return
parts
.
join
(
'.'
)
}
// 临时编辑值存储(用于聚焦时保留用户输入原文)
const
editingTempValue
=
ref
({})
// 输入时实时处理(过滤非法字符,并保留临时编辑值)
function
handleInputChange
(
row
,
col
,
rawValue
,
rowIndex
)
{
const
{
inputType
,
decimalDigits
=
2
}
=
col
let
filtered
=
rawValue
if
(
inputType
===
'integer'
)
{
filtered
=
rawValue
.
replace
(
/
[^
-
\d]
/g
,
''
)
if
(
filtered
===
'-'
)
{
// 保留负号
}
else
if
(
filtered
!==
''
)
{
let
num
=
parseInt
(
filtered
,
10
)
if
(
isNaN
(
num
))
filtered
=
''
else
filtered
=
num
.
toString
()
}
}
else
if
(
inputType
===
'decimalNumber'
)
{
let
temp
=
rawValue
.
replace
(
/
[^
-
\d
.
]
/g
,
''
)
if
(
temp
.
startsWith
(
'-'
))
{
temp
=
'-'
+
temp
.
slice
(
1
).
replace
(
/-/g
,
''
)
}
else
{
temp
=
temp
.
replace
(
/-/g
,
''
)
}
if
(
temp
===
'-'
)
{
filtered
=
'-'
}
else
{
const
pointIndex
=
temp
.
indexOf
(
'.'
)
if
(
pointIndex
!==
-
1
)
{
const
intPart
=
temp
.
slice
(
0
,
pointIndex
).
replace
(
/
[^\d
-
]
/g
,
''
)
let
decPart
=
temp
.
slice
(
pointIndex
+
1
).
replace
(
/
\D
/g
,
''
)
if
(
decPart
.
length
>
decimalDigits
)
decPart
=
decPart
.
slice
(
0
,
decimalDigits
)
filtered
=
intPart
+
(
decPart
?
'.'
+
decPart
:
'.'
)
}
else
{
filtered
=
temp
}
}
}
else
if
(
inputType
===
'decimal'
)
{
let
temp
=
rawValue
.
replace
(
/
[^\d
.
]
/g
,
''
)
const
pointIndex
=
temp
.
indexOf
(
'.'
)
if
(
pointIndex
!==
-
1
)
{
const
intPart
=
temp
.
slice
(
0
,
pointIndex
).
replace
(
/
\D
/g
,
''
)
let
decPart
=
temp
.
slice
(
pointIndex
+
1
).
replace
(
/
\D
/g
,
''
)
if
(
decPart
.
length
>
decimalDigits
)
decPart
=
decPart
.
slice
(
0
,
decimalDigits
)
filtered
=
intPart
+
(
decPart
?
'.'
+
decPart
:
'.'
)
}
else
{
filtered
=
temp
}
}
else
{
// textarea 或普通文本
filtered
=
rawValue
}
// const rowId = row[props.rowIdKey]
// const editingKey = `${rowId}_${col.prop}`
// // 保证响应式更新
// editingTempValue.value = {
// ...editingTempValue.value,
// [editingKey]: filtered
// }
const
rowId
=
row
[
props
.
rowIdKey
]
const
editingKey
=
`
${
rowId
}
_
${
col
.
prop
}
`
// 直接赋值,无需展开整个对象
editingTempValue
.
value
[
editingKey
]
=
filtered
}
// 失焦时:将临时编辑值转换为真实值并更新到表格数据
function
handleInputBlur
(
row
,
col
,
rowIndex
)
{
const
rowId
=
row
[
props
.
rowIdKey
]
const
editingKey
=
`
${
rowId
}
_
${
col
.
prop
}
`
const
rawStr
=
editingTempValue
.
value
[
editingKey
]
// 没有临时编辑值,说明用户未输入任何字符,直接返回
if
(
rawStr
===
undefined
)
{
return
}
delete
editingTempValue
.
value
[
editingKey
]
// 清除临时值
// 用户清空了输入框
if
(
rawStr
===
''
)
{
const
newTableData
=
[...
props
.
tableData
]
newTableData
[
rowIndex
]
=
{
...
row
,
[
col
.
prop
]:
null
}
emit
(
'update:tableData'
,
newTableData
)
validateField
(
newTableData
[
rowIndex
],
col
.
prop
)
return
}
const
{
inputType
,
decimalDigits
=
2
}
=
col
let
finalValue
=
null
if
(
inputType
===
'integer'
)
{
const
match
=
rawStr
.
match
(
/^-
?\d
+/
)
if
(
match
)
{
const
num
=
parseInt
(
match
[
0
],
10
)
if
(
!
isNaN
(
num
))
finalValue
=
num
}
}
else
if
(
inputType
===
'decimalNumber'
)
{
const
num
=
parseFloat
(
rawStr
)
if
(
!
isNaN
(
num
))
finalValue
=
parseFloat
(
num
.
toFixed
(
decimalDigits
))
}
else
if
(
inputType
===
'decimal'
)
{
const
num
=
parseFloat
(
rawStr
)
if
(
!
isNaN
(
num
)
&&
num
>=
0
)
finalValue
=
parseFloat
(
num
.
toFixed
(
decimalDigits
))
}
else
{
// textarea 或普通文本
finalValue
=
rawStr
}
const
newTableData
=
[...
props
.
tableData
]
newTableData
[
rowIndex
]
=
{
...
row
,
[
col
.
prop
]:
finalValue
}
emit
(
'update:tableData'
,
newTableData
)
emit
(
'cell-change'
,
{
row
:
newTableData
[
rowIndex
],
col
,
newValue
:
finalValue
,
oldValue
:
row
[
col
.
prop
],
rowIndex
,
prop
:
col
.
prop
})
validateField
(
newTableData
[
rowIndex
],
col
.
prop
)
}
// ==================== 数据更新与校验 ====================
// 处理单元格值变更
function
handleCellChange
(
row
,
col
,
newValue
,
rowIndex
)
{
const
rowId
=
row
[
props
.
rowIdKey
]
const
oldValue
=
row
[
col
.
prop
]
if
(
oldValue
===
newValue
)
return
// 更新数据
const
newTableData
=
[...
props
.
tableData
]
newTableData
[
rowIndex
]
=
{
...
row
,
[
col
.
prop
]:
newValue
}
emit
(
'update:tableData'
,
newTableData
)
emit
(
'cell-change'
,
{
row
:
newTableData
[
rowIndex
],
col
,
newValue
,
oldValue
,
rowIndex
,
prop
:
col
.
prop
})
// 触发字段校验
validateField
(
newTableData
[
rowIndex
],
col
.
prop
)
}
// 处理 Select 变化(支持额外字段赋值)
function
handleSelectChange
(
row
,
col
,
value
,
rowIndex
)
{
const
newTableData
=
[...
props
.
tableData
]
const
updatedRow
=
{
...
row
,
[
col
.
prop
]:
value
}
// 处理额外字段赋值
if
(
col
.
onChangeExtraFields
)
{
const
options
=
getSelectOptions
(
col
)
const
opt
=
options
.
find
(
o
=>
o
.
value
===
value
)
if
(
opt
?.
raw
)
{
for
(
const
[
targetProp
,
sourceKey
]
of
Object
.
entries
(
col
.
onChangeExtraFields
))
{
updatedRow
[
targetProp
]
=
opt
.
raw
[
sourceKey
]
}
}
}
newTableData
[
rowIndex
]
=
updatedRow
emit
(
'update:tableData'
,
newTableData
)
emit
(
'selectChange'
,
col
.
prop
,
value
,
col
)
validateField
(
updatedRow
,
col
.
prop
)
}
// 校验单个字段
async
function
validateField
(
row
,
prop
)
{
const
col
=
props
.
columns
.
find
(
c
=>
c
.
prop
===
prop
)
if
(
!
col
)
return
true
const
rules
=
getColumnRules
(
col
)
if
(
!
rules
.
length
)
return
true
const
value
=
row
[
prop
]
const
rowId
=
row
[
props
.
rowIdKey
]
let
errorMsg
=
''
for
(
const
rule
of
rules
)
{
if
(
rule
.
required
&&
(
value
===
undefined
||
value
===
null
||
value
===
''
))
{
errorMsg
=
rule
.
message
||
`
${
col
.
label
}
不能为空`
break
}
if
(
rule
.
pattern
&&
!
rule
.
pattern
.
test
(
String
(
value
)))
{
errorMsg
=
rule
.
message
||
`
${
col
.
label
}
格式不正确`
break
}
if
(
rule
.
validator
&&
typeof
rule
.
validator
===
'function'
)
{
try
{
await
rule
.
validator
(
null
,
value
,
()
=>
{})
}
catch
(
err
)
{
errorMsg
=
err
.
message
break
}
}
}
if
(
!
rowErrors
.
value
[
rowId
])
{
rowErrors
.
value
[
rowId
]
=
{}
}
rowErrors
.
value
[
rowId
][
prop
]
=
errorMsg
return
!
errorMsg
}
// ==================== 全局校验方法(暴露给父组件) ====================
function
validateAll
()
{
const
errors
=
[]
const
allValid
=
[]
for
(
let
i
=
0
;
i
<
props
.
tableData
.
length
;
i
++
)
{
const
row
=
props
.
tableData
[
i
]
const
rowId
=
row
[
props
.
rowIdKey
]
let
rowValid
=
true
for
(
const
col
of
visibleColumns
.
value
)
{
if
(
col
.
editable
===
false
)
continue
const
rules
=
getColumnRules
(
col
)
if
(
rules
.
length
===
0
)
continue
const
value
=
row
[
col
.
prop
]
let
errorMsg
=
''
for
(
const
rule
of
rules
)
{
if
(
rule
.
required
&&
(
value
===
undefined
||
value
===
null
||
value
===
''
))
{
errorMsg
=
rule
.
message
||
`
${
col
.
label
}
不能为空`
break
}
if
(
rule
.
pattern
&&
!
rule
.
pattern
.
test
(
String
(
value
)))
{
errorMsg
=
rule
.
message
||
`
${
col
.
label
}
格式不正确`
break
}
}
if
(
errorMsg
)
{
rowValid
=
false
errors
.
push
({
rowIndex
:
i
,
rowId
,
prop
:
col
.
prop
,
label
:
col
.
label
,
message
:
errorMsg
,
row
})
if
(
!
rowErrors
.
value
[
rowId
])
rowErrors
.
value
[
rowId
]
=
{}
rowErrors
.
value
[
rowId
][
col
.
prop
]
=
errorMsg
}
else
{
if
(
rowErrors
.
value
[
rowId
])
{
rowErrors
.
value
[
rowId
][
col
.
prop
]
=
''
}
}
}
allValid
.
push
(
rowValid
)
}
const
valid
=
allValid
.
every
(
v
=>
v
===
true
)
return
{
valid
,
errors
}
}
async
function
validateAndShow
()
{
const
{
valid
,
errors
}
=
validateAll
()
if
(
!
valid
&&
errors
.
length
>
0
)
{
const
firstError
=
errors
[
0
]
ElMessage
.
warning
(
firstError
.
message
)
return
false
}
return
true
}
// ==================== 远程加载 ====================
async
function
loadDictOptions
(
dictType
)
{
const
dictStore
=
useDictStore
()
let
options
=
dictStore
.
getDict
(
dictType
)
if
(
options
&&
options
.
length
>
0
)
return
options
try
{
const
resp
=
await
getDicts
(
dictType
)
options
=
resp
.
data
.
map
(
p
=>
({
label
:
p
.
itemLabel
,
value
:
p
.
itemValue
,
raw
:
p
}))
dictStore
.
setDict
(
dictType
,
options
)
return
options
}
catch
(
err
)
{
ElMessage
.
error
(
`字典
${
dictType
}
加载失败`
)
return
[]
}
}
async
function
loadRemoteOptions
(
col
)
{
const
{
prop
,
api
,
requestParams
}
=
col
if
(
!
api
)
return
if
(
remoteOptions
.
value
[
prop
]?.
length
>
0
)
return
try
{
remoteLoading
.
value
[
prop
]
=
true
const
payload
=
{
...(
typeof
requestParams
===
'function'
?
requestParams
()
:
requestParams
||
{})
}
const
res
=
await
request
({
url
:
api
,
method
:
'post'
,
data
:
payload
})
const
list
=
typeof
col
.
transform
===
'function'
?
col
.
transform
(
res
)
:
res
.
data
?.
records
||
res
.
data
||
[]
remoteOptions
.
value
[
prop
]
=
list
.
map
(
i
=>
({
value
:
String
(
i
[
col
.
valueKey
||
'value'
]),
label
:
i
[
col
.
labelKey
||
'label'
],
raw
:
i
}))
}
catch
(
err
)
{
ElMessage
.
error
(
`加载
${
col
.
label
}
失败`
)
remoteOptions
.
value
[
prop
]
=
[]
}
finally
{
remoteLoading
.
value
[
prop
]
=
false
}
}
let
searchTimeouts
=
{}
async
function
handleRemoteSearch
(
keyword
,
col
)
{
const
{
prop
,
api
,
requestParams
,
keywordField
=
'keyword'
,
debounceWait
=
300
}
=
col
if
(
!
api
)
return
clearTimeout
(
searchTimeouts
[
prop
])
searchTimeouts
[
prop
]
=
setTimeout
(
async
()
=>
{
try
{
remoteLoading
.
value
[
prop
]
=
true
const
payload
=
{
...(
typeof
requestParams
===
'function'
?
requestParams
()
:
requestParams
||
{}),
[
keywordField
]:
keyword
}
const
res
=
await
request
({
url
:
api
,
method
:
'post'
,
data
:
payload
})
const
list
=
typeof
col
.
transform
===
'function'
?
col
.
transform
(
res
)
:
res
.
data
?.
records
||
res
.
data
||
[]
remoteOptions
.
value
[
prop
]
=
list
.
map
(
i
=>
({
value
:
String
(
i
[
col
.
valueKey
||
'value'
]),
label
:
i
[
col
.
labelKey
||
'label'
],
raw
:
i
}))
}
catch
(
err
)
{
ElMessage
.
error
(
`搜索
${
col
.
label
}
失败`
)
}
finally
{
remoteLoading
.
value
[
prop
]
=
false
}
},
debounceWait
)
}
function
getDisabledDateFn
(
col
)
{
const
{
minDate
,
maxDate
}
=
col
if
(
minDate
==
null
&&
maxDate
==
null
)
return
()
=>
false
return
date
=>
{
const
current
=
dayjs
(
date
).
startOf
(
'day'
)
let
minD
=
null
,
maxD
=
null
if
(
minDate
!=
null
)
{
const
val
=
typeof
minDate
===
'function'
?
minDate
()
:
minDate
minD
=
val
?
dayjs
(
val
).
startOf
(
'day'
)
:
null
}
if
(
maxDate
!=
null
)
{
const
val
=
typeof
maxDate
===
'function'
?
maxDate
()
:
maxDate
maxD
=
val
?
dayjs
(
val
).
startOf
(
'day'
)
:
null
}
return
(
minD
&&
current
.
isBefore
(
minD
))
||
(
maxD
&&
current
.
isAfter
(
maxD
))
}
}
// ==================== 上传相关 ====================
function
getFileListDisplay
(
val
)
{
if
(
!
val
)
return
[]
if
(
Array
.
isArray
(
val
))
return
val
try
{
return
JSON
.
parse
(
val
)
}
catch
{
return
[{
url
:
val
,
name
:
'文件'
}]
}
}
function
beforeUpload
(
file
,
col
)
{
if
(
col
.
maxSize
&&
file
.
size
>
col
.
maxSize
)
{
ElMessage
.
error
(
`文件
${
file
.
name
}
超出大小限制`
)
return
false
}
if
(
col
.
accept
)
{
const
ext
=
'.'
+
file
.
name
.
split
(
'.'
).
pop
().
toLowerCase
()
const
allowed
=
col
.
accept
.
split
(
','
).
map
(
s
=>
s
.
trim
().
toLowerCase
())
if
(
!
allowed
.
includes
(
ext
))
{
ElMessage
.
error
(
`文件类型不支持,仅支持:
${
col
.
accept
}
`
)
return
false
}
}
return
true
}
function
handleUploadSuccess
(
row
,
col
,
response
,
file
,
fileList
)
{
const
data
=
response
.
data
||
response
const
url
=
data
.
url
||
data
.
fileUrl
||
data
.
path
const
name
=
data
.
name
||
data
.
fileName
||
file
.
name
if
(
!
url
)
{
ElMessage
.
error
(
'上传成功但未返回文件地址'
)
return
}
const
currentList
=
getFileListDisplay
(
row
[
col
.
prop
])
const
newFile
=
{
uid
:
file
.
uid
,
url
,
name
}
const
newList
=
[...
currentList
,
newFile
]
const
rowIndex
=
props
.
tableData
.
findIndex
(
r
=>
r
[
props
.
rowIdKey
]
===
row
[
props
.
rowIdKey
])
if
(
rowIndex
!==
-
1
)
{
const
newTableData
=
[...
props
.
tableData
]
newTableData
[
rowIndex
]
=
{
...
row
,
[
col
.
prop
]:
newList
}
emit
(
'update:tableData'
,
newTableData
)
}
ElMessage
.
success
(
`
${
file
.
name
}
上传成功`
)
emit
(
'uploadSuccess'
,
col
.
prop
,
newList
)
}
function
handleUploadError
(
row
,
col
,
error
,
file
,
fileList
)
{
ElMessage
.
error
(
`文件
${
file
.
name
}
上传失败`
)
}
function
removeFile
(
row
,
col
,
index
)
{
const
currentList
=
getFileListDisplay
(
row
[
col
.
prop
])
const
newList
=
[...
currentList
]
newList
.
splice
(
index
,
1
)
const
rowIndex
=
props
.
tableData
.
findIndex
(
r
=>
r
[
props
.
rowIdKey
]
===
row
[
props
.
rowIdKey
])
if
(
rowIndex
!==
-
1
)
{
const
newTableData
=
[...
props
.
tableData
]
newTableData
[
rowIndex
]
=
{
...
row
,
[
col
.
prop
]:
newList
}
emit
(
'update:tableData'
,
newTableData
)
}
}
function
previewFile
(
file
)
{
const
url
=
file
.
url
if
(
!
url
)
return
const
ext
=
(
file
.
name
||
''
).
split
(
'.'
).
pop
().
toLowerCase
()
previewUrl
.
value
=
url
previewFileName
.
value
=
file
.
name
||
'文件'
if
([
'jpg'
,
'jpeg'
,
'png'
,
'gif'
,
'webp'
].
includes
(
ext
))
{
previewFileType
.
value
=
'image'
previewDialogVisible
.
value
=
true
}
else
if
(
ext
===
'pdf'
)
{
previewFileType
.
value
=
'pdf'
previewDialogVisible
.
value
=
true
}
else
{
window
.
open
(
url
,
'_blank'
)
}
}
// ==================== 行操作 ====================
function
handleDelete
(
row
)
{
emit
(
'delete'
,
row
)
}
//新增表格数据
const
addTableData
=
()
=>
{
emit
(
'add'
)
}
// ==================== 分页处理 ====================
function
handleSizeChange
(
val
)
{
pageSize
.
value
=
val
emit
(
'update:limit'
,
val
)
emit
(
'update:page'
,
currentPage
.
value
)
}
function
handleCurrentChange
(
val
)
{
currentPage
.
value
=
val
emit
(
'update:page'
,
val
)
}
watch
(
()
=>
props
.
page
,
val
=>
{
currentPage
.
value
=
val
}
)
watch
(
()
=>
props
.
limit
,
val
=>
{
pageSize
.
value
=
val
}
)
// ==================== 初始化 ====================
onMounted
(
async
()
=>
{
for
(
const
col
of
props
.
columns
)
{
if
(
col
.
editType
===
'select'
)
{
if
(
col
.
dictType
)
{
const
opts
=
await
loadDictOptions
(
col
.
dictType
)
remoteOptions
.
value
[
col
.
prop
]
=
opts
dictLoaded
.
value
.
add
(
col
.
prop
)
}
else
if
(
col
.
api
&&
col
.
preload
!==
false
)
{
await
loadRemoteOptions
(
col
)
}
else
if
(
col
.
options
)
{
remoteOptions
.
value
[
col
.
prop
]
=
[...
col
.
options
]
}
}
}
})
// 暴露方法给父组件
defineExpose
({
validateAll
,
validateAndShow
,
refreshRemoteOptions
:
async
prop
=>
{
const
col
=
props
.
columns
.
find
(
c
=>
c
.
prop
===
prop
)
if
(
col
&&
col
.
api
)
{
remoteOptions
.
value
[
prop
]
=
[]
await
loadRemoteOptions
(
col
)
}
},
clearErrors
:
()
=>
{
rowErrors
.
value
=
{}
}
})
</
script
>
<
style
scoped
>
.common-table
{
width
:
100%
;
}
.addBox
{
margin-bottom
:
10px
;
}
.table-pagination
{
margin-top
:
16px
;
display
:
flex
;
justify-content
:
flex-end
;
}
.operation-buttons
{
display
:
flex
;
gap
:
8px
;
justify-content
:
center
;
}
.table-upload-wrapper
{
display
:
flex
;
flex-direction
:
column
;
gap
:
8px
;
}
.upload-file-list
{
max-height
:
80px
;
overflow-y
:
auto
;
border
:
1px
solid
#dcdfe6
;
border-radius
:
4px
;
padding
:
4px
8px
;
}
.file-item
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
font-size
:
12px
;
padding
:
2px
0
;
}
.file-name
{
flex
:
1
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.preview-container
{
text-align
:
center
;
}
.preview-unsupported
{
padding
:
40px
;
color
:
#909399
;
}
.required-star
{
color
:
#f56c6c
;
margin-left
:
2px
;
}
</
style
>
src/components/commonDialog/filePreviewDialog.vue
0 → 100644
View file @
08e9e2d3
<
template
>
<el-dialog
v-model=
"dialogVisible"
:title=
"displayFileName"
width=
"70%"
:close-on-click-modal=
"false"
destroy-on-close
@
close=
"handleClose"
>
<div
class=
"preview-container"
>
<!-- 图片预览 -->
<div
v-if=
"previewType === 'image'"
class=
"preview-image-wrapper"
>
<img
:src=
"previewUrl"
class=
"preview-image"
alt=
"预览图片"
/>
</div>
<!-- PDF 预览 -->
<iframe
v-else-if=
"previewType === 'pdf'"
:src=
"previewUrl"
class=
"preview-pdf"
frameborder=
"0"
></iframe>
<!-- 不支持预览 -->
<div
v-else-if=
"previewType === 'unsupported'"
class=
"preview-unsupported"
>
<el-icon
:size=
"48"
color=
"#909399"
><Document
/></el-icon>
<p>
暂不支持预览此类型文件
</p>
<el-button
type=
"primary"
@
click=
"handleClose"
>
关闭
</el-button>
</div>
</div>
</el-dialog>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
,
ref
,
watch
}
from
'vue'
import
{
Document
}
from
'@element-plus/icons-vue'
// --- Props 定义 ---
interface
Props
{
modelValue
:
boolean
// 控制弹窗显示/隐藏(支持 v-model)
fileUrl
:
string
// 文件 URL 或 Blob URL
fileName
?:
string
// 文件名(用于弹窗标题及类型推断)
fileType
?:
'image'
|
'pdf'
|
'unsupported'
// 手动指定文件类型(可选)
}
const
props
=
withDefaults
(
defineProps
<
Props
>
(),
{
fileName
:
'文件预览'
,
fileType
:
undefined
})
// --- Emits 定义 ---
const
emit
=
defineEmits
<
{
(
e
:
'update:modelValue'
,
value
:
boolean
):
void
(
e
:
'close'
):
void
}
>
()
// --- 内部状态 ---
// 用于实际绑定到 img/iframe 的 URL,关闭时会清空
const
previewUrl
=
ref
(
''
)
// 弹窗显示状态(双向绑定)
const
dialogVisible
=
computed
({
get
:
()
=>
props
.
modelValue
,
set
:
val
=>
emit
(
'update:modelValue'
,
val
)
})
// 最终显示的标题
const
displayFileName
=
computed
(()
=>
props
.
fileName
||
'文件预览'
)
// --- 文件类型推断 ---
const
previewType
=
computed
<
'image'
|
'pdf'
|
'unsupported'
>
(()
=>
{
// 1. 若外部显式传入 fileType,优先使用
if
(
props
.
fileType
)
{
return
props
.
fileType
}
// 2. 根据 fileUrl 或 fileName 的后缀名自动判断
const
url
=
props
.
fileUrl
||
''
const
name
=
props
.
fileName
||
''
const
lowerUrl
=
url
.
toLowerCase
()
const
lowerName
=
name
.
toLowerCase
()
const
imageExts
=
[
'.jpg'
,
'.jpeg'
,
'.png'
,
'.gif'
,
'.webp'
,
'.bmp'
,
'.svg'
]
const
isImage
=
(
str
:
string
)
=>
imageExts
.
some
(
ext
=>
str
.
endsWith
(
ext
))
const
isPdf
=
(
str
:
string
)
=>
str
.
endsWith
(
'.pdf'
)
if
(
isImage
(
lowerUrl
)
||
isImage
(
lowerName
))
return
'image'
if
(
isPdf
(
lowerUrl
)
||
isPdf
(
lowerName
))
return
'pdf'
return
'unsupported'
})
// --- 同步外部 URL 到预览 URL ---
// 当弹窗打开时,将 fileUrl 赋值给 previewUrl
// 当弹窗关闭时,清空 previewUrl,释放资源
watch
(
()
=>
props
.
modelValue
,
visible
=>
{
if
(
visible
&&
props
.
fileUrl
)
{
previewUrl
.
value
=
props
.
fileUrl
}
else
if
(
!
visible
)
{
previewUrl
.
value
=
''
}
},
{
immediate
:
true
}
)
// 如果弹窗已打开但 fileUrl 发生变化(例如父组件动态修改),同步更新预览内容
watch
(
()
=>
props
.
fileUrl
,
newUrl
=>
{
if
(
dialogVisible
.
value
&&
newUrl
)
{
previewUrl
.
value
=
newUrl
}
}
)
// --- 关闭处理 ---
const
handleClose
=
()
=>
{
dialogVisible
.
value
=
false
// 关闭弹窗
previewUrl
.
value
=
''
// 清空预览地址
emit
(
'close'
)
// 通知父组件
}
</
script
>
<
style
scoped
>
.preview-container
{
width
:
100%
;
min-height
:
400px
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
}
.preview-image-wrapper
{
width
:
100%
;
text-align
:
center
;
}
.preview-image
{
max-width
:
100%
;
max-height
:
70vh
;
object-fit
:
contain
;
}
.preview-pdf
{
width
:
100%
;
height
:
70vh
;
}
.preview-unsupported
{
text-align
:
center
;
padding
:
40px
;
}
.preview-unsupported
p
{
margin
:
20px
0
;
color
:
#909399
;
}
</
style
>
src/utils/validate.js
View file @
08e9e2d3
...
...
@@ -597,7 +597,42 @@ export const validateIdCardSimple = (rule, value, callback) => {
callback
()
}
/**
* 英文姓名校验规则
*/
export
const
validateEnglish2
=
(
value
)
=>
{
if
(
!
value
)
{
// 如果值为空且字段不是必填的,直接通过校验
return
}
// 1. 基本字符检查
if
(
!
/^
[
A-Za-z
\s\-
'.
]
+$/
.
test
(
value
))
{
return
"包含非法字符,只允许英文字母、空格、-、'和."
}
// 2. 首字母大写检查
// if (!/^[A-Z]/.test(value)) {
// return callback(new Error('名字应以大写字母开头'))
// }
// 3. 长度检查
if
(
value
.
length
<
2
)
{
return
'名字至少需要2个字符'
}
// 4. 连续特殊字符检查
if
(
/
[\s\-
'.
]{2,}
/
.
test
(
value
))
{
return
'不能连续使用特殊字符'
}
// 5. 开头或结尾不能是特殊字符
if
(
/^
[\s\-
'.
]
|
[\s\-
'.
]
$/
.
test
(
value
.
trim
()))
{
return
'名字不能以特殊字符开头或结尾'
}
return
''
}
// 将身份证验证方法添加到默认导出对象中
export
default
{
validateEnglish
,
...
...
@@ -605,5 +640,6 @@ export default {
validatePhone
,
validateBMI
,
validateIdCard
,
validateIdCardSimple
validateIdCardSimple
,
validateEnglish2
}
src/views/financialCenter/financialBilling.vue
View file @
08e9e2d3
...
...
@@ -15,28 +15,49 @@
<template
#
searchForm
>
<SearchForm
ref=
"searchFormRef"
:config=
"searchConfig"
/>
</
template
>
1111
<!-- 列表区域 -->
<
template
#
table
>
<!-- 统计信息卡片 v-if="statisticsData.totalInAmount > 0"-->
<div
class=
"statistics-container"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"入账金额"
:value=
"statisticsData.totalInAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"入账金额"
:value=
"statisticsData.totalInAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保费(HKD)"
:value=
"statisticsData.totalPremium"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保费(HKD)"
:value=
"statisticsData.totalPremium"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"待出账金额"
:value=
"statisticsData.pendingOutAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-statistic
title=
"待出账金额"
:value=
"statisticsData.pendingOutAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"可出账金额"
:value=
"statisticsData.availableOutAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"可出账金额"
:value=
"statisticsData.availableOutAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"差额(估)"
:value=
"statisticsData.differenceAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"差额(估)"
:value=
"statisticsData.differenceAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
</el-row>
</div>
...
...
@@ -50,6 +71,8 @@
v-loading=
"loading"
>
<el-table-column
type=
"selection"
width=
"40"
/>
<el-table-column
prop=
"policyNo"
label=
"业务编号"
width=
"120"
sortable
/>
<el-table-column
prop=
"isPart"
label=
"是否拆分出账"
width=
"120"
/>
<el-table-column
prop=
"fortuneBizType"
label=
"应付单类型"
width=
"120"
sortable
>
<template
#
default=
"
{ row }">
{{
getFortuneBizTypeLabel
(
row
.
fortuneBizType
)
}}
...
...
@@ -62,14 +85,21 @@
label=
"累积已入账金额"
width=
"120"
sortable
:formatter=
"row=>
formatCurrency(row.commissionPaidAmount || 0)"
:formatter=
"row =>
formatCurrency(row.commissionPaidAmount || 0)"
/>
<el-table-column
<
!-- <
el-table-column
prop="commissionPaidRatio"
label="累积实佣率"
width="120"
sortable
:formatter="row => `${row.commissionPaidRatio ? row.commissionPaidRatio : 0}%`"
/> -->
<el-table-column
prop=
"commissionPaidRatio"
label=
"达成率缺口"
width=
"120"
sortable
:formatter=
"row => `${row.commissionPaidRatio ? row.commissionPaidRatio : 0}%`"
/>
<el-table-column
prop=
"fortuneName"
label=
"出账项目"
width=
"130"
sortable
/>
<el-table-column
prop=
"fortunePeriod"
label=
"出账期数"
width=
"130"
sortable
/>
...
...
@@ -77,17 +107,35 @@
<el-table-column
prop=
"broker"
label=
"转介人"
width=
"130"
sortable
/>
<el-table-column
prop=
"team"
label=
"所属团队"
width=
"120"
sortable
/>
<el-table-column
prop=
"exchangeRate"
label=
"结算汇率(估)"
width=
"140"
sortable
/>
<el-table-column
prop=
"hkdAmount"
label=
"应出账金额(HKD)"
width=
"160"
sortable
:formatter=
"row=>formatCurrency(row.hkdAmount || 0)"
/>
<el-table-column
prop=
"hkdAmount"
label=
"应出账金额(HKD)"
width=
"160"
sortable
:formatter=
"row => formatCurrency(row.hkdAmount || 0)"
/>
<el-table-column
prop=
"currency"
label=
"出账币种"
width=
"130"
sortable
/>
<el-table-column
prop=
"fortunePaidAmount"
label=
"已出账金额"
width=
"160"
sortable
:formatter=
"row=>formatCurrency(row.fortunePaidAmount || 0)"
/>
<el-table-column
prop=
"fortuneUnpaidAmount"
label=
"剩余出账金额"
width=
"160"
sortable
:formatter=
"row=>formatCurrency(row.fortuneUnpaidAmount || 0)"
/>
<el-table-column
prop=
"fortunePaidAmount"
label=
"已出账金额"
width=
"160"
sortable
:formatter=
"row => formatCurrency(row.fortunePaidAmount || 0)"
/>
<el-table-column
prop=
"fortuneUnpaidAmount"
label=
"剩余出账金额"
width=
"160"
sortable
:formatter=
"row => formatCurrency(row.fortuneUnpaidAmount || 0)"
/>
<!-- <el-table-column prop="currentPaymentAmount" label="本期出账金额" width="120" sortable/> -->
<el-table-column
prop=
"currentPaymentHkdAmount"
label=
"本期出账金额(HKD)"
width=
"160"
sortable
:formatter=
"row=>
formatCurrency(row.currentPaymentHkdAmount || 0)"
:formatter=
"row =>
formatCurrency(row.currentPaymentHkdAmount || 0)"
/>
<el-table-column
prop=
"fortuneUnpaidRatio"
...
...
@@ -101,7 +149,13 @@
{{
selectDictLabel
(
csf_fortune_status
,
row
.
status
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
:formatter=
"row=>formatCurrency(row.premium || 0)"
/>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
:formatter=
"row => formatCurrency(row.premium || 0)"
/>
<el-table-column
prop=
"policyCurrency"
label=
"保单币种"
width=
"120"
sortable
/>
<el-table-column
prop=
"payoutDate"
label=
"出账日(估)"
width=
"120"
sortable
/>
<el-table-column
prop=
"actualPayoutDate"
label=
"出账日(实)"
width=
"120"
sortable
/>
...
...
@@ -152,6 +206,7 @@
ref=
"addCheckRecordFormRef"
:config=
"addCheckRecordConfig"
v-model=
"addCheckRecordFormModel"
@
inputChange=
"(prop, value, item) => handleInputChange('addCheckRecord', prop, value, item)"
/>
</CommonDialog>
<!-- 导入出账检核页面 -->
...
...
@@ -187,26 +242,96 @@
v-model=
"setPayoutAmountFormModel"
/>
</CommonDialog>
<!-- 分期出账弹窗 -->
<CommonDialog
dialogTitle=
"分期出账"
dialogWidth=
"80%"
confirmText=
"提交"
:openDialog=
"installmentsBillFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"installmentsBillFlag = false"
@
confirm=
"handleSpiltSubmit"
>
<editTable
ref=
"editTableRef"
addBtnTxt=
"添加出账"
v-model:table-data=
"splitTableData"
:columns=
"splitTableColumns"
row-id-key=
"id"
show-operation
@
delete=
"handleSpiltDelete"
@
add=
"addSpiltRecord"
@
cell-change=
"handleSplitCellChange"
/>
</CommonDialog>
<!-- 设置出账年月弹窗 -->
<CommonDialog
dialogTitle=
"设置本期出账金额"
dialogWidth=
"80%"
:openDialog=
"settingBillYearMonthFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"settingBillYearMonthFlag = false"
@
confirm=
"submitSettingBillYearMonth"
>
<SearchForm
ref=
"settingBillYearMonthRef"
:config=
"settingBillTimeConfig"
v-model=
"settingBillTimeForm"
/>
</CommonDialog>
<!-- 修改结算汇率 -->
<CommonDialog
dialogTitle=
"修改结算汇率"
dialogWidth=
"80%"
:openDialog=
"rateExchangeFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"rateExchangeFlag = false"
@
confirm=
"confirmRateExchange"
>
<SearchForm
ref=
"rateExchangeFormRef"
:config=
"rateExchangeConfig"
v-model=
"rateExchangeForm"
@
inputChange=
"(prop, value, item) => handleInputChange('rateExchange', prop, value, item)"
/>
</CommonDialog>
</div>
</template>
<
script
setup
>
import
{
ref
,
reactive
}
from
'vue'
import
{
round
}
from
'lodash-es'
// 或者自己实现小数保留
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
import
CommonPage
from
'@/components/commonPage'
import
editTable
from
'@/components/Table/editTable.vue'
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
,
billSplitApi
,
commissionExchangeRateApi
,
actualPayoutDateApi
,
editExchangeRateApi
}
from
'@/api/financial/commission'
import
useUserStore
from
'@/store/modules/user'
const
rateExchangeFormRef
=
ref
(
null
)
const
rateExchangeFlag
=
ref
(
false
)
const
rateExchangeForm
=
ref
({})
const
billTimeType
=
ref
(
'single'
)
const
settingBillTimeForm
=
ref
({})
const
splitTableData
=
ref
([])
const
installmentsBillFlag
=
ref
(
false
)
const
settingBillYearMonthFlag
=
ref
(
false
)
const
{
proxy
}
=
getCurrentInstance
()
const
{
csf_fortune_status
}
=
proxy
.
useDict
(
'csf_fortune_status'
)
...
...
@@ -219,6 +344,13 @@ const loading = ref(false)
const
selectedRow
=
ref
(
null
)
const
searchFormRef
=
ref
(
null
)
const
searchParams
=
ref
({})
// 表格操作菜单
const
dropdownItems
=
[
// { label: '设置本期出账金额', value: 'setPayRoll' }
{
label
:
'分期出账'
,
value
:
'billInstallments'
},
{
label
:
'设置出账年月(实)'
,
value
:
'settingBillYearMonth'
},
{
label
:
'修改结算汇率'
,
value
:
'editExchangeRate'
}
]
const
searchConfig
=
ref
([
{
type
:
'input'
,
...
...
@@ -226,6 +358,11 @@ const searchConfig = ref([
label
:
'保单号'
},
{
type
:
'input'
,
prop
:
'broker'
,
label
:
'转介人'
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'出账状态'
,
...
...
@@ -287,17 +424,271 @@ const searchConfig = ref([
dictType
:
'csf_expected_commission_status'
}
])
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'设置本期出账金额'
,
value
:
'setPayRoll'
}
// { label: '更新', value: 'editRecord' },
// { label: '查看记录', value: 'viewRecord' }
const
editTableRef
=
ref
(
null
)
const
splitTableColumns
=
ref
([
{
prop
:
'splitRatio'
,
label
:
'出账比例'
,
editType
:
'input'
,
inputType
:
'decimal'
,
// integer / decimalNumber / decimal
decimalDigits
:
2
,
// 小数位数,默认2
required
:
true
,
placeholder
:
'请输入金额'
},
{
prop
:
'amount'
,
label
:
'原币种金额'
,
editType
:
'input'
,
inputType
:
'decimalNumber'
,
// integer / decimalNumber / decimal
decimalDigits
:
2
,
// 小数位数,默认2
required
:
true
},
{
prop
:
'originalAmount'
,
label
:
'本次出账原币种金额'
,
editType
:
'input'
,
inputType
:
'decimalNumber'
,
// integer / decimalNumber / decimal
decimalDigits
:
2
,
// 小数位数,默认2
required
:
true
},
{
prop
:
'exchangeRate'
,
label
:
'结算汇率'
,
editType
:
'input'
,
inputType
:
'decimal'
,
// integer / decimalNumber / decimal
decimalDigits
:
2
,
// 小数位数,默认2
required
:
true
},
{
prop
:
'hkdAmount'
,
label
:
'港币出账金额'
,
editType
:
'input'
,
inputType
:
'decimalNumber'
,
// integer / decimalNumber / decimal
decimalDigits
:
2
,
// 小数位数,默认2
required
:
true
},
{
prop
:
'payoutYearMonth'
,
label
:
'出账年月(估)'
,
editType
:
'month'
,
required
:
true
},
{
prop
:
'remark'
,
label
:
'备注'
,
editType
:
'input'
,
inputType
:
'textarea'
,
required
:
false
}
// {
// prop: 'userId',
// label: '负责人',
// editType: 'select',
// api: '/insurance/base/api/insuranceCompany/page', // 接口地址
// valueKey: 'insuranceCompanyBizId', // 选项 value 字段名
// labelKey: 'fullName', // 选项 label 字段名
// preload: true, // 初始化时自动加载
// requestParams: { pageNo: 1, pageSize: 20 }, // 固定参数
// // 远程搜索配置
// filterable: true,
// keywordField: 'keyword',
// debounceWait: 300
// },
// {
// prop: 'status',
// label: '状态',
// editType: 'select',
// dictType: 'sys_status', // 系统字典类型
// required: true
// }
])
const
settingBillTimeConfig
=
ref
([
{
type
:
'month'
,
prop
:
'actualPayoutDate'
,
label
:
'出账年月(实)'
,
placeholder
:
'出账年月(实)'
,
rules
:
[{
required
:
true
,
message
:
'请选择出账年月(实)'
,
trigger
:
'blur'
}]
}
])
const
rateExchangeConfig
=
[
{
type
:
'input'
,
prop
:
'originalAmount'
,
label
:
'本期出账原币种金额'
,
inputType
:
'decimal'
,
rules
:
[{
required
:
true
,
message
:
'只能输入正整数和小数'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'exchangeRate'
,
label
:
'结算汇率'
,
inputType
:
'decimal'
,
rules
:
[{
required
:
true
,
message
:
'只能输入正整数和小数'
,
trigger
:
'blur'
}]
// defaultValue: 1
},
{
type
:
'input'
,
prop
:
'hkdAmount'
,
label
:
'港币出账金额'
,
inputType
:
'decimal'
,
rules
:
[{
required
:
true
,
message
:
'只能输入正整数和小数'
,
trigger
:
'blur'
}]
}
]
// 应收单类型
const
fortuneBizTypeOptions
=
[
{
value
:
'R'
,
label
:
'关联保单应付单'
},
{
value
:
'U'
,
label
:
'非关联保单应付单'
}
]
const
confirmRateExchange
=
async
()
=>
{
let
formData
=
await
rateExchangeFormRef
.
value
.
validate
()
formData
.
fortuneBizId
=
selectedRow
.
value
.
fortuneBizId
try
{
//等待后端接口
const
res
=
await
editExchangeRateApi
(
formData
)
ElMessage
.
success
(
'结算汇率修改成功'
)
rateExchangeFlag
.
value
=
false
loadTableData
()
}
catch
(
error
)
{
ElMessage
.
success
(
'结算汇率修改失败'
)
rateExchangeFlag
.
value
=
true
if
(
error
.
message
&&
error
.
message
.
includes
(
'Validation'
))
{
ElMessage
.
error
(
'必填项不能为空'
)
}
}
}
const
handleInputChange
=
async
(
formType
,
prop
,
value
,
item
)
=>
{
if
(
formType
==
'rateExchange'
)
{
if
(
prop
===
'exchangeRate'
&&
value
&&
rateExchangeForm
.
value
.
originalAmount
)
{
// 计算港币金额
const
originalAmount
=
rateExchangeForm
.
value
.
originalAmount
const
exchangeRate
=
value
const
hkdAmount
=
multiply
(
originalAmount
,
exchangeRate
,
2
)
await
nextTick
()
rateExchangeForm
.
value
.
hkdAmount
=
hkdAmount
}
else
if
(
prop
===
'originalAmount'
&&
value
&&
rateExchangeForm
.
value
.
exchangeRate
)
{
// 计算港币金额
const
originalAmount
=
rateExchangeForm
.
value
.
originalAmount
const
exchangeRate
=
value
const
hkdAmount
=
multiply
(
originalAmount
,
exchangeRate
,
2
)
await
nextTick
()
rateExchangeForm
.
value
.
hkdAmount
=
hkdAmount
}
else
if
((
prop
===
'exchangeRate'
||
prop
===
'originalAmount'
)
&&
!
value
)
{
await
nextTick
()
rateExchangeForm
.
value
.
hkdAmount
=
''
}
}
else
if
(
formType
==
'addCheckRecord'
)
{
await
nextTick
()
let
policyNo
=
addCheckRecordFormModel
.
value
.
policyNo
let
fortunePeriod
=
addCheckRecordFormModel
.
value
.
fortunePeriod
if
((
prop
==
'policyNo'
||
prop
==
'fortunePeriod'
)
&&
fortunePeriod
&&
policyNo
)
{
//等待后端接口
const
res
=
await
commissionExchangeRateApi
({
policyNo
:
policyNo
,
commissionPeriod
:
fortunePeriod
})
if
(
res
.
code
==
200
)
{
addCheckRecordFormModel
.
value
.
exchangeRate
=
res
.
data
}
else
{
ElMessage
.
error
(
'查询结算汇率失败'
)
}
}
}
}
// 精确乘法并保留小数位数
const
multiply
=
(
a
,
b
,
digits
=
2
)
=>
{
if
(
a
==
null
||
b
==
null
)
return
null
const
numA
=
parseFloat
(
a
)
const
numB
=
parseFloat
(
b
)
if
(
isNaN
(
numA
)
||
isNaN
(
numB
))
return
null
return
round
(
numA
*
numB
,
digits
)
}
const
handleSplitCellChange
=
({
row
,
col
,
newValue
,
oldValue
,
rowIndex
,
prop
})
=>
{
// 避免同一字段重复触发(如修改 chuAmount 会触发 hkdAmount 计算,该计算会再次触发 cell-change)
// 通过比较新旧值跳过无实际变化的更新
// if (newValue === oldValue) return
const
currentRow
=
splitTableData
.
value
[
rowIndex
]
if
(
!
currentRow
)
return
let
needUpdate
=
false
const
updatedRow
=
{
...
currentRow
}
// 联动规则1:出账比例 或 原币种金额 变化 → 重算 本次出账原币种金额
if
(
prop
===
'splitRatio'
||
prop
===
'amount'
)
{
const
ratio
=
prop
===
'splitRatio'
?
newValue
:
currentRow
.
splitRatio
const
amount
=
prop
===
'amount'
?
newValue
:
currentRow
.
amount
const
newChuAmount
=
multiply
(
amount
,
ratio
,
2
)
updatedRow
.
originalAmount
=
newChuAmount
needUpdate
=
true
}
// 联动规则2:汇率 或 本次出账原币种金额 变化 → 重算 港币金额
if
(
prop
===
'exchangeRate'
||
prop
===
'originalAmount'
)
{
const
rate
=
prop
===
'exchangeRate'
?
newValue
:
currentRow
.
exchangeRate
const
chuAmt
=
prop
===
'originalAmount'
?
newValue
:
currentRow
.
originalAmount
const
newHkdAmount
=
multiply
(
chuAmt
,
rate
,
2
)
updatedRow
.
hkdAmount
=
newHkdAmount
needUpdate
=
true
console
.
log
(
'updatedRow.hkdAmount'
,
updatedRow
.
hkdAmount
)
}
// 如果用户手动修改了 hkdAmount,不做反向联动(符合需求)
if
(
needUpdate
)
{
// 更新表格数据(整体替换,触发视图更新)
const
newData
=
[...
splitTableData
.
value
]
newData
[
rowIndex
]
=
updatedRow
splitTableData
.
value
=
newData
}
}
const
handleSpiltSubmit
=
async
()
=>
{
// 调用组件的校验方法
const
isValid
=
await
editTableRef
.
value
.
validateAndShow
()
if
(
isValid
)
{
try
{
let
params
=
{
fortuneBizId
:
selectedRow
.
value
.
fortuneBizId
,
fortuneSplitDtoList
:
splitTableData
.
value
}
console
.
log
(
'分期出账参数'
,
params
)
const
res
=
await
billSplitApi
(
params
)
console
.
log
(
'分期出账结果'
,
res
)
installmentsBillFlag
.
value
=
false
ElMessage
.
success
(
'分期出账已保存'
)
loadTableData
()
}
catch
(
error
)
{
installmentsBillFlag
.
value
=
true
console
.
log
(
'分期出账错误'
,
error
)
ElMessage
.
error
(
'分期出账失败'
)
}
}
}
const
handleSpiltDelete
=
row
=>
{
let
index
=
splitTableData
.
value
.
findIndex
(
item
=>
item
.
id
==
row
.
id
)
splitTableData
.
value
.
splice
(
index
,
1
)
}
// 生成临时唯一ID
let
nextId
=
1
const
generateId
=
()
=>
Date
.
now
()
+
nextId
++
// 添加出账
const
addSpiltRecord
=
()
=>
{
const
newRow
=
{
id
:
generateId
(),
// 必须有 rowIdKey 对应的字段(默认 'id')
splitRatio
:
''
,
// 出账比例
amount
:
selectedRow
.
value
.
amount
,
// 原币种金额
exchangeRate
:
''
,
// 结算汇率
hkdAmount
:
''
,
// 港币出账金额
payoutYearMonth
:
''
,
// 出账年月(估)
originalAmount
:
''
,
//本次出账原币种金额
remark
:
''
// 备注
}
// 插入到表格数据最前面
splitTableData
.
value
.
push
(
newRow
)
}
// 应付单类型通过value转成label
const
getFortuneBizTypeLabel
=
value
=>
{
const
item
=
fortuneBizTypeOptions
.
find
(
item
=>
item
.
value
===
value
)
...
...
@@ -383,12 +774,19 @@ const addCheckRecordConfig = [
onChangeExtraFields
:
{
broker
:
'realName'
,
// 自动同步 raw.name 到 reconciliationCompany
reconciliationCompanyCode
:
'code'
,
team
:
'deptName'
,
teamBizId
:
'deptBizId'
,
team
:
'deptName'
,
teamBizId
:
'deptBizId'
},
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'input'
,
prop
:
'exchangeRate'
,
label
:
'结算汇率'
,
inputType
:
'decimal'
,
decimalDigits
:
2
}
]
...
...
@@ -517,6 +915,16 @@ const handleSelect = (e, row) => {
selectedRow
.
value
=
row
if
(
e
===
'setPayRoll'
)
{
setPayoutAmountDialogFlag
.
value
=
true
}
else
if
(
e
==
'billInstallments'
)
{
splitTableData
.
value
=
[]
installmentsBillFlag
.
value
=
true
}
else
if
(
e
==
'settingBillYearMonth'
)
{
billTimeType
.
value
=
'single'
settingBillTimeForm
.
value
=
{}
settingBillYearMonthFlag
.
value
=
true
}
else
if
(
e
==
'editExchangeRate'
)
{
rateExchangeForm
.
value
=
{
originalAmount
:
row
.
amount
}
rateExchangeFlag
.
value
=
true
}
}
const
addCheckRecordaddBatchapi
=
async
data
=>
{
...
...
@@ -568,22 +976,55 @@ const handleSelectionChange = val => {
// 完成检核按钮是否禁用
updatePayRollStatusDisable
.
value
=
val
.
length
===
0
}
const
downloadPolicyFortuneAccountapi
=
async
data
=>
{
console
.
log
(
'生成出账清单:'
,
data
)
try
{
const
res
=
await
downloadPolicyFortuneAccount
({
fortuneBizIdList
:
multipleSelection
.
value
.
map
(
item
=>
item
.
fortuneBizId
)
})
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'完成检核,等待关账'
)
const
submitSettingBillYearMonth
=
async
()
=>
{
if
(
billTimeType
.
value
==
'multiple'
)
{
//等后端接口
// try {
// const res = await downloadPolicyFortuneAccount({
// fortuneBizIdList: multipleSelection.value.map(item => item.fortuneBizId)
// })
// if (res.code === 200) {
// ElMessage.success('完成检核,等待关账')
// loadTableData()
// }
// } catch (error) {
// console.error('检核失败:', error)
// ElMessage.error(error.response?.data?.msg || '检核失败')
// }
}
else
if
(
billTimeType
.
value
==
'single'
)
{
const
params
=
{
fortuneBizId
:
selectedRow
.
value
.
fortuneBizId
,
actualPayoutDate
:
settingBillTimeForm
.
value
.
actualPayoutDate
}
try
{
const
singleRes
=
await
actualPayoutDateApi
(
params
)
ElMessage
.
success
(
'设置出账年月成功'
)
settingBillYearMonthFlag
.
value
=
false
loadTableData
()
}
catch
(
error
)
{
ElMessage
.
error
(
'设置出账年月失败'
)
settingBillYearMonthFlag
.
value
=
true
}
}
catch
(
error
)
{
console
.
error
(
'检核失败:'
,
error
)
ElMessage
.
error
(
error
.
response
?.
data
?.
msg
||
'检核失败'
)
}
}
const
downloadPolicyFortuneAccountapi
=
async
data
=>
{
console
.
log
(
'生成出账清单:'
,
data
)
settingBillYearMonthFlag
.
value
=
true
settingBillTimeForm
.
value
=
{}
billTimeType
.
value
=
'multiple'
// try {
// const res = await downloadPolicyFortuneAccount({
// fortuneBizIdList: multipleSelection.value.map(item => item.fortuneBizId)
// })
// if (res.code === 200) {
// ElMessage.success('完成检核,等待关账')
// loadTableData()
// }
// } catch (error) {
// console.error('检核失败:', error)
// ElMessage.error(error.response?.data?.msg || '检核失败')
// }
}
import
FileUploadPreview
from
'@/components/fileUploadPreview/fileUploadPreview.vue'
const
importCheckRecordFlag
=
ref
(
false
)
...
...
src/views/financialCenter/financialIncome.vue
View file @
08e9e2d3
<
template
>
<div
class=
'container'
>
<CommonPage
:operationBtnList=
'operationBtnList'
:visibleDefaultButtons=
"visibleDefaultButtons"
:showSearchForm=
'true'
:show-pagination=
'true'
:total=
'pageTotal'
:current-page=
'currentPage'
:page-size=
'pageSize'
@
size-change=
'handleSizeChange'
@
current-change=
'handleCurrentChange'
>
<div
class=
"container"
>
<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"
/>
...
...
@@ -12,47 +20,87 @@
<!-- 统计信息卡片 -->
<div
class=
"statistics-container"
v-if=
"statisticsData.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保费(HKD)"
:value=
"statisticsData.totalPremium"
:formatter=
"value=>formatCurrency(value)"
/>
<el-statistic
title=
"总保费(HKD)"
:value=
"statisticsData.totalPremium"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"对账公司数"
:value=
"statisticsData.reconciliationCompanyCount"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"对账公司数"
:value=
"statisticsData.reconciliationCompanyCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"比对记录总条数"
:value=
"statisticsData.totalCompareCommissionCount"
/>
<el-statistic
title=
"比对记录总条数"
:value=
"statisticsData.totalCompareCommissionCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"比对成功数"
:value=
"statisticsData.successCompareCommissionCount"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"比对成功数"
:value=
"statisticsData.successCompareCommissionCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"比对失败数"
:value=
"statisticsData.failedCompareCommissionCount"
/>
<el-statistic
title=
"比对失败数"
:value=
"statisticsData.failedCompareCommissionCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"入账金额(实)"
:value=
"statisticsData.totalPaidAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-statistic
title=
"入账金额(实)"
:value=
"statisticsData.totalPaidAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"入账金额(估)"
:value=
"statisticsData.expectePaidAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-statistic
title=
"入账金额(估)"
:value=
"statisticsData.expectePaidAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"差额(估)"
:value=
"statisticsData.differenceAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"差额(估)"
:value=
"statisticsData.differenceAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
</el-row>
</div>
<el-row>
<el-col
:span=
"6"
>
<el-text
tag=
"mark"
class=
"mx-1"
>
实佣率=实际入账金额/结算汇率/每期保费
</el-text>
<el-text
tag=
"mark"
class=
"mx-1"
>
实佣率=实际入账金额/结算汇率/每期保费
</el-text>
</el-col>
<el-col
:span=
"6"
>
<el-text
tag=
"mark"
class=
"mx-1"
>
达成率缺口= 1 - 本期实佣率/
产品本期来佣率
</el-text>
<el-text
tag=
"mark"
class=
"mx-1"
>
达成率缺口= 1 - 本期实佣率/
保单本期来佣率
</el-text>
</el-col>
</el-row>
<el-table
:data=
"tableData"
ref=
"multipleTableRef"
height=
"400"
row-key=
"id"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
@
selection-change=
"handleSelectionChange"
>
<el-table
:data=
"tableData"
ref=
"multipleTableRef"
height=
"400"
row-key=
"id"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"40"
:selectable=
"selectableFn"
/>
<el-table-column
prop=
"commissionStatus"
label=
"比对状态"
width=
"120"
sortable
fixed=
"left"
>
<el-table-column
prop=
"commissionStatus"
label=
"比对状态"
width=
"120"
sortable
fixed=
"left"
>
<template
#
default=
"
{ row }">
{{
selectDictLabel
(
csf_commission_status
,
row
.
commissionStatus
)
}}
</
template
>
...
...
@@ -71,17 +119,53 @@
{{
selectDictLabel
(
csf_expected_commission_status
,
row
.
commissionExpectedStatus
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"currentCommissionRatio"
label=
"本次实佣率"
width=
"130"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"paidRatio"
label=
"累积实佣率"
width=
"130"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"pendingRatio"
label=
"达成率缺口"
width=
"120"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"amount"
label=
"本次入账金额"
width=
"130"
sortable
:formatter=
"formatCurrencyUtil"
/>
<el-table-column
prop=
"currentCommissionRatio"
label=
"本次实佣率"
width=
"130"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"paidRatio"
label=
"累积实佣率"
width=
"130"
sortable
:formatter=
"formatRatio"
/>
<el-table-column
prop=
"pendingRatio"
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
:formatter=
"formatCurrencyUtil"
/>
<el-table-column
prop=
"premium"
label=
"期交保费"
width=
"120"
sortable
:formatter=
"formatCurrencyUtil"
/>
<el-table-column
prop=
"policyCurrency"
label=
"保单币种"
width=
"120"
sortable
/>
<el-table-column
prop=
"policyCurrency"
label=
"产品名称"
width=
"120"
/>
<el-table-column
prop=
"policyCurrency"
label=
"保单本期来佣率"
width=
"120"
/>
<el-table-column
prop=
"policyCurrency"
label=
"投保人"
width=
"120"
/>
<el-table-column
prop=
"policyCurrency"
label=
"投保人(英文)"
width=
"120"
/>
<el-table-column
prop=
"policyCurrency"
label=
"转介人"
width=
"120"
/>
<el-table-column
prop=
"policyCurrency"
label=
"保险公司"
width=
"120"
/>
<el-table-column
prop=
"remark"
label=
"备注"
width=
"120"
sortable
/>
<el-table-column
prop=
"isDeleted"
label=
"记录状态"
width=
"120"
sortable
>
<
template
#
default=
"{ row }"
>
...
...
@@ -99,9 +183,17 @@
<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"
>
<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
>
...
...
@@ -119,17 +211,27 @@
<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-button
type=
"primary"
:icon=
"Select"
:disabled=
"updatePayRollStatusDisable"
@
click=
"generateCommissionRecordapi"
>
{{ multipleSelection.length }} 条数据,生成可出账记录
</el-button
>
</el-col>
</el-row>
</div>
</template>
</CommonPage>
<!-- 开始检核弹窗-->
<CommonDialog
dialogTitle=
'开始检核'
dialogWidth=
'80%'
:openDialog=
dialogFlag
:showAction=
'false'
:showClose=
'true'
@
close=
"closthDialog()"
>
<CommonDialog
dialogTitle=
"开始检核"
dialogWidth=
"80%"
:openDialog=
"dialogFlag"
:showAction=
"false"
:showClose=
"true"
@
close=
"closthDialog()"
>
<el-row>
<el-col
:xs=
"24"
:sm=
"24"
:md=
"24"
:lg=
"24"
>
<SearchForm
ref=
"checkFormRef"
:config=
"checkConfig"
v-model=
"checkFormData"
/>
...
...
@@ -137,12 +239,22 @@
</el-row>
<el-row
:gutter=
"10"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"3"
:lg=
"3"
>
<el-button
type=
"primary"
:icon=
"Plus"
:disabled=
"!checkFormData?.reconciliationYearMonth"
@
click=
"handleAddCheckList()"
>
新增
</el-button>
<el-button
type=
"primary"
:icon=
"Plus"
:disabled=
"!checkFormData?.reconciliationYearMonth"
@
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"
@
click=
"fileUploadDialogFlag = true;"
>
导入
</el-button>
<el-button
type=
"primary"
:icon=
"Upload"
:disabled=
"!checkFormData?.reconciliationYearMonth"
@
click=
"fileUploadDialogFlag = true"
>
导入
</el-button
>
</el-col>
<el-col
:xs=
"24"
:sm=
"24"
:md=
"3"
:lg=
"3"
>
<el-button
type=
"primary"
link
@
click=
"downloadTemplate"
>
下载模板
</el-button>
...
...
@@ -180,11 +292,16 @@
<el-button
type=
"primary"
text
size=
"small"
@
click=
"checkRecordEdit(row)"
>
修改
</el-button>
<el-popconfirm
confirm-button-text=
"Yes"
cancel-button-text=
"No"
:icon=
"InfoFilled"
icon-color=
"#626AEF"
title=
"确认要删除吗?"
@
confirm=
"deletePolicyCommissionApi(row)"
>
<el-popconfirm
confirm-button-text=
"Yes"
cancel-button-text=
"No"
:icon=
"InfoFilled"
icon-color=
"#626AEF"
title=
"确认要删除吗?"
@
confirm=
"deletePolicyCommissionApi(row)"
>
<template
#
reference
>
<el-button
text
type=
"danger"
size=
"small"
>
删除
</el-button>
</
template
>
</el-popconfirm>
</template>
...
...
@@ -195,53 +312,121 @@
<el-row
:gutter=
"10"
>
<el-col
:xs=
"24"
:sm=
"24"
:md=
"24"
:lg=
"24"
>
<div
class=
"pagination-container"
>
<el-pagination
v-model:current-page=
"checkRecordPageInfo.currentPage"
v-model:page-size=
"checkRecordPageInfo.pageSize"
:page-sizes=
"[50, 100, 200, 300]"
:total=
"checkRecordPageInfo.total"
@
size-change=
"checkRecordPageHandleSizeChange"
@
current-change=
"checkRecordPageHandleCurrentChange"
layout=
"total, sizes, prev, pager, next, jumper"
/>
<el-pagination
v-model:current-page=
"checkRecordPageInfo.currentPage"
v-model:page-size=
"checkRecordPageInfo.pageSize"
:page-sizes=
"[50, 100, 200, 300]"
:total=
"checkRecordPageInfo.total"
@
size-change=
"checkRecordPageHandleSizeChange"
@
current-change=
"checkRecordPageHandleCurrentChange"
layout=
"total, sizes, prev, pager, next, jumper"
/>
</div>
</el-col>
</el-row>
</CommonDialog>
<!-- 新增检核记录弹窗 -->
<CommonDialog
:dialogTitle=
'editStatus.value == "add" ? "新增检核记录" : "修改检核记录"'
dialogWidth=
'80%'
:openDialog=
addCheckRecordDialogFlag
:showAction=
'true'
:showClose=
'true'
@
close=
'closeDialog()'
@
confirm=
'handleAddCheckRecord()'
>
<CommonDialog
:dialogTitle=
"editStatus.value == 'add' ? '新增检核记录' : '修改检核记录'"
dialogWidth=
"80%"
: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"
/>
<SearchForm
ref=
"addCheckRecordFormRef"
:config=
"addCheckRecordConfig"
v-model=
"addReceivablesFormModel"
/>
</el-col>
</el-row>
</CommonDialog>
<CommonDialog
dialogTitle=
'文件导入'
dialogWidth=
'80%'
:openDialog=
fileUploadDialogFlag
:showAction=
'true'
: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"
/>
<CommonDialog
dialogTitle=
"文件导入"
dialogWidth=
"80%"
:openDialog=
"fileUploadDialogFlag"
:showAction=
"true"
: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"
/>
</CommonDialog>
<!-- 设置比对状态 -->
<CommonDialog
dialogTitle=
'设置比对状态'
dialogWidth=
'80%'
:openDialog=
setCompareStatusDialogFlag
:showAction=
'true'
:showClose=
'true'
@
close=
'setCompareStatusDialogFlag = false;'
@
confirm=
'setCompareStatusapi'
>
<SearchForm
ref=
"setCompareStatusFormRef"
:config=
"setCompareStatusConfig"
v-model=
"setCompareStatusFormModel"
/>
<CommonDialog
dialogTitle=
"设置比对状态"
dialogWidth=
"80%"
:openDialog=
"setCompareStatusDialogFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"setCompareStatusDialogFlag = false"
@
confirm=
"setCompareStatusapi"
>
<SearchForm
ref=
"setCompareStatusFormRef"
:config=
"setCompareStatusConfig"
v-model=
"setCompareStatusFormModel"
/>
</CommonDialog>
<!-- 更新数据 -->
<CommonDialog
dialogTitle=
'更新数据'
dialogWidth=
'80%'
:openDialog=
updateDataDialogFlag
:showAction=
'true'
:showClose=
'true'
@
close=
'updateDataDialogFlag = false;'
@
confirm=
'updateDataapi'
>
<SearchForm
ref=
"updateDataFormRef"
:config=
"updateDataConfig"
v-model=
"updateDataFormModel"
/>
<CommonDialog
dialogTitle=
"更新数据"
dialogWidth=
"80%"
:openDialog=
"updateDataDialogFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"updateDataDialogFlag = false"
@
confirm=
"updateDataapi"
>
<SearchForm
ref=
"updateDataFormRef"
:config=
"updateDataConfig"
v-model=
"updateDataFormModel"
/>
</CommonDialog>
<!-- 查看记录 -->
<CommonDialog
dialogTitle=
'查看记录'
dialogWidth=
'80%'
:openDialog=
viewRecordDialogFlag
:showAction=
'true'
:showClose=
'true'
@
close=
'viewRecordDialogFlag = false;'
>
<CommonDialog
dialogTitle=
"查看记录"
dialogWidth=
"80%"
:openDialog=
"viewRecordDialogFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"viewRecordDialogFlag = false"
>
</CommonDialog>
<!-- 更新数据 -->
<CommonDialog
dialogTitle=
"修改检核"
dialogWidth=
"80%"
:openDialog=
"recordCheckDialogFlag"
:showAction=
"true"
:showClose=
"true"
@
close=
"recordCheckDialogFlag = false"
@
confirm=
"confirmRecordCheck"
>
<SearchForm
ref=
"updateDataFormRef"
:config=
"updateDataConfig"
v-model=
"updateDataFormModel"
/>
</CommonDialog>
</div>
</template>
...
...
@@ -255,8 +440,15 @@ import { ElMessage } from 'element-plus'
import
{
formatCurrency
}
from
'@/utils/number'
// 接口
import
{
getPolicyCommissionList
,
generateCommissionRecord
,
addPayrollCheckRecord
,
commissionExpectedRecord
,
updateCompareStatus
,
updateCommissionRecord
,
deletePolicyCommission
,
syncExpectedCommission
,
compareCommissionEntry
getPolicyCommissionList
,
generateCommissionRecord
,
addPayrollCheckRecord
,
commissionExpectedRecord
,
updateCompareStatus
,
updateCommissionRecord
,
deletePolicyCommission
,
syncExpectedCommission
,
compareCommissionEntry
}
from
'@/api/financial/commission'
import
{
InfoFilled
,
Select
,
Upload
,
Plus
}
from
'@element-plus/icons-vue'
...
...
@@ -266,7 +458,9 @@ import { loadDicts, getDictLabel } from '@/utils/useDict'
const
{
proxy
}
=
getCurrentInstance
()
const
{
csf_expected_commission_status
}
=
proxy
.
useDict
(
'csf_expected_commission_status'
)
const
{
csf_commission_status
}
=
proxy
.
useDict
(
'csf_commission_status'
)
const
downloadTemplateUrl
=
'https://yd-ali-oss.oss-cn-shanghai-finance-1-pub.aliyuncs.com/xlsx/2026/01/26/33f0637762144d58a256f5d8d3c2d2b6.xlsx'
const
downloadTemplateUrl
=
'https://yd-ali-oss.oss-cn-shanghai-finance-1-pub.aliyuncs.com/xlsx/2026/01/26/33f0637762144d58a256f5d8d3c2d2b6.xlsx'
const
recordCheckDialogFlag
=
ref
(
false
)
const
downloadTemplate
=
()
=>
{
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
downloadTemplateUrl
// 注意:以 / 开头,指向 public 下的文件
...
...
@@ -275,7 +469,7 @@ const downloadTemplate = () => {
}
const
formatRatio
=
(
row
,
column
,
cellValue
,
index
)
=>
{
if
(
cellValue
==
null
||
cellValue
==
''
&&
cellValue
!==
0
)
{
if
(
cellValue
==
null
||
(
cellValue
==
''
&&
cellValue
!==
0
)
)
{
return
'-'
}
return
cellValue
+
'%'
...
...
@@ -298,11 +492,11 @@ const checkRecordPageInfo = reactive({
pageSize
:
10
,
total
:
0
})
const
checkRecordPageHandleSizeChange
=
(
val
)
=>
{
const
checkRecordPageHandleSizeChange
=
val
=>
{
checkRecordPageInfo
.
pageSize
=
val
checkRecordQuery
()
}
const
checkRecordPageHandleCurrentChange
=
(
val
)
=>
{
const
checkRecordPageHandleCurrentChange
=
val
=>
{
checkRecordPageInfo
.
currentPage
=
val
checkRecordQuery
()
}
...
...
@@ -313,13 +507,15 @@ const searchConfig = ref([
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
},
{
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'比对状态'
,
multiple
:
true
,
dictType
:
'csf_commission_status'
},
{
},
{
type
:
'select'
,
prop
:
'reconciliationCompanyBizIdList'
,
label
:
'对账公司'
,
...
...
@@ -331,22 +527,25 @@ const searchConfig = ref([
multiple
:
true
,
valueKey
:
'reconciliationCompanyBizId'
,
labelKey
:
'name'
,
transform
:
(
res
)
=>
{
transform
:
res
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'date'
,
prop
:
'expectedDate'
,
label
:
'入账日(估)'
,
placeholder
:
'请选择'
},
{
},
{
type
:
'daterange'
,
prop
:
'commissionDate'
,
label
:
'入账日(实)'
,
startPlaceholder
:
'开始时间'
,
endPlaceholder
:
'结束时间'
},
{
},
{
type
:
'select'
,
prop
:
'insuranceCompanyBizIdList'
,
label
:
'保险公司'
,
...
...
@@ -358,15 +557,16 @@ const searchConfig = ref([
multiple
:
true
,
valueKey
:
'insuranceCompanyBizId'
,
labelKey
:
'fullName'
,
transform
:
(
res
)
=>
{
transform
:
res
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'month'
,
prop
:
'reconciliationYearMonth'
,
label
:
'检核年月'
,
placeholder
:
'检核年月'
,
placeholder
:
'检核年月'
}
])
const
selectedRow
=
ref
(
null
)
...
...
@@ -385,7 +585,7 @@ const setCompareStatusFormModel = reactive({
status
:
''
})
// 当比对状态为成功时可以选择
const
selectableFn
=
(
row
)
=>
row
.
commissionStatus
==
'1'
&&
row
.
commissionBizType
==
'R'
const
selectableFn
=
row
=>
row
.
commissionStatus
==
'1'
&&
row
.
commissionBizType
==
'R'
// 设置编辑状态,是新增还是修改
const
editStatus
=
ref
(
'add'
)
// 更新数据
...
...
@@ -393,8 +593,6 @@ const updateDataDialogFlag = ref(false)
// 查看记录
const
viewRecordDialogFlag
=
ref
(
false
)
const
fileUploadDialogFlag
=
ref
(
false
)
const
checkRecordTableData
=
ref
([])
...
...
@@ -415,7 +613,7 @@ const checkConfig = ref([
placeholder
:
'保单号'
}
])
const
checkRecordEdit
=
(
row
)
=>
{
const
checkRecordEdit
=
row
=>
{
console
.
log
(
'查看记录'
,
row
)
selectedRowCheck
.
value
=
{
...
row
}
editStatus
.
value
=
'edit'
...
...
@@ -431,7 +629,7 @@ const checkFormData = ref({
// 监听 checkFormData 变化,自动重新查询
watch
(
()
=>
({
...
checkFormData
.
value
}),
// 深度监听对象内容
(
newVal
)
=>
{
newVal
=>
{
// console.log('搜索条件变化:', newVal)
// ✅ 在这里调用查询接口 或 触发列表刷新
...
...
@@ -441,9 +639,12 @@ watch(
},
{
immediate
:
true
}
// 首次加载也执行(可选)
)
// 确认修改检核
const
confirmRecordCheck
=
()
=>
{
//等待后端接口
}
// 删除检核记录
const
deletePolicyCommissionApi
=
async
(
row
)
=>
{
const
deletePolicyCommissionApi
=
async
row
=>
{
console
.
log
(
row
)
try
{
const
res
=
await
deletePolicyCommission
({
commissionBizId
:
row
.
commissionBizId
})
...
...
@@ -464,9 +665,7 @@ const deletePolicyCommissionApi = async (row) => {
// 生成可出账记录按钮
const
updatePayRollStatusDisable
=
ref
(
true
)
onMounted
(
async
()
=>
{
})
onMounted
(
async
()
=>
{})
// 应收单类型
const
commissionBizTypeOptions
=
[
...
...
@@ -474,7 +673,7 @@ const commissionBizTypeOptions = [
{
value
:
'U'
,
label
:
'非关联保单应收单'
}
]
// 应收单类型通过value转成label
const
getCommissionBizTypeLabel
=
(
value
)
=>
{
const
getCommissionBizTypeLabel
=
value
=>
{
const
item
=
commissionBizTypeOptions
.
find
(
item
=>
item
.
value
===
value
)
return
item
?.
label
||
''
}
...
...
@@ -489,48 +688,43 @@ const addCheckRecordConfig = ref([
label
:
'应收单类型'
,
placeholder
:
'应收单类型'
,
options
:
commissionBizTypeOptions
,
rules
:
[
{
required
:
true
,
message
:
'请选择应收单类型'
,
trigger
:
'blur'
},
]
rules
:
[{
required
:
true
,
message
:
'请选择应收单类型'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
==
'R'
,
rules
:
[
{
required
:
true
,
message
:
'请输入保单号'
,
trigger
:
'blur'
},
]
visible
:
formData
=>
formData
.
commissionBizType
==
'R'
,
rules
:
[{
required
:
true
,
message
:
'请输入保单号'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'commissionPeriod'
,
label
:
'佣金期数'
,
inputType
:
'decimal'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
==
'R'
,
visible
:
formData
=>
formData
.
commissionBizType
==
'R'
,
rules
:
[
{
required
:
true
,
message
:
'请输入佣金期数'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
},
{
type
:
'input'
,
prop
:
'totalPeriod'
,
label
:
'总期数'
,
inputType
:
'decimal'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
==
'R'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
visible
:
formData
=>
formData
.
commissionBizType
==
'R'
,
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'date'
,
prop
:
'commissionDate'
,
label
:
'入账日(实)'
,
placeholder
:
'请选择'
,
maxDate
:
'today'
,
rules
:
[
{
required
:
true
,
message
:
'请选择入账日(实)'
,
trigger
:
'blur'
},
]
},
{
rules
:
[{
required
:
true
,
message
:
'请选择入账日(实)'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'入账金额'
,
...
...
@@ -540,26 +734,25 @@ const addCheckRecordConfig = ref([
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^-
?\d
+
(\.\d
+
)?
$/
,
message
:
'请输入有效的数字'
,
trigger
:
'blur'
}
]
},
{
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'入账币种'
,
dictType
:
'bx_currency_type'
,
rules
:
[
{
required
:
true
,
message
:
'请选择入账币种'
,
trigger
:
'blur'
},
]
},
{
rules
:
[{
required
:
true
,
message
:
'请选择入账币种'
,
trigger
:
'blur'
}]
},
{
type
:
'select'
,
prop
:
'commissionType'
,
label
:
'入账项目'
,
dictType
:
'csf_commission_type'
,
rules
:
[
{
required
:
true
,
message
:
'请选择入账项目'
,
trigger
:
'blur'
},
],
rules
:
[{
required
:
true
,
message
:
'请选择入账项目'
,
trigger
:
'blur'
}],
onChangeExtraFields
:
{
commissionName
:
'itemLabel'
},
},
{
}
},
{
type
:
'select'
,
prop
:
'reconciliationCompanyBizId'
,
label
:
'对账公司'
,
...
...
@@ -569,19 +762,18 @@ const addCheckRecordConfig = ref([
placeholder
:
'输入对账公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
onChangeExtraFields
:
{
reconciliationCompany
:
'name'
,
// 自动同步 raw.name 到 reconciliationCompany
reconciliationCompany
:
'name'
,
// 自动同步 raw.name 到 reconciliationCompany
reconciliationCompanyCode
:
'code'
},
valueKey
:
'reconciliationCompanyBizId'
,
labelKey
:
'name'
,
transform
:
(
res
)
=>
{
transform
:
res
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
},
rules
:
[
{
required
:
true
,
message
:
'请选择对账公司'
,
trigger
:
'blur'
},
]
},
{
rules
:
[{
required
:
true
,
message
:
'请选择对账公司'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'exchangeRate'
,
label
:
'结算汇率(实)'
,
...
...
@@ -591,11 +783,10 @@ const addCheckRecordConfig = ref([
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,4})?
$/
,
message
:
'最多四位小数'
,
trigger
:
'blur'
}
]
}
,
}
])
const
addCheckRecordDialogFlag
=
ref
(
false
)
const
handleAddCheckRecord
=
async
()
=>
{
try
{
// ✅ 统一从子组件获取完整表单数据(含 extra 字段)
await
nextTick
()
// 确保子组件已同步
...
...
@@ -625,14 +816,12 @@ const handleAddCheckRecord = async () => {
ElMessage
.
error
(
'操作失败'
)
}
}
const
clearForm
=
(
type
)
=>
{
const
clearForm
=
type
=>
{
if
(
type
===
'addReceivablesFormModel'
)
if
(
addCheckRecordFormRef
.
value
)
{
addReceivablesFormModel
.
value
=
{}
addCheckRecordFormRef
.
value
.
resetForm
()
}
}
const
closeDialog
=
()
=>
{
...
...
@@ -655,13 +844,12 @@ const generateCommissionRecordapi = async () => {
console
.
error
(
'生成可出账记录失败'
,
error
)
ElMessage
.
error
(
'生成可出账记录失败'
)
}
}
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'设置比对状态'
,
value
:
'setStatus'
,
confirm
:
''
},
{
label
:
'同步到应收款管理'
,
value
:
'syncToReceivable'
,
confirm
:
'确认要同步到应收款管理吗?'
},
// { label: '更新检核数据', value: 'editRecord' },
{
label
:
'修改检核记录'
,
value
:
'editCheckRecord'
}
// { label: '查看记录', value: 'viewRecord' }
]
const
handleMenuConfirm
=
async
(
action
,
row
)
=>
{
...
...
@@ -718,7 +906,7 @@ const checkRecordQuery = async () => {
try
{
const
params
=
{
reconciliationYearMonth
:
checkFormData
.
value
.
reconciliationYearMonth
,
policyNo
:
checkFormData
.
value
.
policyNo
,
policyNo
:
checkFormData
.
value
.
policyNo
,
pageNo
:
checkRecordPageInfo
.
currentPage
,
pageSize
:
checkRecordPageInfo
.
pageSize
}
...
...
@@ -731,11 +919,10 @@ const checkRecordQuery = async () => {
console
.
error
(
'查询检核记录失败'
,
error
)
ElMessage
.
error
(
'查询检核记录失败'
)
}
}
const
multipleSelection
=
ref
([])
const
handleSelectionChange
=
(
val
)
=>
{
const
handleSelectionChange
=
val
=>
{
multipleSelection
.
value
=
val
console
.
log
(
'全选:'
,
val
)
// 生成可出账记录按钮是否禁用
...
...
@@ -794,11 +981,11 @@ const loadTableData = async (searchParams = {}) => {
}
loadTableData
()
// 分页事件
const
handleSizeChange
=
(
val
)
=>
{
const
handleSizeChange
=
val
=>
{
pageSize
.
value
=
val
loadTableData
()
}
const
handleCurrentChange
=
(
val
)
=>
{
const
handleCurrentChange
=
val
=>
{
currentPage
.
value
=
val
loadTableData
()
}
...
...
@@ -818,7 +1005,9 @@ const handleSelect = (e, row) => {
viewRecordDialogFlag
.
value
=
true
return
}
else
if
(
e
===
'syncToReceivable'
)
{
return
}
else
if
(
e
===
'editCheckRecord'
)
{
recordCheckDialogFlag
.
value
=
true
return
}
}
...
...
@@ -877,7 +1066,7 @@ const updateDataapi = async () => {
ElMessage
.
error
(
'更新数据失败'
)
}
}
const
handleUploadEnd
=
(
code
)
=>
{
const
handleUploadEnd
=
code
=>
{
if
(
code
===
200
)
{
ElMessage
.
success
(
'上传文件成功'
)
fileUploadDialogFlag
.
value
=
false
...
...
@@ -897,7 +1086,7 @@ const closthDialog = () => {
}
// 重新比对
const
compareCommissionEntryapi
=
async
(
row
)
=>
{
const
compareCommissionEntryapi
=
async
row
=>
{
try
{
const
res
=
await
compareCommissionEntry
(
row
.
commissionBizId
)
if
(
res
.
code
===
200
)
{
...
...
@@ -922,4 +1111,4 @@ const compareCommissionEntryapi = async (row) => {
.el-col
{
margin-bottom
:
5px
;
}
</
style
>
\ No newline at end of file
</
style
>
src/views/financialCenter/financialSalary.vue
View file @
08e9e2d3
...
...
@@ -42,6 +42,7 @@
:border=
"true"
>
<el-table-column
type=
"selection"
width=
"55"
:reserve-selection=
"true"
/>
<el-table-column
prop=
"businessNo"
label=
"业务编号"
min-width=
"120"
/>
<el-table-column
prop=
"fortuneAccountBizId"
label=
"业务ID"
min-width=
"120"
sortable
/>
<el-table-column
prop=
"broker"
label=
"转介人"
min-width=
"120"
sortable
/>
<el-table-column
prop=
"team"
label=
"所属团队"
min-width=
"120"
sortable
/>
...
...
@@ -62,11 +63,17 @@
</el-tag>
</
template
>
</el-table-column>
<el-table-column
<
!-- <
el-table-column
prop="fortuneAccountDate"
label="出账日"
min-width="150"
show-overflow-tooltip
/> -->
<el-table-column
prop=
"fortuneAccountMonth"
label=
"出账月"
min-width=
"150"
show-overflow-tooltip
/>
<!-- <el-table-column prop="remark" label="备注" min-width="150" show-overflow-tooltip /> -->
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
...
...
@@ -174,8 +181,23 @@
</
template
>
</el-table-column>
<el-table-column
label=
"出账机构"
prop=
"billOrg"
width=
"150"
>
<
template
#
default=
"scope"
>
<
!-- <
template #default="scope">
<el-input v-model="scope.row.billOrg" placeholder="请输入" clearable />
</template> -->
<
template
#
default=
"scope"
>
<el-select
v-model=
"scope.row.billOrg"
style=
"width: 100%"
placeholder=
"请选择"
clearable
>
<el-option
v-for=
"item in csf_bill_org"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</
template
>
</el-table-column>
<el-table-column
label=
"原币种金额"
prop=
"fromAmount"
width=
"150"
>
...
...
@@ -303,9 +325,9 @@
:showAction=
"true"
:showClose=
"true"
@
close=
"showSalarySetting = false"
@
confirm
=
"salaryDataSetting"
@
confirm
=
"salaryDataSetting"
>
<el-date-picker
<el-date-picker
v-model=
"fortuneAccountDate"
type=
"date"
placeholder=
"选择薪资日"
...
...
@@ -341,7 +363,7 @@ import { debounce } from 'lodash-es'
const
amountInput
=
usePositiveDecimal
(
4
)
// 默认2位小数
const
{
proxy
}
=
getCurrentInstance
()
const
{
bx_currency_type
}
=
proxy
.
useDict
(
'bx_currency_type
'
)
const
{
bx_currency_type
,
csf_bill_org
}
=
proxy
.
useDict
(
'bx_currency_type'
,
'csf_bill_org
'
)
const
searchFormRef
=
ref
(
null
)
const
searchParams
=
ref
({})
const
searchConfig
=
ref
([
...
...
@@ -421,7 +443,7 @@ const debounceChangeToAmountMap = new WeakMap()
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'拆分出账'
,
value
:
'splitBilling'
},
{
label
:
'设置出账日'
,
value
:
'settingSalaryDate'
}
,
{
label
:
'设置出账日'
,
value
:
'settingSalaryDate'
}
// { label: '查看记录', value: 'viewRecord' }
]
//=============拆分出账开始================
...
...
@@ -684,30 +706,29 @@ const handleSelect = (e, row) => {
billCurrentPage
.
value
=
1
billTableList
.
value
=
[]
getSplitTableList
()
}
else
if
(
e
===
'settingSalaryDate'
)
{
}
else
if
(
e
===
'settingSalaryDate'
)
{
console
.
log
(
'更新薪资数据'
)
fortuneAccountDate
.
value
=
currentRow
.
value
.
fortuneAccountDate
||
''
showSalarySetting
.
value
=
true
;
fortuneAccountDate
.
value
=
currentRow
.
value
.
fortuneAccountDate
||
''
showSalarySetting
.
value
=
true
}
}
const
salaryDataSetting
=
async
(
e
)
=>
{
try
{
const
params
=
{
fortuneAccountBizId
:
currentRow
.
value
.
fortuneAccountBizId
,
fortuneAccountDate
:
fortuneAccountDate
.
value
};
const
response
=
await
updatePolicyFortuneAccount
(
params
)
if
(
response
.
code
==
200
)
{
showSalarySetting
.
value
=
false
;
ElMessage
.
success
(
'修改成功'
)
getList
()
}
}
catch
(
error
)
{
const
salaryDataSetting
=
async
e
=>
{
try
{
const
params
=
{
fortuneAccountBizId
:
currentRow
.
value
.
fortuneAccountBizId
,
fortuneAccountDate
:
fortuneAccountDate
.
value
}
const
response
=
await
updatePolicyFortuneAccount
(
params
)
if
(
response
.
code
==
200
)
{
showSalarySetting
.
value
=
false
ElMessage
.
success
(
'修改成功'
)
getList
()
}
}
catch
(
error
)
{
console
.
error
(
'获取数据失败:'
,
error
)
ElMessage
.
error
(
'修改失败'
)
}
}
// 分页事件
const
handleSizeChange
=
val
=>
{
...
...
src/views/financialCenter/payables.vue
View file @
08e9e2d3
<
template
>
<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"
>
<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"
/>
...
...
@@ -12,30 +20,64 @@
<!-- 统计信息卡片 -->
<div
class=
"statistics-container"
v-if=
"statisticsData.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"应出账总金额"
:value=
"statisticsData.totalExpectedAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"应出账总金额"
:value=
"statisticsData.totalExpectedAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账金额"
:value=
"statisticsData.totalPaidAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账金额"
:value=
"statisticsData.totalPaidAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"待出账金额"
:value=
"statisticsData.totalUnpaidAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"待出账金额"
:value=
"statisticsData.totalUnpaidAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账比例"
:value=
"statisticsData.paidAmountRatio"
:formatter=
"value=>formatCurrency(value,'',2)+'%'"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账比例"
:value=
"statisticsData.paidAmountRatio"
:formatter=
"value => formatCurrency(value, '', 2) + '%'"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保费"
:value=
"statisticsData.totalPremiumAmount"
:formatter=
"value=>formatCurrency(value)"
/>
<el-statistic
title=
"总保费"
:value=
"statisticsData.totalPremiumAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
</el-row>
</div>
<!-- 应付款管理列表 -->
<el-table
:data=
"tableData"
height=
"400"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
v-for=
"(column, index) in payableReportTableColumns"
:key=
"index"
:prop=
"column.prop"
:label=
"column.label"
:width=
"column.width"
:sortable=
"column.sortable"
:formatter=
"column.formatter"
/>
<el-table
:data=
"tableData"
height=
"400"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
v-for=
"(column, index) in payableReportTableColumns"
:key=
"index"
:prop=
"column.prop"
:label=
"column.label"
:width=
"column.width"
:sortable=
"column.sortable"
:formatter=
"column.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<template
#
default=
"scope"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"viewDetail(scope.row)"
>
...
...
@@ -47,33 +89,66 @@
</template>
</CommonPage>
<!-- 查看明细列表 -->
<CommonDialog
dialogTitle=
"应付明细"
dialogWidth=
"80%"
:openDialog=
"detailDialogVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"detailDialogVisible = false"
@
confirm=
"detailDialogVisible = false"
>
<CommonDialog
dialogTitle=
"应付明细"
dialogWidth=
"80%"
:openDialog=
"detailDialogVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"detailDialogVisible = false"
@
confirm=
"detailDialogVisible = false"
>
<div
class=
"statistics-container"
v-if=
"detailRecordStatistics.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"应出账总金额"
:value=
"detailRecordStatistics.totalExpectedAmount"
:formatter=
"value=>formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账金额"
:value=
"detailRecordStatistics.totalPaidAmount"
:formatter=
"value=>formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"待出账金额"
:value=
"detailRecordStatistics.totalUnpaidAmount"
:formatter=
"value=>formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账比例"
:value=
"detailRecordStatistics.paidAmountRatio"
:formatter=
"value=>formatCurrency(value,'',2)+'%'"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"detailRecordStatistics.totalPolicyCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保费"
:value=
"detailRecordStatistics.totalPremiumAmount"
:formatter=
"value=>formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"应出账总金额"
:value=
"detailRecordStatistics.totalExpectedAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账金额"
:value=
"detailRecordStatistics.totalPaidAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"待出账金额"
:value=
"detailRecordStatistics.totalUnpaidAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"已出账比例"
:value=
"detailRecordStatistics.paidAmountRatio"
:formatter=
"value => formatCurrency(value, '', 2) + '%'"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"detailRecordStatistics.totalPolicyCount"
/>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保费"
:value=
"detailRecordStatistics.totalPremiumAmount"
:formatter=
"value => formatCurrency(value)"
/>
</el-col>
</el-row>
</div>
<el-table
:data=
"payableReportTableData"
border
style=
"width: 100%;margin-bottom: 10px;"
>
<el-table-column
v-for=
"item in payableReportListTableColumns"
:key=
"item.property"
:property=
"item.property"
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
<el-table
:data=
"payableReportTableData"
border
style=
"width: 100%; margin-bottom: 10px"
>
<el-table-column
v-for=
"item in payableReportListTableColumns"
:key=
"item.property"
:property=
"item.property"
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"{ row }"
>
<el-popover
placement=
"right"
:width=
"200"
trigger=
"click"
>
...
...
@@ -91,66 +166,204 @@
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page=
"detailPageInfo.currentPage"
v-model:page-size=
"detailPageInfo.pageSize"
:page-sizes=
"[50, 100, 200, 300]"
size=
"default"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"detailPageInfo.total"
@
size-change=
"handleSizeChangeDetailRecord"
@
current-change=
"handleCurrentChangeDetailRecord"
/>
<el-pagination
v-model:current-page=
"detailPageInfo.currentPage"
v-model:page-size=
"detailPageInfo.pageSize"
:page-sizes=
"[50, 100, 200, 300]"
size=
"default"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"detailPageInfo.total"
@
size-change=
"handleSizeChangeDetailRecord"
@
current-change=
"handleCurrentChangeDetailRecord"
/>
</CommonDialog>
<!-- 出账记录表格弹窗-->
<CommonDialog
dialogTitle=
"出账记录"
dialogWidth=
"80%"
:openDialog=
"payRecordDialogTableVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"payRecordDialogTableVisible = false"
@
confirm=
"payRecordDialogTableVisible = false"
>
<CommonDialog
dialogTitle=
"出账记录"
dialogWidth=
"80%"
:openDialog=
"payRecordDialogTableVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"payRecordDialogTableVisible = false"
@
confirm=
"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"
:formatter=
"item.formatter"
/>
<el-table-column
v-for=
"item in payRecordDialogTableColumns"
:key=
"item.property"
:property=
"item.property"
: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=
"resetAddPayRecordForm"
@
confirm=
"handleConfirmAddPayRecord"
>
<SearchForm
ref=
"addPayRecordFormRef"
:config=
"addPayRecordFormConfig"
v-model=
"addPayRecordFormModel"
/>
<CommonDialog
:dialogTitle=
"editStatus === 'add' ? '新增出账记录' : '修改出账记录'"
dialogWidth=
"80%"
:openDialog=
"addPayRecordDialogVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"resetAddPayRecordForm"
@
confirm=
"handleConfirmAddPayRecord"
>
<SearchForm
ref=
"addPayRecordFormRef"
:config=
"addPayRecordFormConfig"
v-model=
"addPayRecordFormModel"
@
inputChange=
"(prop, value, item) => handleInputChange('addPayRecord', prop, value, item)"
/>
</CommonDialog>
<!-- 设置出账状态 -->
<CommonDialog
dialogTitle=
"设置出账状态"
dialogWidth=
"80%"
:openDialog=
"setPayRecordStatusDialogVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"setPayRecordStatusDialogVisible = false"
@
confirm=
"handleConfirmSetPayRecordStatus"
>
<CommonDialog
dialogTitle=
"设置出账状态"
dialogWidth=
"80%"
:openDialog=
"setPayRecordStatusDialogVisible"
:showAction=
"true"
:showClose=
"true"
@
close=
"setPayRecordStatusDialogVisible = false"
@
confirm=
"handleConfirmSetPayRecordStatus"
>
<SearchForm
ref=
"setPayRecordStatusFormRef"
:config=
"setPayRecordStatusFormConfig"
/>
</CommonDialog>
</div>
</template>
<
script
setup
name=
"Payables"
>
import
CommonPage
from
'@/components/commonPage'
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
import
{
ref
,
reactive
,
nextTick
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
formatCurrency
}
from
'@/utils/number'
import
{
expectedFortuneList
,
payRecordList
,
addPayRecord
,
updatePayRecord
,
exportPayRecord
,
payableReport
}
from
'@/api/financial/commission'
import
{
expectedFortuneList
,
payRecordList
,
addPayRecord
,
updatePayRecord
,
exportPayRecord
,
payableReport
}
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
payableReportTableData
=
ref
([])
const
payableReportTableColumns
=
ref
([
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
row
.
policyNo
||
'-'
},
{
prop
:
'broker'
,
label
:
'转介人(主)'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
row
.
broker
||
'-'
},
{
prop
:
'brokerGradeName'
,
label
:
'职级'
,
sortable
:
true
,
width
:
'80'
,
formatter
:
(
row
)
=>
row
.
brokerGradeName
||
'-'
},
{
prop
:
'fortunePeriod'
,
label
:
'出账期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
fortunePeriod
||
'-'
},
{
prop
:
'fortuneTotalPeriod'
,
label
:
'出账总期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
fortuneTotalPeriod
||
'-'
},
{
prop
:
'payoutDate'
,
label
:
'出账日(估)'
,
sortable
:
true
,
width
:
'130'
,
},
{
prop
:
'paidRatio'
,
label
:
'已出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'unpaidRatio'
,
label
:
'待出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
unpaidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已出账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'unpaidAmount'
,
label
:
'待出账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
unpaidAmount
||
0
)
},
{
prop
:
'hkdAmount'
,
label
:
'应出账金额(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
hkdAmount
||
0
)
},
{
prop
:
'currency'
,
label
:
'出账币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
currency
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
productName
||
'-'
},
{
prop
:
'policyCurrency'
,
label
:
'保单币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
policyCurrency
||
'-'
}
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
row
.
policyNo
||
'-'
},
{
prop
:
'policyHolder'
,
label
:
'投保人'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
policyHolder
||
'-'
},
{
prop
:
'broker'
,
label
:
'转介人(主)'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
row
.
broker
||
'-'
},
{
prop
:
'brokerGradeName'
,
label
:
'职级'
,
sortable
:
true
,
width
:
'80'
,
formatter
:
row
=>
row
.
brokerGradeName
||
'-'
},
{
prop
:
'fortunePeriod'
,
label
:
'出账期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
fortunePeriod
||
'-'
},
{
prop
:
'fortuneTotalPeriod'
,
label
:
'出账总期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
fortuneTotalPeriod
||
'-'
},
{
prop
:
'payoutDate'
,
label
:
'出账日(估)'
,
sortable
:
true
,
width
:
'130'
},
{
prop
:
'paidRatio'
,
label
:
'已出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'unpaidRatio'
,
label
:
'待出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
unpaidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已出账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'unpaidAmount'
,
label
:
'待出账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
unpaidAmount
||
0
)
},
{
prop
:
'hkdAmount'
,
label
:
'应出账金额(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
hkdAmount
||
0
)
},
{
prop
:
'currency'
,
label
:
'出账币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
currency
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
productName
||
'-'
},
{
prop
:
'policyCurrency'
,
label
:
'保单币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
policyCurrency
||
'-'
}
])
const
detailDialogVisible
=
ref
(
false
)
...
...
@@ -158,33 +371,170 @@ const detailDialogVisible = ref(false)
const
payableReportListTableColumns
=
ref
([
// { prop: 'fortuneBizType', label: '应付款类型', sortable: true, width: '120', formatter: (row) => getFortuneBizTypeLabel(row.fortuneBizType) || '-' },
// { prop: 'payableNo', label: '应付账款编号', sortable: true, width: '120', formatter: (row) => row.payableNo || '-' },
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'130'
,
formatter
:
(
row
)
=>
row
.
policyNo
||
'-'
},
{
prop
:
'broker'
,
label
:
'转介人'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
broker
||
'-'
},
{
prop
:
'brokerGradeName'
,
label
:
'职级'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
brokerGradeName
||
'-'
},
{
prop
:
'fortuneName'
,
label
:
'出账项目'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
fortuneName
||
'-'
},
{
prop
:
'status'
,
label
:
'出账状态'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
getDictLabel
(
'csf_expected_fortune_status'
,
row
.
status
)
||
'-'
},
{
prop
:
'currencyName'
,
label
:
'出账币种'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
(
row
)
=>
row
.
currencyName
||
'-'
},
{
prop
:
'fortunePeriod'
,
label
:
'出账期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
(
row
)
=>
row
.
fortunePeriod
||
'-'
},
{
prop
:
'fortuneTotalPeriod'
,
label
:
'出账总期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
(
row
)
=>
row
.
fortuneTotalPeriod
||
'-'
},
{
prop
:
'payoutDate'
,
label
:
'出账日(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
payoutDate
||
'-'
},
{
prop
:
'actualPayoutDate'
,
label
:
'出账日(实)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
actualPayoutDate
||
'-'
},
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'130'
,
formatter
:
row
=>
row
.
policyNo
||
'-'
},
{
prop
:
'broker'
,
label
:
'转介人'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
broker
||
'-'
},
{
prop
:
'brokerGradeName'
,
label
:
'职级'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
brokerGradeName
||
'-'
},
{
prop
:
'fortuneName'
,
label
:
'出账项目'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
fortuneName
||
'-'
},
{
prop
:
'status'
,
label
:
'出账状态'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
getDictLabel
(
'csf_expected_fortune_status'
,
row
.
status
)
||
'-'
},
{
prop
:
'currencyName'
,
label
:
'出账币种'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
row
=>
row
.
currencyName
||
'-'
},
{
prop
:
'fortunePeriod'
,
label
:
'出账期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
row
=>
row
.
fortunePeriod
||
'-'
},
{
prop
:
'fortuneTotalPeriod'
,
label
:
'出账总期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
row
=>
row
.
fortuneTotalPeriod
||
'-'
},
{
prop
:
'payoutDate'
,
label
:
'出账日(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
payoutDate
||
'-'
},
{
prop
:
'actualPayoutDate'
,
label
:
'出账日(实)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
actualPayoutDate
||
'-'
},
// { prop: 'commissionRatio', label: '职级对应积分比例', sortable: true, width: '120', formatter: (row) => (row.commissionRatio || 0) || '-' },
{
prop
:
'hkdAmount'
,
label
:
'应出账金额(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
hkdAmount
||
0
)
},
{
prop
:
'paidRatio'
,
label
:
'已出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已出账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'unpaidRatio'
,
label
:
'待出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
unpaidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'unpaidAmount'
,
label
:
'待出账金额(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
unpaidAmount
||
0
)
},
{
prop
:
'brokerRatio'
,
label
:
'持有比例'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
(
row
)
=>
(
row
.
brokerRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
productName
||
'-'
},
{
prop
:
'statusDesc'
,
label
:
'修改理由'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
statusDesc
||
'-'
},
{
prop
:
'remark'
,
label
:
'备注'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
remark
||
'-'
},
{
prop
:
'hkdAmount'
,
label
:
'应出账金额(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
hkdAmount
||
0
)
},
{
prop
:
'paidRatio'
,
label
:
'已出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已出账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'unpaidRatio'
,
label
:
'待出账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
unpaidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'unpaidAmount'
,
label
:
'待出账金额(估)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
unpaidAmount
||
0
)
},
{
prop
:
'brokerRatio'
,
label
:
'持有比例'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
row
=>
(
row
.
brokerRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
productName
||
'-'
},
{
prop
:
'statusDesc'
,
label
:
'修改理由'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
statusDesc
||
'-'
},
{
prop
:
'creatorName'
,
label
:
'操作人'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
creatorName
||
'-'
},
{
prop
:
'updateTime'
,
label
:
'操作时间'
,
sortable
:
true
,
width
:
'180'
,
formatter
:
row
=>
row
.
updateTime
||
'-'
},
{
prop
:
'remark'
,
label
:
'备注'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
remark
||
'-'
}
])
// 设置出账状态
const
setPayRecordStatusDialogVisible
=
ref
(
false
)
const
selectedRow
=
ref
(
null
)
...
...
@@ -195,15 +545,14 @@ const setPayRecordStatusFormConfig = ref([
prop
:
'status'
,
label
:
'出账状态'
,
dictType
:
'csf_expected_fortune_status'
},
{
},
{
type
:
'textarea'
,
prop
:
'statusDesc'
,
label
:
'修改理由'
,
},
])
const
visibleDefaultButtons
=
ref
([
'add'
,
'export'
,
'reset'
,
'query'
label
:
'修改理由'
}
])
const
visibleDefaultButtons
=
ref
([
'add'
,
'export'
,
'reset'
,
'query'
])
const
userStore
=
useUserStore
()
// 应收单类型
const
fortuneBizTypeOptions
=
[
...
...
@@ -211,7 +560,7 @@ const fortuneBizTypeOptions = [
{
value
:
'U'
,
label
:
'非关联保单应付单'
}
]
// 应付单类型通过value转成label
const
getFortuneBizTypeLabel
=
(
value
)
=>
{
const
getFortuneBizTypeLabel
=
value
=>
{
const
item
=
fortuneBizTypeOptions
.
find
(
item
=>
item
.
value
===
value
)
return
item
?.
label
||
''
}
...
...
@@ -224,6 +573,11 @@ const searchConfig = ref([
label
:
'保单号'
},
{
type
:
'input'
,
prop
:
'policyHolder'
,
label
:
'投保人'
},
{
type
:
'daterange'
,
prop
:
'payoutDate'
,
label
:
'出账日(估)'
,
...
...
@@ -242,9 +596,7 @@ const searchConfig = ref([
prop
:
'fortunePeriod'
,
label
:
'出账期数'
,
inputType
:
'decimal'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'select'
,
...
...
@@ -264,11 +616,12 @@ const searchConfig = ref([
valueKey
:
'insuranceCompanyBizId'
,
labelKey
:
'fullName'
,
multiple
:
true
,
transform
:
(
res
)
=>
{
transform
:
res
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'select'
,
prop
:
'productLaunchBizIdList'
,
label
:
'产品计划'
,
...
...
@@ -276,17 +629,22 @@ const searchConfig = ref([
keywordField
:
'productName'
,
requestParams
:
{
tenantBizId
:
userStore
.
projectInfo
.
tenantBizId
||
''
,
projectBizId
:
userStore
.
projectInfo
.
projectBizId
||
''
,
fieldBizId
:
'field_olk1qZe81qHHKXbw'
,
fieldValueBizId
:
'field_value_uOfJH5ucA2YwJpbn'
,
pageNo
:
1
,
pageSize
:
20
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
)
=>
{
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'select'
,
prop
:
'fortuneBizType'
,
label
:
'应付单类型'
,
...
...
@@ -294,7 +652,8 @@ const searchConfig = ref([
{
value
:
'R'
,
label
:
'关联保单应付单'
},
{
value
:
'U'
,
label
:
'非关联保单应付单'
}
]
},
{
},
{
type
:
'select'
,
prop
:
'teamBizIdList'
,
label
:
'出单团队'
,
...
...
@@ -306,17 +665,16 @@ const searchConfig = ref([
multiple
:
true
,
valueKey
:
'teamBizId'
,
labelKey
:
'teamName'
,
transform
:
(
res
)
=>
{
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
}
,
}
])
const
payRecordDialogTableVisible
=
ref
(
false
)
// 新增出账记录
const
addPayRecordFormModel
=
ref
({
fortuneBizType
:
'U'
,
fortuneBizType
:
'U'
})
const
addPayRecordDialogVisible
=
ref
(
false
)
const
addPayRecordFormRef
=
ref
()
...
...
@@ -329,58 +687,61 @@ const addPayRecordFormConfig = [
{
value
:
'R'
,
label
:
'关联保单应付单'
},
{
value
:
'U'
,
label
:
'非关联保单应付单'
}
]
},
{
},
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'关联保单号'
,
visible
:
(
formData
)
=>
formData
.
fortuneBizType
===
'R'
,
},
{
visible
:
formData
=>
formData
.
fortuneBizType
===
'R'
},
{
type
:
'input'
,
prop
:
'fortunePeriod'
,
label
:
'佣金期数'
,
inputType
:
'decimal'
,
visible
:
(
formData
)
=>
formData
.
fortuneBizType
===
'R'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
visible
:
formData
=>
formData
.
fortuneBizType
===
'R'
,
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'fortuneTotalPeriod'
,
label
:
'总期数'
,
inputType
:
'decimal'
,
visible
:
(
formData
)
=>
formData
.
fortuneBizType
===
'R'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
visible
:
formData
=>
formData
.
fortuneBizType
===
'R'
,
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'date'
,
prop
:
'payoutDate'
,
label
:
'出账日(估)'
,
placeholder
:
'请选择'
},
{
},
{
type
:
'date'
,
prop
:
'actualPayoutDate'
,
label
:
'出账日(实)'
,
placeholder
:
'请选择'
,
maxDate
:
'today'
},
{
},
{
type
:
'input'
,
prop
:
'hkdAmount'
,
label
:
'出账金额'
,
rules
:
[
{
pattern
:
/^-
?\d
+
(\.\d{1,2})?
$/
,
message
:
'小数(最多两位)'
,
trigger
:
'blur'
}
]
},
{
rules
:
[{
pattern
:
/^-
?\d
+
(\.\d{1,2})?
$/
,
message
:
'小数(最多两位)'
,
trigger
:
'blur'
}]
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'出账币种'
,
dictType
:
'bx_currency_type'
},
{
},
{
type
:
'select'
,
prop
:
'fortuneType'
,
label
:
'出账项目'
,
dictType
:
'csf_fortune_type'
},
{
},
{
type
:
'select'
,
prop
:
'brokerBizId'
,
label
:
'转介人'
,
...
...
@@ -392,19 +753,52 @@ const addPayRecordFormConfig = [
valueKey
:
'clientUserBizId'
,
labelKey
:
'realName'
,
onChangeExtraFields
:
{
broker
:
'realName'
,
// 自动同步 raw.name 到 reconciliationCompany
broker
:
'realName'
,
// 自动同步 raw.name 到 reconciliationCompany
reconciliationCompanyCode
:
'code'
},
transform
:
(
res
)
=>
{
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'select'
,
prop
:
'status'
,
label
:
'出账状态'
,
dictType
:
'csf_expected_fortune_status'
},
{
type
:
'input'
,
prop
:
'exchangeRate'
,
label
:
'结算汇率'
,
inputType
:
'decimal'
,
rules
:
[{
required
:
true
,
message
:
'只能输入正整数和小数'
,
trigger
:
'blur'
}]
// defaultValue: 1
},
{
type
:
'input'
,
prop
:
'remark'
,
label
:
'备注'
}
]
const
handleInputChange
=
async
(
formType
,
prop
,
value
,
item
)
=>
{
if
(
formType
==
'addPayRecord'
)
{
await
nextTick
()
let
policyNo
=
addPayRecordFormModel
.
value
.
policyNo
let
fortunePeriod
=
addPayRecordFormModel
.
value
.
fortunePeriod
if
((
prop
==
'policyNo'
||
prop
==
'fortunePeriod'
)
&&
fortunePeriod
&&
policyNo
)
{
//等待后端接口
const
res
=
await
commissionExchangeRateApi
({
policyNo
:
policyNo
,
commissionPeriod
:
fortunePeriod
})
if
(
res
.
code
==
200
)
{
addPayRecordFormModel
.
value
.
exchangeRate
=
res
.
data
}
else
{
ElMessage
.
error
(
'查询结算汇率失败'
)
}
}
}
}
const
handleConfirmAddPayRecord
=
async
()
=>
{
if
(
editStatus
.
value
===
'add'
)
{
const
handleConfirmAddPayRecordparams
=
addPayRecordFormRef
.
value
.
getFormData
()
...
...
@@ -427,14 +821,13 @@ const handleConfirmAddPayRecord = async () => {
ElMessage
.
success
(
'更新出账记录成功'
)
addPayRecordDialogVisible
.
value
=
false
addPayRecordFormRef
.
value
.
resetForm
()
editStatus
.
value
=
'add'
;
editStatus
.
value
=
'add'
loadPayRecordTableData
(
selectedRow
.
value
.
expectedFortuneBizId
)
expectedFortuneListData
()
}
catch
(
error
)
{
ElMessage
.
error
(
error
.
message
)
}
}
}
// 弹窗表单重置
const
resetAddPayRecordForm
=
()
=>
{
...
...
@@ -443,7 +836,6 @@ const resetAddPayRecordForm = () => {
addPayRecordDialogVisible
.
value
=
false
}
const
editStatus
=
ref
(
'add'
)
// 出账记录
const
payRecordDialogTableData
=
ref
([])
...
...
@@ -452,14 +844,29 @@ const handleSelect = async (e, row) => {
selectedRow
.
value
=
{
...
row
}
if
(
e
===
'payRecord'
)
{
payRecordDialogTableVisible
.
value
=
true
loadPayRecordTableData
(
selectedRow
.
value
.
expectedFortuneBizId
)
;
loadPayRecordTableData
(
selectedRow
.
value
.
expectedFortuneBizId
)
payRecordDialogTableColumns
.
value
=
[
{
property
:
'broker'
,
label
:
'转介人'
,
width
:
'100'
,
},
{
property
:
'broker'
,
label
:
'转介人'
,
width
:
'100'
},
{
property
:
'fortuneName'
,
label
:
'出账项目'
,
width
:
'150'
},
{
property
:
'currentPaymentHkdAmount'
,
label
:
'出账金额'
,
width
:
'150'
,
formatter
:(
row
)
=>
formatCurrency
(
row
.
currentPaymentHkdAmount
||
0
)},
{
property
:
'currentPaymentHkdAmount'
,
label
:
'出账金额'
,
width
:
'150'
,
formatter
:
row
=>
formatCurrency
(
row
.
currentPaymentHkdAmount
||
0
)
},
{
property
:
'currency'
,
label
:
'出账币种'
,
width
:
'150'
},
{
property
:
'currentPaymentRatio'
,
label
:
'出账比例'
,
width
:
'150'
,
formatter
:
(
row
)
=>
`
${
row
.
currentPaymentRatio
}
%`
},
{
property
:
'fortuneUnpaidRatio'
,
label
:
'待出账比例'
,
width
:
'150'
,
formatter
:
(
row
)
=>
`
${
row
.
fortuneUnpaidRatio
}
%`
},
{
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
:
'reconciliationOperator'
,
label
:
'操作人'
,
width
:
'150'
},
...
...
@@ -474,29 +881,28 @@ const handleSelect = async (e, row) => {
label
:
'出账状态'
,
dictType
:
'csf_expected_fortune_status'
,
defaultValue
:
selectedRow
.
value
.
status
||
''
},
{
},
{
type
:
'textarea'
,
prop
:
'statusDesc'
,
label
:
'修改理由'
,
defaultValue
:
selectedRow
.
value
.
statusDesc
||
''
}
,
}
]
}
else
if
(
e
===
'updateData'
)
{
editStatus
.
value
=
'edit'
addPayRecordDialogVisible
.
value
=
true
// 2. 使用 nextTick 等待 DOM 更新
nextTick
(()
=>
{
// 3. 此时 addRecordRef.value 一定存在了
if
(
addPayRecordFormRef
.
value
&&
selectedRow
.
value
)
{
addPayRecordFormModel
.
value
=
{
...
selectedRow
.
value
};
}
});
// 2. 使用 nextTick 等待 DOM 更新
nextTick
(()
=>
{
// 3. 此时 addRecordRef.value 一定存在了
if
(
addPayRecordFormRef
.
value
&&
selectedRow
.
value
)
{
addPayRecordFormModel
.
value
=
{
...
selectedRow
.
value
}
}
})
console
.
log
(
addPayRecordFormModel
.
value
)
}
}
// 分页相关
const
currentPage
=
ref
(
1
)
const
pageSize
=
ref
(
10
)
...
...
@@ -531,11 +937,7 @@ const handleExport = async () => {
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'
)
await
safeDownload
(
response
,
fileName
,
'application/vnd.ms-excel;charset=utf-8'
)
}
const
handleReset
=
()
=>
{
...
...
@@ -581,12 +983,12 @@ const operationBtnList = ref([
])
// 分页事件
const
handleSizeChange
=
(
val
)
=>
{
const
handleSizeChange
=
val
=>
{
pageSize
.
value
=
val
loadTableData
()
}
const
handleCurrentChange
=
(
val
)
=>
{
const
handleCurrentChange
=
val
=>
{
currentPage
.
value
=
val
loadTableData
()
}
...
...
@@ -618,7 +1020,6 @@ const loadTableData = async () => {
totalPolicyCount
:
response
.
data
.
statisticsVO
.
totalPolicyCount
,
totalPremiumAmount
:
response
.
data
.
statisticsVO
.
totalPremiumAmount
}
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
// ElMessage.error('加载数据失败')
...
...
@@ -628,7 +1029,7 @@ const loadTableData = async () => {
}
// 出账记录查询
const
loadPayRecordTableData
=
async
(
expectedFortuneBizId
)
=>
{
const
loadPayRecordTableData
=
async
expectedFortuneBizId
=>
{
loading
.
value
=
true
try
{
const
params
=
{
...
...
@@ -636,7 +1037,6 @@ const loadPayRecordTableData = async (expectedFortuneBizId) => {
}
const
response
=
await
payRecordList
(
params
)
payRecordDialogTableData
.
value
=
response
.
data
.
records
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
// ElMessage.error('加载数据失败')
...
...
@@ -726,23 +1126,22 @@ const expectedFortuneListData = async () => {
}
}
const
viewDetail
=
(
row
)
=>
{
const
viewDetail
=
row
=>
{
selectedDetailRecordRow
.
value
=
row
detailDialogVisible
.
value
=
true
expectedFortuneListData
()
}
// 分页事件
const
handleSizeChangeDetailRecord
=
(
val
)
=>
{
const
handleSizeChangeDetailRecord
=
val
=>
{
detailPageInfo
.
value
.
pageSize
=
val
expectedFortuneListData
()
}
// 分页事件
const
handleCurrentChangeDetailRecord
=
(
val
)
=>
{
const
handleCurrentChangeDetailRecord
=
val
=>
{
detailPageInfo
.
value
.
currentPage
=
val
expectedFortuneListData
()
}
</
script
>
<
style
scoped
lang=
"scss"
>
...
...
@@ -759,5 +1158,4 @@ const handleCurrentChangeDetailRecord = (val) => {
border-top
:
1px
solid
#ebeef5
;
text-align
:
right
;
}
</
style
>
\ No newline at end of file
</
style
>
src/views/financialCenter/payroll.vue
View file @
08e9e2d3
...
...
@@ -18,7 +18,7 @@
</
template
>
</CommonPage>
</div>
</template>
...
...
@@ -62,7 +62,8 @@ const searchConfig = ref([
])
const
tableColumns
=
ref
([
{
prop
:
'salarySplitNo'
,
label
:
'发放编号'
,
sortable
:
true
,
width
:
'150'
,
fixed
:
'left'
},
{
prop
:
'salarySplitNo'
,
label
:
'发放编号'
,
sortable
:
true
,
width
:
'150'
,
fixed
:
'left'
},
{
prop
:
'businessNo'
,
label
:
'业务编号'
,
width
:
'150'
,
fixed
:
'left'
},
{
prop
:
'brokerName'
,
label
:
'转介人'
,
sortable
:
true
,
width
:
'150'
,
fixed
:
'left'
},
{
prop
:
'internalNumber'
,
label
:
'内部编号'
,
sortable
:
true
,
width
:
'150'
},
{
prop
:
'team'
,
label
:
'所属团队'
,
sortable
:
true
,
width
:
'150'
},
...
...
@@ -151,7 +152,7 @@ const handleExport = async () => {
startMonth
:
params
.
payoutMonth
?
params
.
payoutMonth
[
0
]
:
''
,
endMonth
:
params
.
payoutMonth
?
params
.
payoutMonth
[
1
]
:
''
,
payoutMonth
:
undefined
,
}
const
response
=
await
exportPayRoll
(
params
)
if
(
response
.
data
&&
response
.
data
.
url
){
...
...
@@ -185,4 +186,4 @@ const operationBtnList = ref([
</
script
>
<
style
scoped
></
style
>
\ No newline at end of file
<
style
scoped
></
style
>
src/views/financialCenter/receivables.vue
View file @
08e9e2d3
<
template
>
<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
>
<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
>
<div
class=
"statistics-container"
v-if=
"statisticsData.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.totalAmount"
:formatter=
"value=>formatCurrency(value)"
>
<template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
应收款总金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.totalPaidAmount"
:formatter=
"value=>formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.pendingPaidAmount"
:formatter=
"value=>formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
待入账金额(估)
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.paidAmountRatio"
:formatter=
"value=>formatCurrency(value,'',2)+'%'"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账比例
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
</el-col>
</el-row>
</div>
<!-- 应收款管理列表 -->
<el-table
:data=
"tableData"
height=
"400"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
v-for=
"(column, index) in receivableReportTableColumns"
:key=
"index"
:fixed=
"column.fixed"
:prop=
"column.prop"
:label=
"column.label"
:width=
"column.width"
:sortable=
"column.sortable"
:formatter=
"column.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"viewDetail(scope.row)"
>
查看明细
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 列表区域 -->
<
template
#
table
>
<div
class=
"statistics-container"
v-if=
"statisticsData.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.totalAmount"
:formatter=
"value => formatCurrency(value)"
>
<template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
应收款总金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.totalPaidAmount"
:formatter=
"value => formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.pendingPaidAmount"
:formatter=
"value => formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
待入账金额(估)
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"statisticsData.paidAmountRatio"
:formatter=
"value => formatCurrency(value, '', 2) + '%'"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账比例
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
title=
"总保单数"
:value=
"statisticsData.totalPolicyCount"
/>
</el-col>
</el-row>
</div>
<!-- 应收款管理列表 -->
<el-table
:data=
"tableData"
height=
"400"
border
highlight-current-row
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
v-for=
"(column, index) in receivableReportTableColumns"
:key=
"index"
:fixed=
"column.fixed"
:prop=
"column.prop"
:label=
"column.label"
:width=
"column.width"
:sortable=
"column.sortable"
:formatter=
"column.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"viewDetail(scope.row)"
>
查看明细
</el-button>
</
template
>
</CommonPage>
<CommonDialog
dialogTitle=
"应收明细"
dialogWidth=
"80%"
:openDialog=
"detailDialogVisible"
:showAction=
"false"
:showClose=
"true"
@
close=
"detailDialogVisible = false"
>
<div
class=
"statistics-container"
v-if=
"detailRecordStatistics.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalAmount"
:formatter=
"value=>formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
应入账总金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalPaidAmount"
:formatter=
"value=>formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalUnpaidAmount"
:formatter=
"value=>formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
待入账金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.paidAmountRatio"
:formatter=
"value=>formatCurrency(value,'',2)+'%'"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账比例
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalPolicyCount"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
总保单数
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalPremium"
:formatter=
"value=>formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
总保费
</div>
</
template
>
</el-statistic>
</el-col>
</el-row>
</div>
<el-table
:data=
"receivableReportTableData"
border
style=
"width: 100%;margin-bottom: 10px;min-height: 300px;"
>
<el-table-column
v-for=
"item in receivableReportItemTableColumns"
:key=
"item.property"
:prop=
"item.prop"
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"{ row }"
>
<el-popover
placement=
"right"
:width=
"200"
trigger=
"click"
>
<template
#
reference
>
<el-icon>
<MoreFilled
/>
</el-icon>
</
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"
>
{{ item.label }}
</el-menu-item>
</el-menu>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page=
"detailPageInfo.currentPage"
v-model:page-size=
"detailPageInfo.pageSize"
:page-sizes=
"[50, 100, 200, 300]"
size=
"default"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"detailPageInfo.total"
@
size-change=
"handleSizeChangeDetailRecord"
@
current-change=
"handleCurrentChangeDetailRecord"
/>
</CommonDialog>
<CommonDialog
dialogTitle=
"入账记录"
dialogWidth=
"80%"
:openDialog=
"entryRecordDialogTableVisible"
:showAction=
"false"
:showClose=
"true"
@
close=
"entryRecordDialogTableVisible = false"
>
<el-table
:data=
"entryRecordDialogTableData"
border
style=
"width: 100%"
>
<el-table-column
v-for=
"item in entryRecordDialogTableColumns"
:key=
"item.property"
:prop=
"item.property"
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"handleClick(scope.row)"
>
查看比对记录
</el-button>
</
template
>
</el-table-column>
</el-table>
</CommonDialog>
<CommonDialog
dialogTitle=
"操作记录"
dialogWidth=
"80%"
:openDialog=
"actionRecordsDialogVisible"
:showAction=
"false"
:showClose=
"true"
@
close=
"actionRecordsDialogVisible = false"
>
<el-table
:data=
"actionRecordsDialogTableData"
border
style=
"width: 100%"
>
<el-table-column
v-for=
"item in actionRecordsDialogTableColumns"
:key=
"item.property"
:prop=
"item.property"
:label=
"item.label"
:width=
"item.width"
/>
</el-table>
</CommonDialog>
<CommonDialog
dialogTitle=
"设置入账状态"
dialogWidth=
"80%"
:openDialog=
"setStatusDialogTableVisible"
@
close=
"setStatusDialogTableVisible = false"
@
confirm=
"handleConfirmSetStatus"
>
<SearchForm
ref=
"setCommissionRecordStatusFormRef"
:config=
"setCommissionRecordStatusFormConfig"
/>
</CommonDialog>
<!-- 新增应收款管理 -->
<CommonDialog
:dialogTitle=
"editStatus === 'add' ? '新增应收款' : '更新应收款'"
dialogWidth=
"80%"
:openDialog=
"addReceivablesDialogVisible"
@
close=
"addReceivablesDialogVisible = false; resetAddReceivablesForm()"
@
confirm=
"handleConfirmAddReceivables"
>
<SearchForm
ref=
"addRecordRef"
:config=
"addReceivablesFormConfig"
v-model=
"addReceivablesFormModel"
/>
</CommonDialog>
</div>
</el-table-column>
</el-table>
</template>
</CommonPage>
<CommonDialog
dialogTitle=
"应收明细"
dialogWidth=
"80%"
:openDialog=
"detailDialogVisible"
:showAction=
"false"
:showClose=
"true"
@
close=
"detailDialogVisible = false"
>
<div
class=
"statistics-container"
v-if=
"detailRecordStatistics.totalPolicyCount > 0"
>
<el-row
:gutter=
"20"
>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalAmount"
:formatter=
"value => formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
应入账总金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalPaidAmount"
:formatter=
"value => formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalUnpaidAmount"
:formatter=
"value => formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
待入账金额
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.paidAmountRatio"
:formatter=
"value => formatCurrency(value, '', 2) + '%'"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
已入账比例
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalPolicyCount"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
总保单数
</div>
</
template
>
</el-statistic>
</el-col>
<el-col
:xs=
"24"
:sm=
"12"
:md=
"4"
class=
"text-center mb-4"
>
<el-statistic
:value=
"detailRecordStatistics.totalPremium"
:formatter=
"value => formatCurrency(value)"
>
<
template
#
title
>
<div
style=
"display: inline-flex; align-items: center"
>
总保费
</div>
</
template
>
</el-statistic>
</el-col>
</el-row>
</div>
<el-table
:data=
"receivableReportTableData"
border
style=
"width: 100%; margin-bottom: 10px; min-height: 300px"
>
<el-table-column
v-for=
"item in receivableReportItemTableColumns"
:key=
"item.property"
:prop=
"item.prop"
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"{ row }"
>
<el-popover
placement=
"right"
:width=
"200"
trigger=
"click"
>
<template
#
reference
>
<el-icon>
<MoreFilled
/>
</el-icon>
</
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"
>
{{ item.label }}
</el-menu-item>
</el-menu>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page=
"detailPageInfo.currentPage"
v-model:page-size=
"detailPageInfo.pageSize"
:page-sizes=
"[50, 100, 200, 300]"
size=
"default"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"detailPageInfo.total"
@
size-change=
"handleSizeChangeDetailRecord"
@
current-change=
"handleCurrentChangeDetailRecord"
/>
</CommonDialog>
<CommonDialog
dialogTitle=
"入账记录"
dialogWidth=
"80%"
:openDialog=
"entryRecordDialogTableVisible"
:showAction=
"false"
:showClose=
"true"
@
close=
"entryRecordDialogTableVisible = false"
>
<el-table
:data=
"entryRecordDialogTableData"
border
style=
"width: 100%"
>
<el-table-column
v-for=
"item in entryRecordDialogTableColumns"
:key=
"item.property"
:prop=
"item.property"
:label=
"item.label"
:width=
"item.width"
:formatter=
"item.formatter"
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"120"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"handleClick(scope.row)"
>
查看比对记录
</el-button>
</
template
>
</el-table-column>
</el-table>
</CommonDialog>
<CommonDialog
dialogTitle=
"操作记录"
dialogWidth=
"80%"
:openDialog=
"actionRecordsDialogVisible"
:showAction=
"false"
:showClose=
"true"
@
close=
"actionRecordsDialogVisible = false"
>
<el-table
:data=
"actionRecordsDialogTableData"
border
style=
"width: 100%"
>
<el-table-column
v-for=
"item in actionRecordsDialogTableColumns"
:key=
"item.property"
:prop=
"item.property"
:label=
"item.label"
:width=
"item.width"
/>
</el-table>
</CommonDialog>
<CommonDialog
dialogTitle=
"设置入账状态"
dialogWidth=
"80%"
:openDialog=
"setStatusDialogTableVisible"
@
close=
"setStatusDialogTableVisible = false"
@
confirm=
"handleConfirmSetStatus"
>
<SearchForm
ref=
"setCommissionRecordStatusFormRef"
:config=
"setCommissionRecordStatusFormConfig"
/>
</CommonDialog>
<!-- 新增应收款管理 -->
<CommonDialog
:dialogTitle=
"editStatus === 'add' ? '新增应收款' : '更新应收款'"
dialogWidth=
"80%"
:openDialog=
"addReceivablesDialogVisible"
@
close=
"((addReceivablesDialogVisible = false), resetAddReceivablesForm())"
@
confirm=
"handleConfirmAddReceivables"
>
<SearchForm
ref=
"addRecordRef"
:config=
"addReceivablesFormConfig"
v-model=
"addReceivablesFormModel"
@
inputChange=
"(prop, value, item) => handleInputChange('addReceivables', prop, value, item)"
/>
</CommonDialog>
</div>
</template>
<
script
setup
name=
"Receivables"
>
import
{
validateEnglish2
}
from
'@/utils/validate'
import
CommonPage
from
'@/components/commonPage'
import
CommonDialog
from
'@/components/commonDialog'
import
{
ref
,
reactive
,
onMounted
,
computed
,
nextTick
}
from
'vue'
import
{
ref
,
reactive
,
onMounted
,
computed
,
nextTick
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
MoreFilled
}
from
'@element-plus/icons-vue'
import
{
receivedFortuneList
,
updateCommissionExpected
,
commissionEntryEditRecords
,
exportReceivedFortune
,
commissionExpectedRecord
,
addReceivedFortune
,
receivableReport
,
CommissionExpectedChangeStatus
receivedFortuneList
,
updateCommissionExpected
,
commissionEntryEditRecords
,
exportReceivedFortune
,
commissionExpectedRecord
,
addReceivedFortune
,
receivableReport
,
CommissionExpectedChangeStatus
,
commissionExchangeRateApi
}
from
'@/api/financial/commission'
import
{
numberWithCommas
}
from
'@/utils/index'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
...
...
@@ -213,277 +310,304 @@ import { formatCurrency } from '@/utils/number'
const
userStore
=
useUserStore
()
// 应收单类型
const
commissionBizTypeOptions
=
[
{
value
:
'R'
,
label
:
'关联保单应收单'
},
{
value
:
'U'
,
label
:
'非关联保单应收单'
}
{
value
:
'R'
,
label
:
'关联保单应收单'
},
{
value
:
'U'
,
label
:
'非关联保单应收单'
}
]
const
editStatus
=
ref
(
'add'
)
// 新增应收款管理
const
addReceivablesFormModel
=
ref
({
commissionBizType
:
'U'
,
commissionBizType
:
'U'
})
const
addReceivablesDialogVisible
=
ref
(
false
)
const
addRecordRef
=
ref
(
null
)
const
addReceivablesFormConfig
=
[
{
type
:
'select'
,
prop
:
'commissionBizType'
,
label
:
'应收单类型'
,
placeholder
:
'应收单类型'
,
options
:
commissionBizTypeOptions
},
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
==
'R'
},
{
type
:
'input'
,
prop
:
'commissionPeriod'
,
label
:
'佣金期数'
,
inputType
:
'decimal'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
===
'R'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
type
:
'input'
,
prop
:
'totalPeriod'
,
label
:
'总期数'
,
inputType
:
'decimal'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
===
'R'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
type
:
'date'
,
prop
:
'commissionDate'
,
label
:
'入账日(估)'
,
placeholder
:
'请选择'
},
// {
// type: 'date',
// prop: 'actualCommissionDate',
// label: '入账日(实)',
// placeholder: '请选择',
// maxDate: 'today'
// },
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'入账金额'
,
inputType
:
'decimal'
,
decimalDigits
:
4
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
===
'U'
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,4})?
$/
,
message
:
'最多四位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'input'
,
prop
:
'commissionRatio'
,
label
:
'入账比例(%)'
,
visible
:
(
formData
)
=>
formData
.
commissionBizType
===
'R'
,
rules
:
[
{
required
:
true
,
message
:
'请输入入账比例'
,
trigger
:
'blur'
},
{
pattern
:
/^-
?\d
+
(\.\d{1,4})?
$/
,
message
:
'最多四位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'入账币种'
,
dictType
:
'bx_currency_type'
},
{
type
:
'select'
,
prop
:
'commissionType'
,
label
:
'入账项目'
,
dictType
:
'csf_commission_type'
,
onChangeExtraFields
:
{
commissionName
:
'itemLabel'
,
},
},
{
type
:
'select'
,
prop
:
'reconciliationCompanyBizId'
,
label
:
'对账公司'
,
api
:
'/insurance/base/api/insuranceReconciliationCompany/page'
,
keywordField
:
'name'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入对账公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
valueKey
:
'reconciliationCompanyBizId'
,
labelKey
:
'name'
,
onChangeExtraFields
:
{
reconciliationCompany
:
'name'
,
// 自动同步 raw.name 到 reconciliationCompany
reconciliationCompanyCode
:
'code'
},
transform
:
(
res
)
=>
{
console
.
log
(
'对账公司'
,
res
)
return
res
.
data
.
records
||
[]
}
{
type
:
'select'
,
prop
:
'commissionBizType'
,
label
:
'应收单类型'
,
placeholder
:
'应收单类型'
,
options
:
commissionBizTypeOptions
},
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
,
visible
:
formData
=>
formData
.
commissionBizType
==
'R'
},
{
type
:
'input'
,
prop
:
'commissionPeriod'
,
label
:
'佣金期数'
,
inputType
:
'decimal'
,
visible
:
formData
=>
formData
.
commissionBizType
===
'R'
,
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'totalPeriod'
,
label
:
'总期数'
,
inputType
:
'decimal'
,
visible
:
formData
=>
formData
.
commissionBizType
===
'R'
,
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'date'
,
prop
:
'commissionDate'
,
label
:
'入账日(估)'
,
placeholder
:
'请选择'
},
// {
// type: 'date',
// prop: 'actualCommissionDate',
// label: '入账日(实)',
// placeholder: '请选择',
// maxDate: 'today'
// },
{
type
:
'input'
,
prop
:
'amount'
,
label
:
'入账金额'
,
inputType
:
'decimal'
,
decimalDigits
:
4
,
visible
:
formData
=>
formData
.
commissionBizType
===
'U'
,
rules
:
[
{
required
:
true
,
message
:
'请输入金额'
,
trigger
:
'blur'
},
{
pattern
:
/^
\d
+
(\.\d{1,4})?
$/
,
message
:
'最多四位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'input'
,
prop
:
'commissionRatio'
,
label
:
'入账比例(%)'
,
visible
:
formData
=>
formData
.
commissionBizType
===
'R'
,
rules
:
[
{
required
:
true
,
message
:
'请输入入账比例'
,
trigger
:
'blur'
},
{
pattern
:
/^-
?\d
+
(\.\d{1,4})?
$/
,
message
:
'最多四位小数'
,
trigger
:
'blur'
}
]
},
{
type
:
'select'
,
prop
:
'currency'
,
label
:
'入账币种'
,
dictType
:
'bx_currency_type'
},
{
type
:
'select'
,
prop
:
'commissionType'
,
label
:
'入账项目'
,
dictType
:
'csf_commission_type'
,
onChangeExtraFields
:
{
commissionName
:
'itemLabel'
}
},
{
type
:
'select'
,
prop
:
'reconciliationCompanyBizId'
,
label
:
'对账公司'
,
api
:
'/insurance/base/api/insuranceReconciliationCompany/page'
,
keywordField
:
'name'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入对账公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
valueKey
:
'reconciliationCompanyBizId'
,
labelKey
:
'name'
,
onChangeExtraFields
:
{
reconciliationCompany
:
'name'
,
// 自动同步 raw.name 到 reconciliationCompany
reconciliationCompanyCode
:
'code'
},
{
type
:
'input'
,
prop
:
'remark'
,
label
:
'备注'
,
transform
:
res
=>
{
console
.
log
(
'对账公司'
,
res
)
return
res
.
data
.
records
||
[]
}
},
{
type
:
'input'
,
prop
:
'exchangeRate'
,
label
:
'结算汇率'
,
inputType
:
'decimal'
,
rules
:
[{
required
:
true
,
message
:
'只能输入正整数和小数'
,
trigger
:
'blur'
}]
// defaultValue: 1
},
{
type
:
'input'
,
prop
:
'remark'
,
label
:
'备注'
}
]
// 弹窗表单重置
const
resetAddReceivablesForm
=
()
=>
{
addRecordRef
.
value
.
resetForm
()
editStatus
.
value
=
'add'
addRecordRef
.
value
.
resetForm
()
editStatus
.
value
=
'add'
}
const
handleConfirmAddReceivables
=
async
()
=>
{
if
(
editStatus
.
value
===
'add'
)
{
const
p
=
addRecordRef
.
value
.
getFormData
()
try
{
await
addReceivedFortune
({
commissionExpectedAddDtoList
:
[
p
]
})
ElMessage
.
success
(
'新增应收款成功'
)
addReceivablesDialogVisible
.
value
=
false
resetAddReceivablesForm
()
handleQuery
()
}
catch
(
error
)
{
ElMessage
.
error
(
error
.
message
)
}
}
else
{
try
{
const
res
=
await
updateCommissionExpected
({
commissionExpectedBizId
:
selectedRow
.
value
.
commissionExpectedBizId
,
...
addReceivablesFormModel
.
value
})
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'应收款修改成功'
)
addReceivablesDialogVisible
.
value
=
false
resetAddReceivablesForm
()
loadTableData
()
// 重新加载表格
}
else
{
ElMessage
.
error
(
res
.
msg
||
'应收款修改失败'
)
}
}
catch
(
error
)
{
console
.
error
(
'修改应收款失败:'
,
error
)
ElMessage
.
error
(
'修改应收款失败'
)
}
}
if
(
editStatus
.
value
===
'add'
)
{
const
p
=
addRecordRef
.
value
.
getFormData
()
try
{
await
addReceivedFortune
({
commissionExpectedAddDtoList
:
[
p
]
})
ElMessage
.
success
(
'新增应收款成功'
)
addReceivablesDialogVisible
.
value
=
false
resetAddReceivablesForm
()
handleQuery
()
}
catch
(
error
)
{
ElMessage
.
error
(
error
.
message
)
}
}
else
{
try
{
const
res
=
await
updateCommissionExpected
({
commissionExpectedBizId
:
selectedRow
.
value
.
commissionExpectedBizId
,
...
addReceivablesFormModel
.
value
})
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'应收款修改成功'
)
addReceivablesDialogVisible
.
value
=
false
resetAddReceivablesForm
()
loadTableData
()
// 重新加载表格
}
else
{
ElMessage
.
error
(
res
.
msg
||
'应收款修改失败'
)
}
}
catch
(
error
)
{
console
.
error
(
'修改应收款失败:'
,
error
)
ElMessage
.
error
(
'修改应收款失败'
)
}
}
}
const
searchFormRef
=
ref
(
null
)
const
searchParams
=
ref
({})
const
searchConfig
=
ref
([
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
},
{
type
:
'daterange'
,
prop
:
'entryDate'
,
label
:
'入账日(估)'
,
startPlaceholder
:
'开始时间'
,
endPlaceholder
:
'结束时间'
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'入账状态'
,
multiple
:
true
,
dictType
:
'csf_expected_commission_status'
},
{
type
:
'input'
,
prop
:
'commissionPeriod'
,
label
:
'入账期数'
,
inputType
:
'decimal'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
},
{
type
:
'select'
,
prop
:
'fortuneName'
,
label
:
'入账项目'
,
dictType
:
'csf_commission_type'
},
{
type
:
'select'
,
prop
:
'reconciliationCompanyBizIdList'
,
label
:
'对账公司'
,
api
:
'/insurance/base/api/insuranceReconciliationCompany/page'
,
keywordField
:
'name'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入对账公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
multiple
:
true
,
valueKey
:
'reconciliationCompanyBizId'
,
labelKey
:
'name'
,
transform
:
(
res
)
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'select'
,
prop
:
'insurerCompanyBizIdList'
,
label
:
'保险公司'
,
api
:
'/insurance/base/api/insuranceCompany/page'
,
keywordField
:
'queryContent'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入保险公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
multiple
:
true
,
valueKey
:
'insuranceCompanyBizId'
,
labelKey
:
'fullName'
,
transform
:
(
res
)
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'select'
,
prop
:
'productLaunchBizId'
,
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'
,
transform
:
(
res
)
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'select'
,
prop
:
'commissionBizType'
,
label
:
'应收单类型'
,
options
:
commissionBizTypeOptions
,
},
{
type
:
'select'
,
prop
:
'teamBizId'
,
label
:
'出单团队'
,
api
:
'/csf/api/team/page'
,
keywordField
:
'teamName'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入出单团队名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
valueKey
:
'teamBizId'
,
labelKey
:
'teamName'
,
transform
:
(
res
)
=>
{
return
res
?.
data
.
records
||
[]
}
{
type
:
'input'
,
prop
:
'policyNo'
,
label
:
'保单号'
},
{
type
:
'daterange'
,
prop
:
'entryDate'
,
label
:
'入账日(估)'
,
startPlaceholder
:
'开始时间'
,
endPlaceholder
:
'结束时间'
},
{
type
:
'select'
,
prop
:
'statusList'
,
label
:
'入账状态'
,
multiple
:
true
,
dictType
:
'csf_expected_commission_status'
},
{
type
:
'input'
,
prop
:
'commissionPeriod'
,
label
:
'入账期数'
,
inputType
:
'decimal'
,
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'select'
,
prop
:
'fortuneName'
,
label
:
'入账项目'
,
dictType
:
'csf_commission_type'
},
{
type
:
'select'
,
prop
:
'reconciliationCompanyBizIdList'
,
label
:
'对账公司'
,
api
:
'/insurance/base/api/insuranceReconciliationCompany/page'
,
keywordField
:
'name'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入对账公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
multiple
:
true
,
valueKey
:
'reconciliationCompanyBizId'
,
labelKey
:
'name'
,
transform
:
res
=>
{
console
.
log
(
res
)
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'select'
,
prop
:
'insurerCompanyBizIdList'
,
label
:
'保险公司'
,
api
:
'/insurance/base/api/insuranceCompany/page'
,
keywordField
:
'queryContent'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入保险公司名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
multiple
:
true
,
valueKey
:
'insuranceCompanyBizId'
,
labelKey
:
'fullName'
,
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'select'
,
prop
:
'productLaunchBizId'
,
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'
,
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'select'
,
prop
:
'commissionBizType'
,
label
:
'应收单类型'
,
options
:
commissionBizTypeOptions
},
{
type
:
'select'
,
prop
:
'teamBizId'
,
label
:
'出单团队'
,
api
:
'/csf/api/team/page'
,
keywordField
:
'teamName'
,
requestParams
:
{
pageNo
:
1
,
pageSize
:
20
},
placeholder
:
'输入出单团队名称搜索'
,
debounceWait
:
500
,
// 自定义防抖时间
valueKey
:
'teamBizId'
,
labelKey
:
'teamName'
,
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
type
:
'input'
,
prop
:
'policyHolder'
,
label
:
'投保人(中文/英文)'
},
{
type
:
'input'
,
prop
:
'insured'
,
label
:
'受保人(中文/英文)'
}
// {
// type: 'input',
// prop: 'signer',
// label: '签单员'
// },
// {
// type: 'input',
// prop: 'brokerName',
// label: '转介人(主)'
// }
])
// 分页相关
...
...
@@ -492,18 +616,17 @@ const pageSize = ref(10)
const
pageTotal
=
ref
(
0
)
const
loading
=
ref
(
false
)
// 应收单类型通过value转成label
const
getCommissionBizTypeLabel
=
(
value
)
=>
{
const
item
=
commissionBizTypeOptions
.
find
(
item
=>
item
.
value
===
value
)
return
item
?.
label
||
''
const
getCommissionBizTypeLabel
=
value
=>
{
const
item
=
commissionBizTypeOptions
.
find
(
item
=>
item
.
value
===
value
)
return
item
?.
label
||
''
}
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'入账记录'
,
value
:
'entryRecord'
},
{
label
:
'设置状态'
,
value
:
'setStatus'
},
{
label
:
'更新数据'
,
value
:
'updateData'
},
{
label
:
'入账记录'
,
value
:
'entryRecord'
},
{
label
:
'设置状态'
,
value
:
'setStatus'
},
{
label
:
'更新数据'
,
value
:
'updateData'
}
]
// 弹窗状态
...
...
@@ -527,360 +650,625 @@ const tableData = ref([])
// 统计信息
const
statisticsData
=
ref
({
totalAmount
:
0
,
totalPaidAmount
:
0
,
pendingPaidAmount
:
0
,
paidAmountRatio
:
0
,
totalPolicyCount
:
0
totalAmount
:
0
,
totalPaidAmount
:
0
,
pendingPaidAmount
:
0
,
paidAmountRatio
:
0
,
totalPolicyCount
:
0
})
const
handleInputChange
=
async
(
formType
,
prop
,
value
,
item
)
=>
{
if
(
formType
==
'addReceivables'
)
{
await
nextTick
()
let
policyNo
=
addReceivablesFormModel
.
value
.
policyNo
let
commissionPeriod
=
addReceivablesFormModel
.
value
.
commissionPeriod
if
((
prop
==
'policyNo'
||
prop
==
'commissionPeriod'
)
&&
commissionPeriod
&&
policyNo
)
{
//等待后端接口
const
res
=
await
commissionExchangeRateApi
({
policyNo
:
policyNo
,
commissionPeriod
:
commissionPeriod
})
if
(
res
.
code
==
200
)
{
addReceivablesFormModel
.
value
.
exchangeRate
=
res
.
data
}
else
{
ElMessage
.
error
(
'查询结算汇率失败'
)
}
}
}
}
// 按钮事件处理
const
handleAdd
=
()
=>
{
addReceivablesDialogVisible
.
value
=
true
if
(
addRecordRef
.
value
)
{
addRecordRef
.
value
.
resetForm
()
}
addReceivablesFormModel
.
value
=
{}
addReceivablesDialogVisible
.
value
=
true
if
(
addRecordRef
.
value
)
{
addRecordRef
.
value
.
resetForm
()
}
addReceivablesFormModel
.
value
=
{}
}
const
handleImport
=
()
=>
ElMessage
.
info
(
'点击导入按钮'
)
const
handleExport
=
async
()
=>
{
// 获取搜索参数
const
params
=
searchFormRef
.
value
?.
getFormData
()
||
{}
const
response
=
await
exportReceivedFortune
(
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
params
=
searchFormRef
.
value
?.
getFormData
()
||
{}
const
response
=
await
exportReceivedFortune
(
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
=
()
=>
{
// 重置搜索表单
searchFormRef
.
value
.
resetForm
()
searchParams
.
value
=
{}
console
.
log
(
'表单已重置'
)
loadTableData
()
// 重置搜索表单
searchFormRef
.
value
.
resetForm
()
searchParams
.
value
=
{}
console
.
log
(
'表单已重置'
)
loadTableData
()
}
const
handleQuery
=
()
=>
{
loadTableData
()
loadTableData
()
}
const
visibleDefaultButtons
=
ref
([
'add'
,
'export'
,
'reset'
,
'query'
])
const
visibleDefaultButtons
=
ref
([
'add'
,
'export'
,
'reset'
,
'query'
])
// 按钮配置
const
operationBtnList
=
ref
([
{
key
:
'add'
,
direction
:
'left'
,
click
:
handleAdd
},
// { key: 'import', direction: 'left', click: handleImport },
{
key
:
'export'
,
direction
:
'right'
,
click
:
handleExport
},
{
key
:
'reset'
,
direction
:
'right'
,
click
:
handleReset
},
{
key
:
'query'
,
direction
:
'right'
,
click
:
handleQuery
}
{
key
:
'add'
,
direction
:
'left'
,
click
:
handleAdd
},
// { key: 'import', direction: 'left', click: handleImport },
{
key
:
'export'
,
direction
:
'right'
,
click
:
handleExport
},
{
key
:
'reset'
,
direction
:
'right'
,
click
:
handleReset
},
{
key
:
'query'
,
direction
:
'right'
,
click
:
handleQuery
}
])
// 分页事件
const
handleSizeChange
=
(
val
)
=>
{
pageSize
.
value
=
val
loadTableData
()
const
handleSizeChange
=
val
=>
{
pageSize
.
value
=
val
loadTableData
()
}
const
handleCurrentChange
=
(
val
)
=>
{
currentPage
.
value
=
val
loadTableData
()
const
handleCurrentChange
=
val
=>
{
currentPage
.
value
=
val
loadTableData
()
}
// 加载表格数据
const
loadTableData
=
async
()
=>
{
const
searchParams
=
searchFormRef
.
value
.
getFormData
()
||
{}
loading
.
value
=
true
try
{
const
params
=
{
...
searchParams
,
commissionDateStart
:
searchParams
?.
entryDate
?.[
0
]
||
undefined
,
commissionDateEnd
:
searchParams
?.
entryDate
?.[
1
]
||
undefined
,
entryDate
:
undefined
,
pageNo
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
}
const
response
=
await
receivableReport
(
params
)
tableData
.
value
=
response
.
data
.
page
.
records
||
[]
pageTotal
.
value
=
response
.
data
.
page
.
total
||
0
pageSize
.
value
=
response
.
data
.
page
.
size
||
50
// 统计信息
statisticsData
.
value
=
{
totalAmount
:
response
.
data
.
statisticsVO
.
totalAmount
,
totalPaidAmount
:
response
.
data
.
statisticsVO
.
totalPaidAmount
,
pendingPaidAmount
:
response
.
data
.
statisticsVO
.
pendingPaidAmount
,
paidAmountRatio
:
response
.
data
.
statisticsVO
.
paidAmountRatio
,
totalPolicyCount
:
response
.
data
.
statisticsVO
.
totalPolicyCount
}
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
ElMessage
.
error
(
'加载数据失败'
)
}
finally
{
loading
.
value
=
false
const
searchParams
=
searchFormRef
.
value
.
getFormData
()
||
{}
// let msg = validateEnglish2(searchParams.eng)
// if (searchParams.eng && msg) {
// ElMessage.error(`投保人(英文):${msg}`)
// return
// }
loading
.
value
=
true
try
{
const
params
=
{
...
searchParams
,
commissionDateStart
:
searchParams
?.
entryDate
?.[
0
]
||
undefined
,
commissionDateEnd
:
searchParams
?.
entryDate
?.[
1
]
||
undefined
,
entryDate
:
undefined
,
pageNo
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
}
const
response
=
await
receivableReport
(
params
)
tableData
.
value
=
response
.
data
.
page
.
records
||
[]
pageTotal
.
value
=
response
.
data
.
page
.
total
||
0
pageSize
.
value
=
response
.
data
.
page
.
size
||
50
// 统计信息
statisticsData
.
value
=
{
totalAmount
:
response
.
data
.
statisticsVO
.
totalAmount
,
totalPaidAmount
:
response
.
data
.
statisticsVO
.
totalPaidAmount
,
pendingPaidAmount
:
response
.
data
.
statisticsVO
.
pendingPaidAmount
,
paidAmountRatio
:
response
.
data
.
statisticsVO
.
paidAmountRatio
,
totalPolicyCount
:
response
.
data
.
statisticsVO
.
totalPolicyCount
}
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
ElMessage
.
error
(
'加载数据失败'
)
}
finally
{
loading
.
value
=
false
}
}
// 入账记录查询
const
loadEntryRecordData
=
async
(
cbd
)
=>
{
loading
.
value
=
true
try
{
const
params
=
{
commissionExpectedBizId
:
cbd
}
const
response
=
await
commissionExpectedRecord
(
params
)
return
response
.
data
.
records
||
[]
}
catch
(
error
)
{
console
.
error
(
'加载入账记录失败:'
,
error
)
ElMessage
.
error
(
'加载入账记录失败'
)
return
[]
}
finally
{
loading
.
value
=
false
}
const
loadEntryRecordData
=
async
cbd
=>
{
loading
.
value
=
true
try
{
const
params
=
{
commissionExpectedBizId
:
cbd
}
const
response
=
await
commissionExpectedRecord
(
params
)
return
response
.
data
.
records
||
[]
}
catch
(
error
)
{
console
.
error
(
'加载入账记录失败:'
,
error
)
ElMessage
.
error
(
'加载入账记录失败'
)
return
[]
}
finally
{
loading
.
value
=
false
}
}
// 入账操作记录查询
const
loadEntryEditRecordData
=
async
(
cbd
)
=>
{
loading
.
value
=
true
try
{
const
params
=
{
commissionBizId
:
cbd
}
const
response
=
await
commissionEntryEditRecords
(
params
)
return
response
.
data
.
records
||
[]
}
catch
(
error
)
{
console
.
error
(
'加载操作记录失败:'
,
error
)
ElMessage
.
error
(
'加载操作记录失败'
)
return
[]
}
finally
{
loading
.
value
=
false
}
const
loadEntryEditRecordData
=
async
cbd
=>
{
loading
.
value
=
true
try
{
const
params
=
{
commissionBizId
:
cbd
}
const
response
=
await
commissionEntryEditRecords
(
params
)
return
response
.
data
.
records
||
[]
}
catch
(
error
)
{
console
.
error
(
'加载操作记录失败:'
,
error
)
ElMessage
.
error
(
'加载操作记录失败'
)
return
[]
}
finally
{
loading
.
value
=
false
}
}
// 操作菜单选择事件
const
handleSelect
=
async
(
e
,
row
)
=>
{
selectedRow
.
value
=
{
...
row
}
if
(
e
===
'entryRecord'
)
{
entryRecordDialogTableVisible
.
value
=
true
entryRecordDialogTableColumns
.
value
=
[
{
property
:
'reconciliationYearMonth'
,
label
:
'检核年月'
,
width
:
'100'
},
{
property
:
'commissionPeriod'
,
label
:
'佣金期数'
,
width
:
'100'
},
{
property
:
'totalPeriod'
,
label
:
'总期数'
,
width
:
'150'
},
{
property
:
'exchangeRate'
,
label
:
'结算汇率(实)'
,
width
:
'150'
},
{
property
:
'currency'
,
label
:
'入账币种'
,
width
:
'150'
},
{
property
:
'amount'
,
label
:
'入账金额'
,
width
:
'150'
,
formatter
:(
row
)
=>
formatCurrency
(
row
.
amount
||
0
)
},
{
property
:
'currentCommissionRatio'
,
label
:
'入账比例'
,
width
:
'150'
,
formatter
:
(
row
)
=>
`
${
row
.
currentCommissionRatio
||
''
}
%`
},
{
property
:
'commissionDate'
,
label
:
'入账日'
,
width
:
'150'
},
{
property
:
'commissionStatusName'
,
label
:
'入账状态'
,
width
:
'150'
}
]
// 加载真实数据
const
records
=
await
loadEntryRecordData
(
row
.
commissionExpectedBizId
)
entryRecordDialogTableData
.
value
=
records
.
length
?
records
:
[]
}
else
if
(
e
===
'setStatus'
)
{
console
.
log
(
selectedRow
.
value
.
status
)
setCommissionRecordStatusFormConfig
.
value
=
[
{
type
:
'select'
,
prop
:
'status'
,
label
:
'入账状态'
,
dictType
:
'csf_expected_commission_status'
,
defaultValue
:
selectedRow
.
value
.
status
||
''
},
{
type
:
'textarea'
,
prop
:
'statusDesc'
,
label
:
'修改理由'
,
defaultValue
:
selectedRow
.
value
.
statusDesc
||
''
},
]
setStatusDialogTableVisible
.
value
=
true
}
else
if
(
e
===
'updateData'
)
{
editStatus
.
value
=
'update'
addReceivablesDialogVisible
.
value
=
true
// 2. 使用 nextTick 等待 DOM 更新
nextTick
(()
=>
{
// 3. 此时 addRecordRef.value 一定存在了
if
(
addRecordRef
.
value
&&
selectedRow
.
value
)
{
addReceivablesFormModel
.
value
=
{
...
selectedRow
.
value
};
console
.
log
(
'赋值成功:'
,
addReceivablesFormModel
.
value
);
}
});
console
.
log
(
'更新数据'
,
selectedRow
.
value
)
}
selectedRow
.
value
=
{
...
row
}
if
(
e
===
'entryRecord'
)
{
entryRecordDialogTableVisible
.
value
=
true
entryRecordDialogTableColumns
.
value
=
[
{
property
:
'reconciliationYearMonth'
,
label
:
'检核年月'
,
width
:
'100'
},
{
property
:
'commissionPeriod'
,
label
:
'佣金期数'
,
width
:
'100'
},
{
property
:
'totalPeriod'
,
label
:
'总期数'
,
width
:
'150'
},
{
property
:
'exchangeRate'
,
label
:
'结算汇率(实)'
,
width
:
'150'
},
{
property
:
'currency'
,
label
:
'入账币种'
,
width
:
'150'
},
{
property
:
'amount'
,
label
:
'入账金额'
,
width
:
'150'
,
formatter
:
row
=>
formatCurrency
(
row
.
amount
||
0
)
},
{
property
:
'currentCommissionRatio'
,
label
:
'入账比例'
,
width
:
'150'
,
formatter
:
row
=>
`
${
row
.
currentCommissionRatio
||
''
}
%`
},
{
property
:
'commissionDate'
,
label
:
'入账日'
,
width
:
'150'
},
{
property
:
'commissionStatusName'
,
label
:
'入账状态'
,
width
:
'150'
}
]
// 加载真实数据
const
records
=
await
loadEntryRecordData
(
row
.
commissionExpectedBizId
)
entryRecordDialogTableData
.
value
=
records
.
length
?
records
:
[]
}
else
if
(
e
===
'setStatus'
)
{
console
.
log
(
selectedRow
.
value
.
status
)
setCommissionRecordStatusFormConfig
.
value
=
[
{
type
:
'select'
,
prop
:
'status'
,
label
:
'入账状态'
,
dictType
:
'csf_expected_commission_status'
,
defaultValue
:
selectedRow
.
value
.
status
||
''
},
{
type
:
'textarea'
,
prop
:
'statusDesc'
,
label
:
'修改理由'
,
defaultValue
:
selectedRow
.
value
.
statusDesc
||
''
}
]
setStatusDialogTableVisible
.
value
=
true
}
else
if
(
e
===
'updateData'
)
{
editStatus
.
value
=
'update'
addReceivablesDialogVisible
.
value
=
true
// 2. 使用 nextTick 等待 DOM 更新
nextTick
(()
=>
{
// 3. 此时 addRecordRef.value 一定存在了
if
(
addRecordRef
.
value
&&
selectedRow
.
value
)
{
addReceivablesFormModel
.
value
=
{
...
selectedRow
.
value
}
console
.
log
(
'赋值成功:'
,
addReceivablesFormModel
.
value
)
}
})
console
.
log
(
'更新数据'
,
selectedRow
.
value
)
}
}
// 查看比对记录
const
handleClick
=
async
(
row
)
=>
{
actionRecordsDialogVisible
.
value
=
true
actionRecordsDialogTableColumns
.
value
=
[
{
property
:
'checkMonth'
,
label
:
'检核年月'
,
width
:
'100'
},
{
property
:
'compareStatus'
,
label
:
'比对状态'
,
width
:
'150'
},
{
property
:
'entryRatio'
,
label
:
'入账比例'
,
width
:
'150'
},
{
property
:
'shouldEntryRatio'
,
label
:
'应入账比例'
,
width
:
'150'
},
{
property
:
'reconciliationCompany'
,
label
:
'对账公司'
,
width
:
'150'
},
{
property
:
'createTime'
,
label
:
'比对时间'
,
width
:
'150'
},
{
property
:
'userName'
,
label
:
'比对人'
,
width
:
'150'
}
]
// 加载真实数据
const
records
=
await
loadEntryEditRecordData
(
row
.
commissionBizId
)
actionRecordsDialogTableData
.
value
=
records
.
length
?
records
:
[]
const
handleClick
=
async
row
=>
{
actionRecordsDialogVisible
.
value
=
true
actionRecordsDialogTableColumns
.
value
=
[
{
property
:
'checkMonth'
,
label
:
'检核年月'
,
width
:
'100'
},
{
property
:
'compareStatus'
,
label
:
'比对状态'
,
width
:
'150'
},
{
property
:
'entryRatio'
,
label
:
'入账比例'
,
width
:
'150'
},
{
property
:
'shouldEntryRatio'
,
label
:
'应入账比例'
,
width
:
'150'
},
{
property
:
'reconciliationCompany'
,
label
:
'对账公司'
,
width
:
'150'
},
{
property
:
'createTime'
,
label
:
'比对时间'
,
width
:
'150'
},
{
property
:
'userName'
,
label
:
'比对人'
,
width
:
'150'
}
]
// 加载真实数据
const
records
=
await
loadEntryEditRecordData
(
row
.
commissionBizId
)
actionRecordsDialogTableData
.
value
=
records
.
length
?
records
:
[]
}
// 新增:设置状态确认事件
const
handleConfirmSetStatus
=
()
=>
{
const
formData
=
setCommissionRecordStatusFormRef
.
value
.
getFormData
()
if
(
!
formData
.
status
)
{
return
ElMessage
.
warning
(
'请选择入账状态'
)
}
if
(
!
formData
.
statusDesc
)
{
return
ElMessage
.
warning
(
'请输入修改理由'
)
}
// 调用接口修改状态(示例)
ElMessageBox
.
confirm
(
'确定要修改入账状态吗?'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}).
then
(
async
()
=>
{
try
{
const
res
=
await
CommissionExpectedChangeStatus
({
commissionExpectedBizId
:
selectedRow
.
value
.
commissionExpectedBizId
,
...
formData
})
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'状态修改成功'
)
setStatusDialogTableVisible
.
value
=
false
loadTableData
()
// 重新加载表格
}
else
{
ElMessage
.
error
(
res
.
msg
||
'状态修改失败'
)
}
}
catch
(
error
)
{
console
.
error
(
'修改状态失败:'
,
error
)
ElMessage
.
error
(
'修改状态失败'
)
const
formData
=
setCommissionRecordStatusFormRef
.
value
.
getFormData
()
if
(
!
formData
.
status
)
{
return
ElMessage
.
warning
(
'请选择入账状态'
)
}
if
(
!
formData
.
statusDesc
)
{
return
ElMessage
.
warning
(
'请输入修改理由'
)
}
// 调用接口修改状态(示例)
ElMessageBox
.
confirm
(
'确定要修改入账状态吗?'
,
'提示'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
})
.
then
(
async
()
=>
{
try
{
const
res
=
await
CommissionExpectedChangeStatus
({
commissionExpectedBizId
:
selectedRow
.
value
.
commissionExpectedBizId
,
...
formData
})
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'状态修改成功'
)
setStatusDialogTableVisible
.
value
=
false
loadTableData
()
// 重新加载表格
}
else
{
ElMessage
.
error
(
res
.
msg
||
'状态修改失败'
)
}
}).
catch
(()
=>
{
ElMessage
.
info
(
'已取消修改'
)
}
catch
(
error
)
{
console
.
error
(
'修改状态失败:'
,
error
)
ElMessage
.
error
(
'修改状态失败'
)
}
})
.
catch
(()
=>
{
ElMessage
.
info
(
'已取消修改'
)
})
}
// 获取入账状态,字典值转化方法
onMounted
(
async
()
=>
{
try
{
await
loadDicts
([
'csf_expected_commission_status'
])
loadTableData
()
}
catch
(
error
)
{
console
.
error
(
'字典加载失败'
,
error
)
}
finally
{
loading
.
value
=
false
}
try
{
await
loadDicts
([
'csf_expected_commission_status'
])
loadTableData
()
}
catch
(
error
)
{
console
.
error
(
'字典加载失败'
,
error
)
}
finally
{
loading
.
value
=
false
}
})
// 格式化函数(每次渲染都会调用,所以能拿到最新字典)
const
formatStatus
=
(
row
,
column
)
=>
{
return
getDictLabel
(
'csf_expected_commission_status'
,
row
.
status
)
// 实时查缓存
const
formatStatus
=
(
row
,
column
)
=>
{
return
getDictLabel
(
'csf_expected_commission_status'
,
row
.
status
)
// 实时查缓存
}
const
detailDialogVisible
=
ref
(
false
)
const
receivableReportTableData
=
ref
([])
const
receivableReportTableColumns
=
ref
([
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'150'
,
fixed
:
'left'
,
formatter
:
(
row
)
=>
row
.
policyNo
||
'-'
},
{
prop
:
'reconciliationCompany'
,
label
:
'对账公司'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
row
.
reconciliationCompany
||
'-'
},
{
prop
:
'commissionPeriod'
,
label
:
'入账期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
(
row
)
=>
row
.
commissionPeriod
||
'-'
},
{
prop
:
'totalPeriod'
,
label
:
'入账总期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
(
row
)
=>
row
.
totalPeriod
||
'-'
},
{
prop
:
'commissionDate'
,
label
:
'入账日(估)'
,
sortable
:
true
,
width
:
'130'
,
},
{
prop
:
'commissionRatio'
,
label
:
'产品对应来佣率'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
commissionRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'hkdAmount'
,
label
:
'预估入账金额HKD'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
hkdAmount
||
0
)
},
{
prop
:
'paidRatio'
,
label
:
'已入账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已入账金额HKD'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'unpaidRatio'
,
label
:
'待入账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
unpaidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'unpaidAmount'
,
label
:
'待入账金额HKD'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
unpaidAmount
||
0
)
},
{
prop
:
'exchangeRate'
,
label
:
'结算汇率(估)'
,
sortable
:
true
,
width
:
'120'
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
productName
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'policyCurrency'
,
label
:
'保单币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
policyCurrency
||
'-'
},
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'150'
,
fixed
:
'left'
,
formatter
:
row
=>
row
.
policyNo
||
'-'
},
{
prop
:
'reconciliationCompany'
,
label
:
'对账公司'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
row
.
reconciliationCompany
||
'-'
},
{
prop
:
'commissionPeriod'
,
label
:
'入账期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
row
=>
row
.
commissionPeriod
||
'-'
},
{
prop
:
'totalPeriod'
,
label
:
'入账总期数'
,
sortable
:
true
,
width
:
'100'
,
formatter
:
row
=>
row
.
totalPeriod
||
'-'
},
{
prop
:
'commissionDate'
,
label
:
'入账年月(估)'
,
sortable
:
true
,
width
:
'130'
},
{
prop
:
'commissionRatio'
,
label
:
'产品对应来佣率'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
commissionRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'hkdAmount'
,
label
:
'预估入账金额HKD'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
hkdAmount
||
0
)
},
{
prop
:
'paidRatio'
,
label
:
'已入账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已入账金额HKD'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'unpaidRatio'
,
label
:
'待入账比例'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
unpaidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'unpaidAmount'
,
label
:
'待入账金额HKD'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
unpaidAmount
||
0
)
},
{
prop
:
'exchangeRate'
,
label
:
'结算汇率(估)'
,
sortable
:
true
,
width
:
'120'
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'policyHolder'
,
label
:
'投保人'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
policyHolder
||
'-'
},
{
prop
:
'policyHolderEn'
,
label
:
'投保人(英文)'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
policyHolderEn
||
'-'
},
{
prop
:
'remark'
,
label
:
'备注'
,
width
:
'150'
,
formatter
:
row
=>
row
.
remark
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
productName
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'policyCurrency'
,
label
:
'保单币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
policyCurrency
||
'-'
}
])
// 应收明细
const
receivableReportItemTableColumns
=
ref
([
{
prop
:
'commissionBizType'
,
label
:
'应收单类型'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
getCommissionBizTypeLabel
(
row
.
commissionBizType
)
||
'-'
},
{
prop
:
'receivableNo'
,
label
:
'应收款编号'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
row
.
receivableNo
||
'-'
},
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
row
.
policyNo
||
'-'
},
{
prop
:
'reconciliationCompany'
,
label
:
'对账公司'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
(
row
)
=>
row
.
reconciliationCompany
||
'-'
},
{
prop
:
'status'
,
label
:
'入账状态'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatStatus
(
row
)
||
'-'
},
{
prop
:
'commissionPeriod'
,
label
:
'入账期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
commissionPeriod
||
'-'
},
{
prop
:
'totalPeriod'
,
label
:
'入账总期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
totalPeriod
||
'-'
},
{
prop
:
'commissionName'
,
label
:
'入账项目'
,
sortable
:
true
,
width
:
'130'
,
formatter
:
(
row
)
=>
row
.
commissionName
||
'-'
},
{
prop
:
'commissionDate'
,
label
:
'入账日(估)'
,
sortable
:
true
,
width
:
'130'
,
formatter
:
(
row
)
=>
row
.
commissionDate
||
'-'
},
{
prop
:
'commissionRatio'
,
label
:
'产品对应来佣率'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
commissionRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'expectedAmount'
,
label
:
'预估入账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
expectedAmount
||
0
)
},
{
prop
:
'paidRatio'
,
label
:
'实佣率'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已入账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'pendingRatio'
,
label
:
'实佣率缺口'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
(
row
.
pendingRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'pendingAmount'
,
label
:
'待入账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
pendingAmount
||
0
)
},
{
prop
:
'defaultExchangeRate'
,
label
:
'结算汇率(估)'
,
sortable
:
true
,
width
:
'120'
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
productName
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'policyCurrency'
,
label
:
'保单币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
policyCurrency
||
'-'
},
{
prop
:
'currency'
,
label
:
'入账币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
currency
||
'-'
},
{
prop
:
'statusDesc'
,
label
:
'入账状态修改理由'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
statusDesc
||
'-'
},
{
prop
:
'remark'
,
label
:
'备注'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
(
row
)
=>
row
.
remark
||
'-'
},
{
prop
:
'commissionBizType'
,
label
:
'应收单类型'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
getCommissionBizTypeLabel
(
row
.
commissionBizType
)
||
'-'
},
{
prop
:
'receivableNo'
,
label
:
'应收款编号'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
row
.
receivableNo
||
'-'
},
{
prop
:
'policyNo'
,
label
:
'保单号'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
row
.
policyNo
||
'-'
},
{
prop
:
'reconciliationCompany'
,
label
:
'对账公司'
,
sortable
:
true
,
width
:
'150'
,
formatter
:
row
=>
row
.
reconciliationCompany
||
'-'
},
{
prop
:
'status'
,
label
:
'入账状态'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatStatus
(
row
)
||
'-'
},
{
prop
:
'commissionPeriod'
,
label
:
'入账期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
commissionPeriod
||
'-'
},
{
prop
:
'totalPeriod'
,
label
:
'入账总期数'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
totalPeriod
||
'-'
},
{
prop
:
'commissionName'
,
label
:
'入账项目'
,
sortable
:
true
,
width
:
'130'
,
formatter
:
row
=>
row
.
commissionName
||
'-'
},
{
prop
:
'commissionDate'
,
label
:
'入账日(估)'
,
sortable
:
true
,
width
:
'130'
,
formatter
:
row
=>
row
.
commissionDate
||
'-'
},
{
prop
:
'commissionRatio'
,
label
:
'产品对应来佣率'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
commissionRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'expectedAmount'
,
label
:
'预估入账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
expectedAmount
||
0
)
},
{
prop
:
'paidRatio'
,
label
:
'实佣率'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
paidRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'paidAmount'
,
label
:
'已入账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
paidAmount
||
0
)
},
{
prop
:
'pendingRatio'
,
label
:
'实佣率缺口'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
(
row
.
pendingRatio
||
0
)
+
'%'
||
'-'
},
{
prop
:
'pendingAmount'
,
label
:
'待入账金额'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
pendingAmount
||
0
)
},
{
prop
:
'defaultExchangeRate'
,
label
:
'结算汇率(估)'
,
sortable
:
true
,
width
:
'120'
},
{
prop
:
'insuranceCompany'
,
label
:
'保险公司'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
insuranceCompany
||
'-'
},
{
prop
:
'productName'
,
label
:
'产品计划'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
productName
||
'-'
},
{
prop
:
'premium'
,
label
:
'期交保费'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
formatCurrency
(
row
.
premium
||
0
)
},
{
prop
:
'policyCurrency'
,
label
:
'保单币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
policyCurrency
||
'-'
},
{
prop
:
'currency'
,
label
:
'入账币种'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
currency
||
'-'
},
{
prop
:
'statusDesc'
,
label
:
'入账状态修改理由'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
statusDesc
||
'-'
},
{
prop
:
'remark'
,
label
:
'备注'
,
sortable
:
true
,
width
:
'120'
,
formatter
:
row
=>
row
.
remark
||
'-'
}
])
const
detailRecordStatistics
=
ref
({})
const
detailPageInfo
=
ref
({
pageNo
:
1
,
pageSize
:
10
,
currentPage
:
1
,
total
:
0
pageNo
:
1
,
pageSize
:
10
,
currentPage
:
1
,
total
:
0
})
// 获取入账报告
const
receivedFortuneListData
=
async
()
=>
{
loading
.
value
=
true
try
{
const
params
=
{
policyNo
:
selectedDetailRecordRow
.
value
.
policyNo
,
commissionPeriod
:
selectedDetailRecordRow
.
value
.
commissionPeriod
,
receivableNo
:
selectedDetailRecordRow
.
value
.
receivableNo
,
pageNo
:
detailPageInfo
.
value
.
currentPage
,
pageSize
:
detailPageInfo
.
value
.
pageSize
}
const
response
=
await
receivedFortuneList
(
params
)
receivableReportTableData
.
value
=
response
.
data
.
page
.
records
||
[]
detailPageInfo
.
value
.
total
=
response
.
data
.
page
.
total
||
0
detailPageInfo
.
value
.
pageSize
=
response
.
data
.
page
.
size
||
50
// 统计信息
detailRecordStatistics
.
value
=
{
totalAmount
:
response
.
data
.
expectedStatisticsVO
.
totalAmount
,
totalPaidAmount
:
response
.
data
.
expectedStatisticsVO
.
totalPaidAmount
,
pendingPaidAmount
:
response
.
data
.
expectedStatisticsVO
.
pendingPaidAmount
,
paidAmountRatio
:
response
.
data
.
expectedStatisticsVO
.
paidAmountRatio
,
totalPolicyCount
:
response
.
data
.
expectedStatisticsVO
.
totalPolicyCount
,
totalPremium
:
response
.
data
.
expectedStatisticsVO
.
totalPremium
}
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
ElMessage
.
error
(
'加载数据失败'
)
}
finally
{
loading
.
value
=
false
loading
.
value
=
true
try
{
const
params
=
{
policyNo
:
selectedDetailRecordRow
.
value
.
policyNo
,
commissionPeriod
:
selectedDetailRecordRow
.
value
.
commissionPeriod
,
receivableNo
:
selectedDetailRecordRow
.
value
.
receivableNo
,
pageNo
:
detailPageInfo
.
value
.
currentPage
,
pageSize
:
detailPageInfo
.
value
.
pageSize
}
const
response
=
await
receivedFortuneList
(
params
)
receivableReportTableData
.
value
=
response
.
data
.
page
.
records
||
[]
detailPageInfo
.
value
.
total
=
response
.
data
.
page
.
total
||
0
detailPageInfo
.
value
.
pageSize
=
response
.
data
.
page
.
size
||
50
// 统计信息
detailRecordStatistics
.
value
=
{
totalAmount
:
response
.
data
.
expectedStatisticsVO
.
totalAmount
,
totalPaidAmount
:
response
.
data
.
expectedStatisticsVO
.
totalPaidAmount
,
pendingPaidAmount
:
response
.
data
.
expectedStatisticsVO
.
pendingPaidAmount
,
paidAmountRatio
:
response
.
data
.
expectedStatisticsVO
.
paidAmountRatio
,
totalPolicyCount
:
response
.
data
.
expectedStatisticsVO
.
totalPolicyCount
,
totalPremium
:
response
.
data
.
expectedStatisticsVO
.
totalPremium
}
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
ElMessage
.
error
(
'加载数据失败'
)
}
finally
{
loading
.
value
=
false
}
}
const
selectedDetailRecordRow
=
ref
({})
const
viewDetail
=
(
row
)
=>
{
selectedDetailRecordRow
.
value
=
row
detailDialogVisible
.
value
=
true
receivedFortuneListData
()
const
viewDetail
=
row
=>
{
selectedDetailRecordRow
.
value
=
row
detailDialogVisible
.
value
=
true
receivedFortuneListData
()
}
// 分页事件
const
handleSizeChangeDetailRecord
=
(
val
)
=>
{
detailPageInfo
.
value
.
pageSize
=
val
receivedFortuneListData
()
const
handleSizeChangeDetailRecord
=
val
=>
{
detailPageInfo
.
value
.
pageSize
=
val
receivedFortuneListData
()
}
// 分页事件
const
handleCurrentChangeDetailRecord
=
(
val
)
=>
{
detailPageInfo
.
value
.
currentPage
=
val
receivedFortuneListData
()
const
handleCurrentChangeDetailRecord
=
val
=>
{
detailPageInfo
.
value
.
currentPage
=
val
receivedFortuneListData
()
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
\ No newline at end of file
<
style
scoped
lang=
"scss"
></
style
>
src/views/sign/FnaList/edit.vue
View file @
08e9e2d3
...
...
@@ -12,7 +12,7 @@
<span
class=
"iconfont icon-yanqiweiwancheng"
></span>
<span
>
{{
parseTime
(
processInfo
.
createTime
)
}}
由
{{
processInfo
.
userBizId
||
'--'
processInfo
.
creatorName
||
'--'
}}
创建
</span
>
</div>
...
...
@@ -161,7 +161,7 @@ const processInfo = ref({
fnaNo
:
'--'
,
status
:
'未保存'
,
createTime
:
proxy
.
parseTime
(
new
Date
()),
c
ustome
rName
:
userStore
.
name
c
reato
rName
:
userStore
.
name
})
// 流程详情信息
const
updateStatus
=
ref
(
false
)
const
dictTypeLists
=
ref
([])
...
...
@@ -321,7 +321,7 @@ const getDictsData = async () => {
projectBizId
:
userStore
.
projectInfo
.
projectBizId
,
tenantBizId
:
userStore
.
projectInfo
.
tenantBizId
,
fieldBizId
:
'field_olk1qZe81qHHKXbw'
,
fieldValueBizId
:
'field_value_yXzTigvgUdRMFpoR'
,
fieldValueBizId
:
'field_value_yXzTigvgUdRMFpoR'
}
const
response6
=
await
secondAdditonalList
(
params6
)
if
(
response6
.
code
==
200
)
{
...
...
@@ -399,6 +399,9 @@ function getProcessInfo(fnaBizId, changeTab, currentTab) {
getProcessDetail
(
fnaBizId
).
then
(
async
res
=>
{
if
(
res
.
code
==
200
)
{
processInfo
.
value
=
res
.
data
if
(
!
processInfo
.
value
.
creatorName
)
{
processInfo
.
value
.
creatorName
=
userStore
.
name
}
tabsList
.
value
.
forEach
(
item
=>
{
if
(
res
.
data
[
item
.
key
]
&&
item
.
status
)
{
item
.
status
=
'1'
...
...
src/views/sign/FnaList/index.vue
View file @
08e9e2d3
...
...
@@ -61,6 +61,16 @@
</el-select>
</el-form-item>
</el-col>
<el-col
:sm=
"12"
:lg=
"6"
:xs=
"24"
>
<el-form-item
label=
"创建人"
prop=
"creatorName"
>
<el-input
v-model=
"queryParams.creatorName"
placeholder=
"请输入创建人"
clearable
@
keyup
.
enter=
"handleQuery"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</
template
>
...
...
@@ -76,22 +86,26 @@
max-height=
"380px"
>
<el-table-column
type=
"index"
width=
"100"
label=
"序号"
/>
<el-table-column
label=
"客户姓名"
align=
"center"
prop=
"customerName"
width=
"180"
>
<template
#
default=
"scope"
>
<el-table-column
label=
"客户姓名"
align=
"center"
prop=
"customerName"
width=
"180"
>
<template
#
default=
"scope"
>
<el-button
link
size=
"default"
>
<span
@
click=
"copyToClipboard(scope.row.customerName,'客户姓名')"
>
{{
scope
.
row
.
customerName
}}
</span>
<span
@
click=
"copyToClipboard(scope.row.customerName, '客户姓名')"
>
{{
scope
.
row
.
customerName
}}
</span>
</el-button>
</
template
>
</el-table-column>
<el-table-column
label=
"中文姓名"
align=
"center"
prop=
"customerNameCn"
width=
"180"
>
<
template
#
default=
"scope"
>
<el-button
link
size=
"default"
>
<span
@
click=
"copyToClipboard(scope.row.customerNameCn,'中文姓名')"
>
{{
scope
.
row
.
customerNameCn
}}
</span>
</el-button>
</
template
>
</el-table-column>
</
template
>
</el-table-column>
<el-table-column
label=
"中文姓名"
align=
"center"
prop=
"customerNameCn"
width=
"180"
>
<
template
#
default=
"scope"
>
<el-button
link
size=
"default"
>
<span
@
click=
"copyToClipboard(scope.row.customerNameCn, '中文姓名')"
>
{{
scope
.
row
.
customerNameCn
}}
</span>
</el-button>
</
template
>
</el-table-column>
<!-- <el-table-column label="状态" align="center" prop="status" width="100" :formatter="getDictLabel('csf_fna_status')"/> -->
<el-table-column
label=
"流程状态"
sortable
align=
"center"
prop=
"status"
width=
"200"
>
<el-table-column
label=
"流程状态"
sortable
align=
"center"
prop=
"status"
width=
"200"
>
<
template
#
default=
"scope"
>
<span>
{{
selectDictLabel
(
csf_fna_status
,
scope
.
row
.
status
)
}}
</span>
</
template
>
...
...
@@ -101,13 +115,16 @@
align=
"center"
prop=
"fnaNo"
width=
"240"
show-overflow-tooltip
>
<
template
#
default=
"scope"
>
show-overflow-tooltip
>
<
template
#
default=
"scope"
>
<el-button
link
size=
"default"
>
<span
@
click=
"copyToClipboard(scope.row.fnaNo,'流程编号')"
>
{{
scope
.
row
.
fnaNo
}}
</span>
<span
@
click=
"copyToClipboard(scope.row.fnaNo, '流程编号')"
>
{{
scope
.
row
.
fnaNo
}}
</span>
</el-button>
</
template
>
</el-table-column>
</
template
>
</el-table-column>
<el-table-column
label=
"预约编号"
align=
"center"
...
...
@@ -117,12 +134,14 @@
>
<
template
#
default=
"scope"
>
<el-button
link
size=
"default"
>
<span
@
click=
"copyToClipboard(scope.row.appointmentNo,'预约编号')"
>
{{
scope
.
row
.
appointmentNo
}}
</span>
<span
@
click=
"copyToClipboard(scope.row.appointmentNo, '预约编号')"
>
{{
scope
.
row
.
appointmentNo
}}
</span>
</el-button>
</
template
>
</el-table-column>
<!-- <el-table-column label="新单编号" align="center" prop="policyId" /> -->
</
template
>
</el-table-column>
<el-table-column
label=
"保单号"
align=
"center"
prop=
"policyNo"
width=
"180"
/>
<el-table-column
label=
"创建人"
align=
"center"
prop=
"creatorName"
width=
"180"
/>
<el-table-column
label=
"创建时间"
sortable
align=
"center"
prop=
"createTime"
width=
"200"
>
<
template
#
default=
"scope"
>
...
...
@@ -181,7 +200,7 @@ import { getFnaList, deleteFna, subProcess } from '@/api/sign/fna'
import
useUserStore
from
'@/store/modules/user'
import
{
MoreFilled
,
InfoFilled
}
from
'@element-plus/icons-vue'
import
useDictStore
from
'@/store/modules/dict'
import
copyToClipboard
from
'@/utils/copyToClipboard'
;
import
copyToClipboard
from
'@/utils/copyToClipboard'
const
dictStore
=
useDictStore
()
const
userStore
=
useUserStore
()
const
router
=
useRouter
()
...
...
@@ -395,7 +414,6 @@ function handleUpdate(row) {
}
getList
()
</
script
>
<
style
lang=
"scss"
scoped
>
.bottomBtn
{
...
...
src/views/sign/policyReceipts/premiumRecon.vue
View file @
08e9e2d3
...
...
@@ -98,7 +98,9 @@
</el-table-column>
<el-table-column
prop=
"payer"
label=
"付款人"
width=
"150"
/>
<el-table-column
prop=
"policyHolder"
label=
"投保人"
width=
"150"
/>
<el-table-column
prop=
"policyHolderEn"
label=
"投保人(英文)"
width=
"120"
/>
<el-table-column
prop=
"insured"
label=
"受保人"
width=
"150"
/>
<el-table-column
prop=
"insuredEn"
label=
"受保人(英文)"
width=
"150"
/>
<el-table-column
prop=
"brokerName"
label=
"转介人"
width=
"150"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
width=
"150"
>
<
template
#
default=
"{ row }"
>
...
...
@@ -244,9 +246,10 @@
:config=
"remittanceConfig"
v-model=
"remittanceFormModel"
@
uploadSuccess=
"handleUploadSuccess"
@
select-change=
"onSelectChange"
/>
<div
v-if=
"remittanceFormModel.apiPremiumRemittanceFileDtoList
?.length
"
v-if=
"remittanceFormModel.apiPremiumRemittanceFileDtoList
.length > 0
"
class=
"otherFileBox"
>
<el-table
border
:data=
"tempOtherFileList"
size=
"small"
>
...
...
@@ -260,6 +263,7 @@
</el-table-column>
<el-table-column
label=
"操作"
width=
"100"
>
<
template
#
default=
"{ row, $index }"
>
<el-button
type=
"primary"
link
@
click=
"viewFile(row, $index)"
>
查看
</el-button>
<el-button
type=
"danger"
link
@
click=
"removeOtherFile(row, $index)"
>
删除
</el-button>
...
...
@@ -270,13 +274,21 @@
</div>
</el-scrollbar>
</CommonDialog>
<filePreviewDialog
v-model=
"previewVisible"
:file-url=
"currentOtherFile.fileUrl"
:file-name=
"currentOtherFile.fileName"
ref=
"filePreviewDialogRef"
/>
</div>
</template>
<
script
setup
>
import
{
validateEnglish2
}
from
'@/utils/validate'
import
{
ref
,
reactive
,
watch
}
from
'vue'
import
CommonPage
from
'@/components/commonPage'
import
CommonDialog
from
'@/components/commonDialog'
import
filePreviewDialog
from
'@/components/commonDialog/filePreviewDialog.vue'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
import
{
ElMessage
}
from
'element-plus'
import
{
formatCurrency
}
from
'@/utils/number'
...
...
@@ -296,13 +308,19 @@ import {
editPremiumReconciliation
,
getRemainingUnpaidAmount
,
submitResult
,
addSinglePremiumRemittance
addSinglePremiumRemittance
,
policyDetail
}
from
'@/api/sign/policy'
import
{
getBankList
}
from
'@/api/common'
import
useUserStore
from
'@/store/modules/user'
import
{
loadDicts
,
getDictLabel
}
from
'@/utils/useDict'
import
{
getToken
}
from
'@/utils/auth'
import
{
getNowTime
,
formatToDate
,
formatToDateTime
}
from
'@/utils/date'
const
previewVisible
=
ref
(
false
)
const
currentFileUrl
=
ref
(
''
)
const
currentFileName
=
ref
(
''
)
const
currentOtherFile
=
ref
({
fileUrl
:
''
,
fileName
:
''
})
const
{
proxy
}
=
getCurrentInstance
()
const
userStore
=
useUserStore
()
// 分页相关
...
...
@@ -374,7 +392,7 @@ const searchConfig = ref([
{
type
:
'input'
,
prop
:
'policyHolder'
,
label
:
'投保人'
label
:
'投保人
(中文/英文)
'
},
{
type
:
'select'
,
...
...
@@ -384,6 +402,11 @@ const searchConfig = ref([
dictType
:
'csf_ap_first_issue'
},
{
type
:
'input'
,
prop
:
'insured'
,
label
:
'受保人(中文/英文)'
},
{
type
:
'select'
,
prop
:
'policyFollowStatus'
,
label
:
'新单状态'
,
...
...
@@ -408,10 +431,15 @@ const searchConfig = ref([
type
:
'date'
,
prop
:
'paymentDate'
,
label
:
'付款日期'
,
maxDate
:
'today'
}
// {
// type: 'input',
// prop: 'eng',
// label: '英文名字'
// }
])
// 动态生成操作菜单项
const
getMenuItems
=
row
=>
{
const
items
=
[{
label
:
'编辑'
,
value
:
'editRecord'
}]
...
...
@@ -426,6 +454,13 @@ const getMenuItems = row => {
return
items
}
const
viewFile
=
row
=>
{
console
.
log
(
'===================================='
)
console
.
log
(
'其他附件'
,
row
)
console
.
log
(
'===================================='
)
previewVisible
.
value
=
true
currentOtherFile
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
row
))
}
//获取远程搜索下拉框数据,回显数据用
const
getSelectOptions
=
async
()
=>
{
const
params4
=
{
...
...
@@ -748,13 +783,16 @@ const remittanceConfig = [
multiple
:
true
,
limit
:
10
,
maxSize
:
10
*
1024
*
1024
,
// 10MB
accept
:
'.png,.jpg,.jpeg,.webp,.pdf,.doc,.docx,.xls,.xlsx,.txt'
,
// ✅ 改成扩展名!
// accept: '.png,.jpg,.jpeg,.webp,.pdf,.doc,.docx,.xls,.xlsx,.txt', // ✅ 改成扩展名!
accept
:
'.png,.jpg,.jpeg,.webp,.pdf'
,
// ✅ 改成扩展名!
action
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/oss/api/oss/upload'
,
headers
:
{
Authorization
:
'Bearer '
+
getToken
()
},
listType
:
'text'
,
defaultValue
:
[],
span
:
24
,
rules
:
[{
required
:
true
,
message
:
'请上传支付凭证'
,
trigger
:
'blur'
}]
rules
:
[{
required
:
true
,
message
:
'请上传支付凭证'
,
trigger
:
'blur'
}],
customFileList
:
true
,
// ✅ 开启自定义列表
customUploadButtonText
:
'点击上传文件'
// 可选,默认“点击上传文件”
},
{
type
:
'upload'
,
...
...
@@ -764,13 +802,15 @@ const remittanceConfig = [
multiple
:
true
,
limit
:
10
,
maxSize
:
10
*
1024
*
1024
,
// 10MB
accept
:
'.png,.jpg,.jpeg,.webp,.pdf
,.doc,.docx,.xls,.xlsx,.txt
'
,
// ✅ 改成扩展名!
accept
:
'.png,.jpg,.jpeg,.webp,.pdf'
,
// ✅ 改成扩展名!
action
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/oss/api/oss/upload'
,
headers
:
{
Authorization
:
'Bearer '
+
getToken
()
},
listType
:
'text'
,
defaultValue
:
[],
span
:
24
,
rules
:
[{
required
:
true
,
message
:
'请上传账户证明'
,
trigger
:
'blur'
}]
rules
:
[{
required
:
true
,
message
:
'请上传账户证明'
,
trigger
:
'blur'
}],
customFileList
:
true
,
// ✅ 开启自定义列表
customUploadButtonText
:
'点击上传文件'
// 可选,默认“点击上传文件”
},
{
type
:
'upload'
,
...
...
@@ -780,7 +820,7 @@ const remittanceConfig = [
multiple
:
true
,
limit
:
10
,
maxSize
:
10
*
1024
*
1024
,
// 5MB
accept
:
'.png,.jpg,.jpeg,.webp,.pdf
,.doc,.docx,.xls,.xlsx,.txt
'
,
// ✅ 支持多种格式
accept
:
'.png,.jpg,.jpeg,.webp,.pdf'
,
// ✅ 支持多种格式
action
:
import
.
meta
.
env
.
VITE_APP_BASE_API
+
'/oss/api/oss/upload'
,
headers
:
{
Authorization
:
'Bearer '
+
getToken
()
},
listType
:
'text'
,
// ← 按钮样式(非图片卡片)
...
...
@@ -809,12 +849,43 @@ const handleUploadSuccess = (prop, Model) => {
}
}
// 下拉框改变
function
onSelectChange
(
prop
,
value
,
item
)
{
async
function
onSelectChange
(
prop
,
value
,
item
)
{
console
.
log
(
'【Select 变更】字段:'
,
prop
,
'新值:'
,
value
,
'配置:'
,
item
)
// 示例:你可以在这里做任何事
if
(
prop
===
'policyNo'
)
{
checkPolicyNo
(
value
)
}
else
if
(
prop
==
'paymentRel'
)
{
if
(
value
!==
'TBR'
&&
value
!==
'SBR'
)
{
await
nextTick
()
// 等待 Vue 完成本轮 DOM 更新
remittanceFormModel
.
value
.
payer
=
''
}
if
(
value
==
'TBR'
||
value
==
'SBR'
)
{
getPolicyInfo
(
currentRow
.
value
.
policyNo
,
'remittance'
,
value
)
}
}
}
// 检查此保单号是否已经提交过保费对账
const
getPolicyInfo
=
async
(
policyNo
,
type
,
valueType
)
=>
{
try
{
const
res
=
await
policyDetail
(
policyNo
)
console
.
log
(
'姓名'
,
res
)
if
(
type
==
'remittance'
)
{
if
(
valueType
==
'TBR'
)
{
remittanceFormModel
.
value
.
payer
=
res
.
data
.
policyHolder
}
else
if
(
valueType
==
'SBR'
)
{
remittanceFormModel
.
value
.
payer
=
res
.
data
.
insured
}
}
else
if
(
type
==
'affirm'
)
{
affirmFormModel
.
value
.
effectiveDate
=
res
.
data
.
effectiveDate
affirmFormModel
.
value
.
underwritingDate
=
res
.
data
.
underwritingDate
affirmFormModel
.
value
.
status
=
res
.
data
.
status
affirmFormModel
.
value
.
policyExpirationDate
=
res
.
data
.
policyExpirationDate
affirmFormModel
.
value
.
coolingOffEndDate
=
res
.
data
.
coolingOffEndDate
}
}
catch
(
error
)
{
console
.
error
(
'加载数据失败:'
,
error
)
ElMessage
.
error
(
error
.
message
||
'加载数据失败'
)
}
}
// 新增汇款
...
...
@@ -908,6 +979,7 @@ const confirmRemittance = async data => {
const
formData
=
await
remittanceFormRef
.
value
.
validate
()
let
newFormData
=
JSON
.
parse
(
JSON
.
stringify
(
formData
))
// 因为汇款记录回显了保费对账的一些字段,但提交汇款记录的时候这些回显的字段是不能提交的,所以在这里做删除
for
(
const
key
in
newFormData
)
{
if
(
key
==
deleteObjkeys
[
key
])
delete
newFormData
[
key
]
// 文件上传的数据格式在这里统一处理
...
...
@@ -934,6 +1006,9 @@ const confirmRemittance = async data => {
}
}
let
res
=
{}
console
.
log
(
'===================================='
)
console
.
log
(
'newFormData'
,
newFormData
)
console
.
log
(
'===================================='
)
if
(
currentRow
.
value
.
premiumReconciliationBizId
&&
!
formData
.
premiumRemittanceBizId
)
{
//编辑保费对账状态下新增汇款记录
const
params
=
{
...
...
@@ -986,8 +1061,11 @@ const confirmRemittance = async data => {
}
}
// 修改汇款记录
const
editRemittance
=
row
=>
{
const
editRemittance
=
async
row
=>
{
let
newObj
=
JSON
.
parse
(
JSON
.
stringify
(
row
))
console
.
log
(
'===================================='
)
console
.
log
(
'修改'
,
row
)
console
.
log
(
'===================================='
)
// 添加保费对账弹窗得form表单便于汇款回显
newObj
.
reconciliationType
=
addCheckRecordFormModel
.
value
.
reconciliationType
newObj
.
applicant
=
addCheckRecordFormModel
.
value
.
applicant
...
...
@@ -997,28 +1075,47 @@ const editRemittance = row => {
// 上传回显得格式是[{url:''}]所以要处理一下
for
(
const
key
in
newObj
)
{
if
(
(
key
==
'paymentVoucherList'
||
key
==
'accountVerificationList'
||
key
==
'apiPremiumRemittanceFileDtoList'
)
&&
newObj
[
key
]
&&
newObj
[
key
].
length
>
0
key
==
'accountVerificationDtoList'
||
(
key
==
'paymentVoucherDtoList'
&&
newObj
[
key
]
&&
newObj
[
key
].
length
>
0
)
)
{
console
.
log
(
'key'
,
key
)
newObj
[
key
]
=
newObj
[
key
].
map
(
item
=>
{
return
{
url
:
item
.
fileUrl
,
name
:
item
.
fileName
}
})
}
if
(
key
==
'apiPremiumRemittanceFileDtoList'
&&
newObj
[
key
]
&&
newObj
[
key
].
length
>
0
)
{
newObj
[
key
]
=
newObj
[
key
].
map
(
item
=>
{
if
(
key
==
'apiPremiumRemittanceFileDtoList'
)
{
return
{
...
item
,
url
:
item
.
fileUrl
}
}
else
{
return
{
url
:
item
}
}
// else {
// return {
// url: item.fileUrl,
// name: item.fileName
// }
// }
})
}
}
remittanceFormModel
.
value
=
newObj
console
.
log
(
'remittanceFormModel.value'
,
remittanceFormModel
.
value
)
if
(
newObj
.
accountVerificationDtoList
&&
newObj
.
accountVerificationDtoList
.
length
>
0
)
{
remittanceFormModel
.
value
.
accountVerificationList
=
newObj
.
accountVerificationDtoList
}
if
(
newObj
.
paymentVoucherDtoList
&&
newObj
.
paymentVoucherDtoList
.
length
>
0
)
{
remittanceFormModel
.
value
.
paymentVoucherList
=
newObj
.
paymentVoucherDtoList
}
if
(
remittanceFormModel
.
value
.
apiPremiumRemittanceFileDtoList
.
length
>
0
)
{
tempOtherFileList
.
value
=
remittanceFormModel
.
value
.
apiPremiumRemittanceFileDtoList
}
showRemittance
.
value
=
true
}
...
...
@@ -1148,7 +1245,11 @@ const handleReset = () => {
const
handleQuery
=
async
()
=>
{
const
params
=
searchFormRef
.
value
.
getFormData
()
console
.
log
(
'params'
,
params
)
// let msg = validateEnglish2(params.eng)
// if (params.eng && msg) {
// ElMessage.error(`英文名字:${msg}`)
// return
// }
loadTableData
(
params
)
}
const
visibleDefaultButtons
=
ref
([
'add'
,
'reset'
,
'query'
])
...
...
@@ -1222,8 +1323,10 @@ const handleSelect = (command, row) => {
settingAffirmLoading
.
value
=
false
showAffirm
.
value
=
true
currentRow
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
row
))
getPolicyInfo
(
row
.
policyNo
,
'affirm'
)
}
}
const
addReceipts
=
async
()
=>
{
try
{
// ✅ 正确:await validate(),成功时返回表单数据
...
...
src/views/sign/underwritingMain/index.vue
View file @
08e9e2d3
<
template
>
<div>
<CommonPage
:operationBtnList=
'operationBtnList'
:visibleDefaultButtons=
"visibleDefaultButtons"
v-loading
.
fullscreen
.
lock=
"statusLoading"
:showSearchForm=
'true'
:show-pagination=
'true'
:total=
'pageTotal'
:current-page=
'currentPage'
:page-size=
'pageSize'
@
size-change=
'handleSizeChange'
@
current-change=
'handleCurrentChange'
>
<CommonPage
:operationBtnList=
"operationBtnList"
:visibleDefaultButtons=
"visibleDefaultButtons"
v-loading
.
fullscreen
.
lock=
"statusLoading"
:showSearchForm=
"true"
:show-pagination=
"true"
:total=
"pageTotal"
:current-page=
"currentPage"
:page-size=
"pageSize"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
>
<!-- 搜索区域 -->
<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
: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 }">
...
...
@@ -25,6 +41,10 @@
<el-table-column
prop=
"insuranceCompany"
label=
"保险公司"
width=
"200"
sortable
/>
<el-table-column
prop=
"productName"
label=
"产品计划"
width=
"200"
sortable
/>
<el-table-column
prop=
"issueNumber"
label=
"缴费年期"
width=
"120"
sortable
/>
<el-table-column
prop=
"brokerName"
label=
"转介人(主)"
width=
"120"
/>
<el-table-column
prop=
"eachIssuePremium"
label=
"保费"
width=
"120"
/>
<el-table-column
prop=
"signer"
label=
"签单员"
width=
"120"
/>
<el-table-column
prop=
"coolingOffEndDate"
label=
"冷静期结束日"
width=
"150"
sortable
/>
<el-table-column
fixed=
"right"
label=
"操作"
min-width=
"80"
>
<
template
#
default=
"{ row }"
>
<el-popover
placement=
"right"
:width=
"200"
trigger=
"click"
>
...
...
@@ -34,9 +54,12 @@
</el-icon>
</
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"
>
{{
item.label
}}
</el-menu-item>
<el-menu-item
:index=
"item.value"
v-for=
"item in dropdownItems"
:key=
"item.value"
>
{{ item.label }}
</el-menu-item
>
</el-menu>
</el-popover>
</template>
...
...
@@ -45,14 +68,31 @@
</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
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'
>
<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"
/>
...
...
@@ -69,21 +109,31 @@
</CommonDialog>
<!-- 查看详情、更新数据 -->
<CommonDialog
:dialogTitle=
'mode === "viewDetail" ? "查看详情" : "更新数据"'
dialogWidth=
'80%'
:openDialog=
viewDetailDialogFlag
:showAction=
'false'
:showClose=
'true'
@
close=
'viewDetailDialogFlag=false'
@
confirm=
'handleUpdateSubmit'
>
<PolicyDetail
v-model=
"policyDetailFormData"
:policyBizId=
"selectedRow.policyBizId"
:mode=
"mode"
ref=
"policyDetailFormRef"
@
submit=
"onSubmit"
@
cancel=
"viewDetailDialogFlag = false"
v-if=
"viewDetailDialogFlag"
/>
<CommonDialog
:dialogTitle=
"mode === 'viewDetail' ? '查看详情' : '更新数据'"
dialogWidth=
"80%"
:openDialog=
"viewDetailDialogFlag"
:showAction=
"false"
:showClose=
"true"
@
close=
"viewDetailDialogFlag = false"
@
confirm=
"handleUpdateSubmit"
>
<PolicyDetail
v-model=
"policyDetailFormData"
:policyBizId=
"selectedRow.policyBizId"
:mode=
"mode"
ref=
"policyDetailFormRef"
@
submit=
"onSubmit"
@
cancel=
"viewDetailDialogFlag = false"
v-if=
"viewDetailDialogFlag"
/>
</CommonDialog>
</div>
</template>
<
script
setup
>
import
{
ref
,
reactive
,
computed
,
watch
,
nextTick
}
from
'vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
CommonPage
from
'@/components/commonPage'
import
SearchForm
from
'@/components/SearchForm/SearchForm.vue'
import
CommonDialog
from
'@/components/commonDialog'
...
...
@@ -95,9 +145,13 @@ import {
getExpectedCommissionList
,
changePolicyStatus
,
policyFollowReport
,
saveMailingInfo
,
updatePolicyfollow
,
batchSaveBrokers
,
saveInitialPayment
,
updatePolicyProduct
saveMailingInfo
,
updatePolicyfollow
,
batchSaveBrokers
,
saveInitialPayment
,
updatePolicyProduct
}
from
'@/api/sign/underwritingMain'
import
{
copyToClipboard
}
from
'@/utils/copyToClipboard'
import
{
copyToClipboard
}
from
'@/utils/copyToClipboard'
import
PolicyDetail
from
'./policyDetail.vue'
const
policyDetailFormRef
=
ref
(
null
)
const
policyDetailFormData
=
ref
({})
...
...
@@ -108,7 +162,7 @@ const pageSize = ref(10)
const
pageTotal
=
ref
(
0
)
const
loading
=
ref
(
false
)
const
statusLoading
=
ref
(
false
)
// 搜索表单数据
// 搜索表单数据
const
searchFormData
=
reactive
({})
const
selectedRow
=
ref
(
null
)
// 弹窗相关
...
...
@@ -123,26 +177,27 @@ const editStatusFormConfig = ref([
prop
:
'status'
,
label
:
'新单状态'
,
dictType
:
'csf_policy_follow_status_new'
},
},
{
type
:
'date'
,
prop
:
'effectiveDate'
,
label
:
'保单生效日'
,
},
{
label
:
'保单生效日'
},
{
type
:
'date'
,
prop
:
'underwritingDate'
,
label
:
'保单核保日'
,
}
,
label
:
'保单核保日'
}
])
// 查看关联记录
const
viewRelatedDialogFlag
=
ref
(
false
)
const
relateRecordTableData
=
ref
([])
const
viewRelatedDetail
=
(
row
)
=>
{
const
viewRelatedDetail
=
row
=>
{
ElMessage
.
info
(
`查看关联记录详情:
${
JSON
.
stringify
(
row
)}
`
)
}
// 提交修改状态
const
handleEditStatusSubmit
=
async
()
=>
{
statusLoading
.
value
=
true
;
statusLoading
.
value
=
true
try
{
await
editStatusFormRef
.
value
.
validate
()
const
res
=
await
changePolicyStatus
({
...
...
@@ -150,16 +205,16 @@ const handleEditStatusSubmit = async () => {
...
editStatusFormData
.
value
})
if
(
res
.
code
===
200
)
{
statusLoading
.
value
=
false
;
statusLoading
.
value
=
false
ElMessage
.
success
(
'修改状态成功'
)
editStatusDialogFlag
.
value
=
false
loadTableData
()
}
else
{
statusLoading
.
value
=
false
;
statusLoading
.
value
=
false
ElMessage
.
error
(
res
.
msg
||
'修改状态失败'
)
}
}
catch
(
error
)
{
statusLoading
.
value
=
false
;
statusLoading
.
value
=
false
console
.
error
(
'修改状态失败'
,
error
)
}
}
...
...
@@ -167,7 +222,7 @@ const handleEditStatusSubmit = async () => {
// 查看详情、更新数据
const
viewDetailDialogFlag
=
ref
(
false
)
const
onSubmit
=
async
(
data
)
=>
{
const
onSubmit
=
async
data
=>
{
console
.
log
(
'提交的数据:'
,
data
)
// 调用 API 保存
// alert('提交成功!')
...
...
@@ -193,24 +248,26 @@ const onSubmit = async (data) => {
const
res
=
await
updatePolicyfollow
(
params
)
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
data
.
activeTab
===
'basic'
?
'保存基本信息成功'
:
'保存产品计划成功'
)
loadTableData
()
loadTableData
()
// viewDetailDialogFlag.value = false
}
else
{
ElMessage
.
error
(
res
.
msg
||
(
data
.
activeTab
===
'basic'
?
'保存基本信息失败'
:
'保存产品计划失败'
))
ElMessage
.
error
(
res
.
msg
||
(
data
.
activeTab
===
'basic'
?
'保存基本信息失败'
:
'保存产品计划失败'
)
)
}
}
else
if
(
data
.
activeTab
===
'productPlan'
)
{
params
=
{
policyBizId
:
selectedRow
.
value
.
policyBizId
,
apiProductPlanMainInfoDto
:
{...
data
},
apiProductPlanMainInfoDto
:
{
...
data
},
activeTab
:
undefined
}
const
res
=
await
updatePolicyProduct
(
params
)
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'保存产品计划成功'
)
loadTableData
()
loadTableData
()
// viewDetailDialogFlag.value = false
}
else
{
ElMessage
.
error
(
res
.
msg
||
(
'保存产品计划失败'
)
)
ElMessage
.
error
(
res
.
msg
||
'保存产品计划失败'
)
}
}
else
if
(
data
.
activeTab
===
'introducer'
)
{
params
=
{
...
...
@@ -225,8 +282,7 @@ const onSubmit = async (data) => {
}
else
{
ElMessage
.
error
(
res
.
msg
||
'保存转介人失败'
)
}
}
else
if
(
data
.
activeTab
===
'firstPayment'
)
{
}
else
if
(
data
.
activeTab
===
'firstPayment'
)
{
try
{
params
=
{
policyBizId
:
selectedRow
.
value
.
policyBizId
,
...
...
@@ -244,15 +300,13 @@ const onSubmit = async (data) => {
console
.
error
(
'首期缴费表单验证失败'
,
error
)
return
}
}
else
if
(
data
.
activeTab
===
'attachment'
){
viewDetailDialogFlag
.
value
=
false
}
else
if
(
data
.
activeTab
===
'attachment'
)
{
viewDetailDialogFlag
.
value
=
false
}
}
// 处理转介人数据格式
const
normalizeIntroducerData
=
(
data
)
=>
{
const
normalizeIntroducerData
=
data
=>
{
if
(
Array
.
isArray
(
data
))
return
data
if
(
data
&&
typeof
data
===
'object'
)
{
const
keys
=
Object
.
keys
(
data
).
filter
(
k
=>
/^
\d
+$/
.
test
(
k
))
...
...
@@ -310,11 +364,11 @@ const operationBtnList = ref([
])
// 分页事件
const
handleSizeChange
=
(
val
)
=>
{
const
handleSizeChange
=
val
=>
{
pageSize
.
value
=
val
loadTableData
()
}
const
handleCurrentChange
=
(
val
)
=>
{
const
handleCurrentChange
=
val
=>
{
currentPage
.
value
=
val
loadTableData
()
}
...
...
@@ -338,7 +392,8 @@ const searchConfig = ref([
type
:
'input'
,
prop
:
'appointmentNo'
,
label
:
'预约编号'
},
{
},
{
type
:
'daterange'
,
prop
:
'signDate'
,
label
:
'签单日'
,
...
...
@@ -364,10 +419,11 @@ const searchConfig = ref([
valueKey
:
'insuranceCompanyBizId'
,
labelKey
:
'fullName'
,
multiple
:
true
,
transform
:
(
res
)
=>
{
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'select'
,
prop
:
'productLaunchBizIdList'
,
label
:
'产品计划'
,
...
...
@@ -375,28 +431,50 @@ const searchConfig = ref([
keywordField
:
'productName'
,
requestParams
:
{
tenantBizId
:
userStore
.
projectInfo
.
tenantBizId
||
''
,
projectBizId
:
userStore
.
projectInfo
.
projectBizId
||
''
,
fieldBizId
:
'field_olk1qZe81qHHKXbw'
,
fieldValueBizId
:
'field_value_uOfJH5ucA2YwJpbn'
,
pageNo
:
1
,
pageSize
:
20
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
)
=>
{
transform
:
res
=>
{
return
res
?.
data
.
records
||
[]
}
},
{
},
{
type
:
'input'
,
prop
:
'issueNumber'
,
label
:
'缴费年期'
,
inputType
:
'decimal'
,
rules
:
[
{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}
]
rules
:
[{
pattern
:
/^
\d
+$/
,
message
:
'只能输入正整数'
,
trigger
:
'blur'
}]
},
{
type
:
'input'
,
prop
:
'policyHolder'
,
label
:
'投保人'
},
{
type
:
'input'
,
prop
:
'signer'
,
label
:
'签单员'
},
{
type
:
'input'
,
prop
:
'brokerName'
,
label
:
'转介人'
},
{
type
:
'input'
,
prop
:
'insured'
,
label
:
'受保人'
}
])
const
loadTableData
=
async
()
=>
{
loading
.
value
=
true
searchParams
.
value
=
searchFormRef
.
value
.
getFormData
()
||
{}
...
...
@@ -421,13 +499,12 @@ const loadTableData = async () => {
}
}
// 表格操作菜单
const
dropdownItems
=
[
{
label
:
'查看保单详情'
,
value
:
'viewDetail'
},
{
label
:
'补充保单信息'
,
value
:
'updateData'
},
{
label
:
'生成签单报告'
,
value
:
'generateReport'
},
{
label
:
'设置新单状态'
,
value
:
'setNewSingleStatus'
}
,
{
label
:
'设置新单状态'
,
value
:
'setNewSingleStatus'
}
// { label: '查看关联', value: 'viewRelated' },
// { label: '查看记录', value: 'viewRecord' },
]
...
...
@@ -449,15 +526,15 @@ const handleSelect = async (e, row) => {
viewDetailDialogFlag
.
value
=
true
break
case
'setNewSingleStatus'
:
if
(
selectedRow
.
value
.
status
===
'生效'
)
{
if
(
selectedRow
.
value
.
status
===
'生效'
)
{
ElMessage
.
warning
(
'保单已生效,不能更新新单状态'
)
return
}
editStatusDialogFlag
.
value
=
true
editStatusFormData
.
value
=
{
status
:
row
.
status
,
effectiveDate
:
row
.
effectiveDate
,
underwritingDate
:
row
.
underwritingDate
effectiveDate
:
row
.
effectiveDate
,
underwritingDate
:
row
.
underwritingDate
}
break
case
'viewRelated'
:
...
...
@@ -474,7 +551,7 @@ const handleSelect = async (e, row) => {
}
}
const
generateReport
=
async
(
row
)
=>
{
const
generateReport
=
async
row
=>
{
if
(
!
selectedRow
.
value
)
{
ElMessage
.
warning
(
'请选择要生成报告的新单'
)
return
...
...
@@ -483,14 +560,10 @@ const generateReport = async (row) => {
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'
)
await
safeDownload
(
response
,
fileName
,
'application/pdf;charset=utf-8'
)
if
(
res
.
code
===
200
)
{
ElMessage
.
success
(
'报告生成成功'
)
}
else
{
}
else
{
ElMessage
.
error
(
res
.
msg
||
'报告生成失败'
)
}
...
...
@@ -529,7 +602,7 @@ const saveMailingInfoapi = async () => {
mailingMethod
:
postalFormData
.
value
.
mailingMethod
,
deliveryNo
:
postalFormData
.
value
.
deliveryNo
,
brokerSignDate
:
postalFormData
.
value
.
brokerSignDate
,
customerSignDate
:
postalFormData
.
value
.
customerSignDate
,
customerSignDate
:
postalFormData
.
value
.
customerSignDate
}
const
res
=
await
savePostalInfo
(
params
)
if
(
res
.
code
===
200
)
{
...
...
@@ -540,16 +613,8 @@ const saveMailingInfoapi = async () => {
}
catch
(
error
)
{
console
.
error
(
'保存邮寄信息失败'
,
error
)
}
finally
{
}
}
</
script
>
<
style
scoped
></
style
>
\ No newline at end of file
<
style
scoped
></
style
>
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