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
8f8977d8
Commit
8f8977d8
authored
Oct 11, 2025
by
Sweet Zhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
对接保单来佣和发佣
parent
35ccd9f3
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
573 additions
and
212 deletions
+573
-212
src/api/financial/commission.js
+15
-2
src/api/sign/underwritingMain.js
+20
-0
src/components/FileUpload/index.vue
+20
-12
src/components/PolicyDetailDialog/index.vue
+214
-0
src/utils/1.js
+0
-60
src/utils/2.js
+0
-0
src/utils/date.js
+8
-0
src/utils/generator/config.js
+3
-2
src/utils/index.js
+5
-0
src/views/financialCenter/financialBilling.vue
+68
-26
src/views/financialCenter/financialIncome.vue
+69
-12
src/views/sign/underwritingMain/index.vue
+151
-98
No files found.
src/api/financial/commission.js
View file @
8f8977d8
...
...
@@ -50,9 +50,10 @@ export function getPolicyFortuneList(data) {
export
function
downloadPolicyFortune
(
data
)
{
return
request
({
url
:
'/csf/api/fortune/download'
,
url
:
'/csf/api/fortune/download
/raw
'
,
method
:
'post'
,
data
:
data
data
:
data
,
responseType
:
'blob'
})
}
...
...
@@ -75,3 +76,15 @@ export function getReferrerFortuneList(data) {
data
:
data
})
}
// 删除来佣数据
// /csf/api/commission/delete
export
function
deletePolicyCommission
(
data
)
{
return
request
({
url
:
'/csf/api/commission/delete'
,
method
:
'post'
,
data
:
data
})
}
src/api/sign/underwritingMain.js
View file @
8f8977d8
...
...
@@ -7,4 +7,23 @@ export function getPolicyFollowList(data) {
method
:
'post'
,
data
:
data
})
}
// 获取预计来佣列表
// /csf/api/commission/list/page/commission_expected
export
function
getExpectedCommissionList
(
data
)
{
return
request
({
url
:
'/csf/api/policy/list/page/commission_expected'
,
method
:
'post'
,
data
:
data
})
}
// 更新至保单库
export
function
updateToPolicyLib
(
data
)
{
return
request
({
url
:
'/csf/api/policy_follow/addToPolicy'
,
method
:
'post'
,
data
:
data
})
}
\ No newline at end of file
src/components/FileUpload/index.vue
View file @
8f8977d8
<
template
>
<div
class=
"upload-file"
>
<el-upload
multiple
:multiple =
"multiple"
:action=
"uploadFileUrl"
:before-upload=
"handleBeforeUpload"
:file-list=
"fileList"
...
...
@@ -17,7 +17,7 @@
v-if=
"!disabled"
>
<!-- 上传按钮 -->
<el-button
size=
"
mini
"
type=
"primary"
>
{{
uploadBtnText
}}
</el-button>
<el-button
size=
"
small
"
type=
"primary"
>
{{
uploadBtnText
}}
</el-button>
<!-- 上传提示 -->
<div
class=
"el-upload__tip"
v-if=
"showTip"
>
请上传
...
...
@@ -98,6 +98,10 @@ export default {
drag
:
{
type
:
Boolean
,
default
:
true
},
multiple
:{
type
:
Boolean
,
default
:
true
}
},
data
()
{
...
...
@@ -116,14 +120,17 @@ export default {
if
(
this
.
drag
&&
!
this
.
disabled
)
{
this
.
$nextTick
(()
=>
{
const
element
=
this
.
$refs
.
uploadFileList
?.
$el
||
this
.
$refs
.
uploadFileList
Sortable
.
create
(
element
,
{
ghostClass
:
'file-upload-darg'
,
onEnd
:
(
evt
)
=>
{
const
movedItem
=
this
.
fileList
.
splice
(
evt
.
oldIndex
,
1
)[
0
]
this
.
fileList
.
splice
(
evt
.
newIndex
,
0
,
movedItem
)
this
.
$emit
(
"input"
,
this
.
listToString
(
this
.
fileList
))
}
})
// 添加元素存在性检查,防止undefined错误
if
(
element
)
{
Sortable
.
create
(
element
,
{
ghostClass
:
'file-upload-darg'
,
onEnd
:
(
evt
)
=>
{
const
movedItem
=
this
.
fileList
.
splice
(
evt
.
oldIndex
,
1
)[
0
]
this
.
fileList
.
splice
(
evt
.
newIndex
,
0
,
movedItem
)
this
.
$emit
(
"input"
,
this
.
listToString
(
this
.
fileList
))
}
})
}
})
}
},
...
...
@@ -224,7 +231,7 @@ export default {
}
this
.
uploadList
=
[]
this
.
number
=
0
this
.
$emit
(
"
input
"
,
this
.
uploadList
.
length
>
0
?
this
.
listToString
(
this
.
fileList
):
code
)
this
.
$emit
(
"
uploadEnd
"
,
this
.
uploadList
.
length
>
0
?
this
.
listToString
(
this
.
fileList
):
code
)
this
.
$modal
.
closeLoading
()
},
// 获取文件名称
...
...
@@ -275,4 +282,4 @@ export default {
.el-upload__tip
{
margin-left
:
10px
;
}
</
style
>
</
style
>
\ No newline at end of file
src/components/PolicyDetailDialog/index.vue
0 → 100644
View file @
8f8977d8
<
template
>
<el-dialog
:model-value=
"visible"
:title=
"title"
width=
"80%"
top=
"5vh"
:close-on-click-modal=
"false"
class=
"detail-dialog"
@
update:model-value=
"handleVisibleChange"
@
close=
"handleClose"
>
<el-tabs
v-model=
"activeTab"
class=
"detail-tabs"
>
<!-- 保单信息 -->
<el-tab-pane
label=
"保单信息"
name=
"policy"
>
<el-descriptions
:column=
"2"
border
>
<el-descriptions-item
label=
"保单号"
>
{{
detailData
.
policyNo
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"客户名称"
>
{{
detailData
.
customerName
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"签单日期"
>
{{
detailData
.
signDate
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"签单人"
>
{{
detailData
.
signer
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"供款年期"
>
{{
detailData
.
paymentTerm
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"产品名称"
>
{{
detailData
.
productName
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"保险公司"
>
{{
detailData
.
insurer
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"对账公司"
>
{{
detailData
.
reconciliationCompany
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"保单持有人"
>
{{
detailData
.
policyHolder
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"受保人"
>
{{
detailData
.
insured
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"币种"
>
{{
detailData
.
currency
||
'-'
}}
</el-descriptions-item>
<el-descriptions-item
label=
"首期保费"
>
{{
numberWithCommas
(
detailData
.
initialPremium
||
0
)
}}
</el-descriptions-item>
<el-descriptions-item
label=
"新单状态"
>
{{
convertStatusToDict
(
detailData
.
status
)
||
'-'
}}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<!-- 入账信息 -->
<el-tab-pane
label=
"入账信息"
name=
"income"
>
<el-table
:data=
"expectedCommissionList"
border
size=
"small"
>
<el-table-column
type=
"index"
width=
"30"
/>
<el-table-column
prop=
"reconciliationCompany"
label=
"对账公司"
align=
"center"
/>
<el-table-column
prop=
"commissionPeriod"
label=
"佣金期数"
align=
"center"
/>
<el-table-column
prop=
"totalPeriod"
label=
"总佣金期数"
align=
"center"
/>
<el-table-column
prop=
"commissionName"
label=
"来佣名称"
align=
"center"
/>
<!--
<el-table-column
prop=
"commissionType"
label=
"来佣类型"
align=
"center"
/>
-->
<el-table-column
prop=
"amount"
label=
"来佣金额"
align=
"center"
/>
<el-table-column
prop=
"currency"
label=
"币种"
align=
"center"
/>
<el-table-column
prop=
"commissionDate"
label=
"来佣日期"
align=
"center"
/>
<el-table-column
prop=
"commissionStatusLabel"
label=
"来佣状态"
align=
"center"
/>
<el-table-column
prop=
"remark"
label=
"备注"
align=
"center"
/>
<el-table-column
prop=
"creatorId"
label=
"创建人"
align=
"center"
/>
<el-table-column
prop=
"updaterId"
label=
"更新人"
align=
"center"
/>
<el-table-column
prop=
"createTime"
label=
"创建时间"
align=
"center"
/>
<el-table-column
prop=
"updateTime"
label=
"更新时间"
align=
"center"
/>
<!--
<template
#
append
>
<div
style=
"padding: 20px;display: flex;justify-content: end;"
>
<el-pagination
v-model:current-page=
"currentPage1"
:page-size=
"pageSize1"
background
layout=
"total, prev, pager, next"
:total=
"total1"
@
current-change=
"handleCurrentChange('expectedCommissionList')"
/>
</div>
</
template
>
-->
</el-table>
</el-tab-pane>
<!-- 出账信息 -->
<el-tab-pane
label=
"出账信息"
name=
"expense"
>
<el-descriptions
:column=
"2"
border
>
<el-descriptions-item
label=
"出账状态"
>
{{ detailData.expenseStatus || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"出账金额"
>
{{ numberWithCommas(detailData.expenseAmount || 0) }}
</el-descriptions-item>
<el-descriptions-item
label=
"出账日期"
>
{{ detailData.expenseDate || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"出账银行"
>
{{ detailData.expenseBank || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"出账账号"
>
{{ detailData.expenseAccount || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"出账凭证号"
>
{{ detailData.expenseVoucherNo || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"出账备注"
>
{{ detailData.expenseRemark || '-' }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<!-- 转介人信息 -->
<el-tab-pane
label=
"转介人信息"
name=
"broker"
>
<el-table
:data=
"detailData.brokerList"
border
size=
"small"
>
<el-table-column
prop=
"brokerName"
label=
"姓名"
align=
"center"
/>
<el-table-column
prop=
"team"
label=
"团队"
align=
"center"
/>
<el-table-column
prop=
"brokerRatio"
label=
"介绍费占比"
align=
"center"
/>
<el-table-column
prop=
"remark"
label=
"备注"
align=
"center"
/>
</el-table>
</el-tab-pane>
<!-- 其他信息 -->
<el-tab-pane
label=
"其他信息"
name=
"other"
>
<el-descriptions
:column=
"2"
border
>
<el-descriptions-item
label=
"创建时间"
>
{{ detailData.createTime || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"更新时间"
>
{{ detailData.updateTime || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"创建人"
>
{{ detailData.createBy || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"更新人"
>
{{ detailData.updateBy || '-' }}
</el-descriptions-item>
<el-descriptions-item
label=
"备注信息"
:span=
"2"
>
{{ detailData.remark || '-' }}
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
</el-tabs>
<
template
#
footer
>
<span
class=
"dialog-footer"
>
<el-button
@
click=
"handleClose"
>
关闭
</el-button>
</span>
</
template
>
</el-dialog>
</template>
<
script
setup
>
import
{
ref
,
watch
}
from
'vue'
import
{
numberWithCommas
}
from
'@/utils/index.js'
// 定义props
const
props
=
defineProps
({
visible
:
{
type
:
Boolean
,
default
:
false
},
detailData
:
{
type
:
Object
,
default
:
()
=>
({})
},
title
:
{
type
:
String
,
default
:
'数据详情'
},
policyFollowStatusList
:
{
type
:
Array
,
default
:
()
=>
[]
},
expectedCommissionList
:
{
type
:
Array
,
default
:
()
=>
[]
},
})
// 定义emits
const
emit
=
defineEmits
([
'update:visible'
,
'close'
,
'current-change'
])
// 响应式数据
const
activeTab
=
ref
(
'policy'
)
const
currentPage1
=
ref
(
1
)
const
total1
=
ref
(
1000
)
const
pageSize1
=
ref
(
100
)
// 监听visible变化
watch
(()
=>
props
.
visible
,
(
newVal
)
=>
{
if
(
newVal
)
{
activeTab
.
value
=
'policy'
}
})
// 处理visible变化
const
handleVisibleChange
=
(
value
)
=>
{
emit
(
'update:visible'
,
value
)
}
// 状态转换函数
const
convertStatusToDict
=
(
status
)
=>
{
const
dictItem
=
props
.
policyFollowStatusList
.
find
(
item
=>
item
.
itemValue
==
status
)
return
dictItem
?.
itemLabel
??
status
}
// 关闭弹窗
const
handleClose
=
()
=>
{
emit
(
'update:visible'
,
false
)
emit
(
'close'
)
}
// 表格分页当前页改变
const
handleCurrentChange
=
(
val
)
=>
{
console
.
log
(
`当前页:
${
val
}
`
)
emit
(
'current-change'
,
val
,
currentPage1
.
value
)
}
</
script
>
<
style
scoped
>
.detail-dialog
{
max-height
:
80vh
;
}
.detail-tabs
{
max-height
:
60vh
;
overflow-y
:
auto
;
}
.detail-tabs
.el-tab-pane
{
padding
:
20px
;
}
.broker-section
{
margin-top
:
20px
;
}
.broker-section
h4
{
margin-bottom
:
15px
;
color
:
#303133
;
font-weight
:
600
;
}
/* 响应式调整详情弹窗 */
@media
(
max-width
:
768px
)
{
.detail-dialog
{
width
:
95%
!important
;
}
.detail-tabs
.el-descriptions
{
font-size
:
12px
;
}
}
</
style
>
\ No newline at end of file
src/utils/1.js
deleted
100644 → 0
View file @
35ccd9f3
{
"id"
:
5
,
"fnaFormBizId"
:
"fna_form_8VXGgMskIU3uZWG7"
,
"customerBizId"
:
"customer_bkr6dz9BkYGar48o"
,
"personalData"
:
{
"accountName"
:
"user_1002"
,
"registrationNumber"
:
"11"
,
"number"
:
null
,
"customerName"
:
"11"
,
"taxCountry"
:
"11"
,
"employment"
:
"PRAT_TIME"
,
"otherEmployment"
:
null
,
"isRetired"
:
"1"
,
"retiredAge"
:
null
},
"familyMembers"
:
[
{
"type"
:
"1"
,
"needProvide"
:
"1"
,
"age"
:
"11"
},
{
"type"
:
"2"
,
"needProvide"
:
"1"
,
"age"
:
"11"
},
{
"type"
:
"3"
,
"needProvide"
:
"1"
,
"age"
:
"11"
},
{
"type"
:
"4"
,
"needProvide"
:
"1"
,
"age"
:
"11"
}
],
"existingSecurityOwner"
:
[],
"existingSecurityInsured"
:
[],
"incomeExpense"
:
{
"monthlyIncome"
:
null
,
"monthlyExpense"
:
null
},
"liquidAssets"
:
{
"liquidAssets"
:
null
,
"liquidAssetType"
:
null
,
"otherLiquidAsset"
:
null
},
"primaryResidence"
:
null
,
"investment"
:
null
,
"companyBusinessData"
:
{
"averageNetProfit"
:
null
,
"estimatedTotalAssets"
:
null
,
"currency"
:
null
,
"assetPercentage"
:
null
},
"other"
:
{
"premiumFundingSource"
:
null
}
}
src/utils/2.js
deleted
100644 → 0
View file @
35ccd9f3
src/utils/date.js
View file @
8f8977d8
import
dayjs
from
'dayjs'
import
{
de
}
from
'element-plus/es/locales.mjs'
export
function
formatIsoToDateTime
(
isoStr
)
{
// 处理 null/undefined 情况,避免报错
...
...
@@ -23,3 +24,10 @@ export const getNowTime = (format = DATE_TIME_FORMAT) => {
if
(
!
date
)
return
''
return
dayjs
().
format
(
format
)
}
export
default
{
formatIsoToDateTime
,
formatToDateTime
,
formatToDate
,
getNowTime
}
src/utils/generator/config.js
View file @
8f8977d8
...
...
@@ -378,7 +378,7 @@ export const selectComponents = [
'color-format'
:
''
,
disabled
:
false
,
required
:
true
,
size
:
'
default'
,
size
:
'
'
,
// 将 'default' 改为 '' 或 'small'
regList
:
[],
changeTag
:
true
,
document
:
'https://element-plus.org/zh-CN/component/color-picker'
,
...
...
@@ -449,4 +449,4 @@ export const trigger = {
'el-time-picker'
:
'change'
,
'el-date-picker'
:
'change'
,
'el-rate'
:
'change'
,
}
}
\ No newline at end of file
src/utils/index.js
View file @
8f8977d8
...
...
@@ -387,4 +387,9 @@ export function camelCase(str) {
export
function
isNumberStr
(
str
)
{
return
/^
[
+-
]?(
0|
([
1-9
]\d
*
))(\.\d
+
)?
$/g
.
test
(
str
)
}
// 数字千分位格式化,保留2位小数
export
function
numberWithCommas
(
x
,
fixed
=
2
)
{
return
x
.
toFixed
(
fixed
).
toString
().
replace
(
/
\B(?=(\d{3})
+
(?!\d))
/g
,
','
)
}
src/views/financialCenter/financialBilling.vue
View file @
8f8977d8
...
...
@@ -61,7 +61,6 @@
:uploadBtnText=
"'批量导入'"
@
input =
'getUploadFileFunc'
:responseType=
"'onlyStatus'"
/>
</el-col>
<el-col
:span=
"12"
style=
"text-align: right;"
>
...
...
@@ -76,8 +75,19 @@
</el-row>
</el-card>
<!-- 数据表格 -->
<el-card>
<!-- 增加勾选后下载按钮 -->
<el-col
:span=
"24"
style=
"text-align: right;"
v-if=
"selectedRows.length > 0"
>
<el-button
type=
"primary"
@
click=
"downloadSelected"
>
下载选中项
</el-button>
</el-col>
<el-table
:data=
"tableData"
@
selection-change=
"handleSelectionChange"
...
...
@@ -206,7 +216,7 @@ const queryParams = reactive({
company
:
''
,
billingDate
:
[],
pageNum
:
1
,
pageSize
:
10
pageSize
:
10
0
})
// 表格数据
...
...
@@ -238,7 +248,42 @@ const companyOptions = [
{
label
:
'公司B'
,
value
:
'company_b'
},
{
label
:
'公司C'
,
value
:
'company_c'
}
]
// 下载选中项
const
downloadSelected
=
async
()
=>
{
if
(
selectedRows
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请选择要下载的项'
)
return
}
try
{
// API调用
const
response
=
await
downloadPolicyFortune
({
fortuneBizIdList
:
selectedRows
.
value
.
map
(
row
=>
row
.
fortuneBizId
)
})
if
(
response
)
{
ElMessage
.
success
(
'下载成功'
)
// 触发文件下载
// 处理下载响应
const
blob
=
response
instanceof
Blob
?
response
:
new
Blob
([
response
],
{
type
:
'application/vnd.ms-excel;charset=utf-8'
})
// 创建Blob对象,指定正确的MIME类型
const
url
=
window
.
URL
.
createObjectURL
(
blob
)
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
url
// 不需要指定文件名,浏览器会自动使用默认文件名
link
.
download
=
`出账管理_
${
new
Date
().
getTime
()}
.xlsx`
document
.
body
.
appendChild
(
link
)
link
.
click
()
document
.
body
.
removeChild
(
link
)
window
.
URL
.
revokeObjectURL
(
url
)
}
else
{
ElMessage
.
error
(
'下载失败'
)
}
}
catch
(
error
)
{
ElMessage
.
error
(
'下载失败'
)
}
}
const
getUploadFileFunc
=
(
data
)
=>
{
console
.
log
(
data
)
if
(
data
===
200
){
ElMessage
.
success
(
'上传成功'
);
getList
()
...
...
@@ -333,7 +378,7 @@ const handleView = (row) => {
}
const
generateBillingList
=
()
=>
{
const
generateBillingList
=
async
()
=>
{
if
(
selectedRows
.
value
.
length
===
0
)
{
ElMessage
.
warning
(
'请先选择要生成清单的记录'
)
return
...
...
@@ -344,32 +389,29 @@ const generateBillingList = () => {
{
type
:
'warning'
}
).
then
(()
=>
{
).
then
(
async
()
=>
{
console
.
log
(
'开始生成出账清单'
)
// 调用下载API
downloadPolicyFortuneAccount
({
const
response
=
await
downloadPolicyFortuneAccount
({
fortuneBizIdList
:
selectedRows
.
value
.
map
(
item
=>
item
.
fortuneBizId
)
}).
then
((
res
)
=>
{
console
.
log
(
res
)
if
(
res
){
// 处理下载响应
const
blob
=
res
instanceof
Blob
?
res
:
new
Blob
([
res
],
{
type
:
'application/vnd.ms-excel;charset=utf-8'
})
// 创建Blob对象,指定正确的MIME类型
const
url
=
window
.
URL
.
createObjectURL
(
blob
)
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
url
// 不需要指定文件名,浏览器会自动使用默认文件名
link
.
download
=
`出账清单_
${
new
Date
().
getTime
()}
.xlsx`
document
.
body
.
appendChild
(
link
)
link
.
click
()
document
.
body
.
removeChild
(
link
)
window
.
URL
.
revokeObjectURL
(
url
)
}
else
{
ElMessage
.
error
(
'下载失败'
)
}
})
console
.
log
(
response
)
// 调用下载API
if
(
response
){
// 处理下载响应
const
blob
=
response
instanceof
Blob
?
response
:
new
Blob
([
response
],
{
type
:
'application/vnd.ms-excel;charset=utf-8'
})
// 创建Blob对象,指定正确的MIME类型
const
url
=
window
.
URL
.
createObjectURL
(
blob
)
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
url
// 不需要指定文件名,浏览器会自动使用默认文件名
link
.
download
=
`出账清单_
${
new
Date
().
getTime
()}
.xlsx`
document
.
body
.
appendChild
(
link
)
link
.
click
()
document
.
body
.
removeChild
(
link
)
window
.
URL
.
revokeObjectURL
(
url
)
}
else
{
ElMessage
.
error
(
'下载失败'
)
}
selectedRows
.
value
=
[]
}).
catch
((
error
)
=>
{
if
(
error
!==
'cancel'
)
{
...
...
src/views/financialCenter/financialIncome.vue
View file @
8f8977d8
...
...
@@ -53,7 +53,7 @@
<div
class=
"import-actions"
>
<FileUpload
:fileType=
"['xlsx', 'xls']"
:action=
"'/csf/api/commission/upload/excel'"
@
input
=
'getUploadFileFunc'
@
uploadEnd
=
'getUploadFileFunc'
:responseType=
"'onlyStatus'"
/>
...
...
@@ -74,16 +74,22 @@
border
style=
"width: 100%"
@
selection-change=
"handleSelectionChange"
@
sort-change=
"handleSortChange"
>
<el-table-column
type=
"selection"
width=
"55"
align=
"center"
/>
<el-table-column
prop=
"policyNo"
label=
"保单号"
min-width=
"120"
align=
"center"
/>
<el-table-column
prop=
"reconciliationCompany"
label=
"对账公司"
min-width=
"120"
align=
"center"
/>
<el-table-column
prop=
"c
urrent
Period"
label=
"当前入账期数"
min-width=
"100"
align=
"center"
/>
<el-table-column
prop=
"c
ommission
Period"
label=
"当前入账期数"
min-width=
"100"
align=
"center"
/>
<el-table-column
prop=
"totalPeriod"
label=
"预计总期数"
min-width=
"100"
align=
"center"
/>
<el-table-column
prop=
"commissionName"
label=
"入账项目"
min-width=
"120"
align=
"center"
/>
<el-table-column
prop=
"amount"
label=
"入账金额"
min-width=
"100"
align=
"center"
/>
<el-table-column
prop=
"currency"
label=
"入账币种"
min-width=
"80"
align=
"center"
/>
<el-table-column
prop=
"commissionDate"
label=
"入账日期"
min-width=
"120"
align=
"center"
/>
<el-table-column
prop=
"status"
label=
"比对状态"
min-width=
"100"
align=
"center"
>
<template
#
default=
"scope"
>
<span>
{{
convertStatusToDict
(
scope
.
row
.
status
)
}}
</span>
</
template
>
</el-table-column>
>
<el-table-column
prop=
"remark"
label=
"备注"
min-width=
"150"
align=
"center"
show-overflow-tooltip
/>
<el-table-column
label=
"操作"
width=
"180"
align=
"center"
fixed=
"right"
>
<
template
#
default=
"scope"
>
...
...
@@ -217,7 +223,43 @@ import * as XLSX from 'xlsx'
import
{
getPolicyCommissionList
,
downloadPolicyFortune
,
generateCommissionRecord
,
updatePolicyCommission
}
from
"@/api/financial/commission"
import
FileUpload
from
"@/components/FileUpload/index"
import
{
useRouter
}
from
'vue-router'
const
router
=
useRouter
()
import
{
listType
}
from
'@/api/system/dict/type'
// 通过dictType=csf_commission_status获取比对状态字典值,获取对象中的dictItemList
const
dictLists
=
ref
([]);
const
getLists
=
()
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
listType
({
typeList
:
[
'csf_commission_status'
]}).
then
(
res
=>
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
dictData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'csf_commission_status'
);
dictLists
.
value
=
dictData
?.
dictItemList
||
[];
console
.
log
(
'获取到的字典数据:'
,
dictLists
.
value
);
resolve
(
dictLists
.
value
);
}
else
{
dictLists
.
value
=
[];
resolve
([]);
}
}).
catch
(
error
=>
{
console
.
error
(
'获取状态列表失败:'
,
error
);
dictLists
.
value
=
[];
reject
(
error
);
});
});
}
// 返回数据中状态需要转换为字典值
const
convertStatusToDict
=
(
status
)
=>
{
const
dictItem
=
dictLists
.
value
.
find
(
item
=>
item
.
itemValue
==
status
);
return
dictItem
?.
itemLabel
??
status
;
}
// 增加通过表格排序,排序字段sortField,升降序sortOrder
const
handleSortChange
=
(
column
)
=>
{
pagination
.
sortField
=
column
.
prop
pagination
.
sortOrder
=
column
.
order
===
'ascending'
?
'ascend'
:
'descend'
fetchTableData
()
}
// 搜索表单数据
const
searchForm
=
reactive
({
...
...
@@ -249,13 +291,19 @@ const pagination = reactive({
const
selectedFile
=
ref
(
null
)
const
importLoading
=
ref
(
false
)
// 页面加载时获取数据
onMounted
(()
=>
{
fetchTableData
()
// 获取字典值后,再调用接口获取来佣列表
initialData
();
})
const
initialData
=
async
()
=>
{
await
getLists
();
fetchTableData
();
}
const
getUploadFileFunc
=
(
data
)
=>
{
console
.
log
(
data
)
if
(
data
===
200
){
ElMessage
.
success
(
'上传成功'
);
fetchTableData
()
...
...
@@ -350,7 +398,7 @@ const handleAdd = () => {
ElMessage
.
info
(
'打开新增入账对话框'
)
}
import
{
deletePolicyCommission
}
from
'@/api/financial/commission'
// 删除
const
handleDelete
=
(
row
)
=>
{
ElMessageBox
.
confirm
(
...
...
@@ -362,10 +410,19 @@ const handleDelete = (row) => {
type
:
'warning'
}
).
then
(()
=>
{
ElMessage
.
success
(
'删除成功'
)
fetchTableData
()
}).
catch
(()
=>
{
ElMessage
.
info
(
'已取消删除'
)
// 调用删除接口
deletePolicyCommission
({
commissionBizId
:
row
.
commissionBizId
}).
then
((
res
)
=>
{
if
(
res
.
code
===
200
){
ElMessage
.
success
(
'删除成功'
)
fetchTableData
()
}
else
{
ElMessage
.
error
(
'删除失败'
)
}
}).
catch
(()
=>
{
ElMessage
.
error
(
'删除失败'
)
})
})
}
...
...
@@ -381,9 +438,9 @@ const handleGenerateBilling = async () => {
await
generateCommissionRecord
({
commissionBizIdList
:
selectedRows
.
value
.
map
(
row
=>
row
.
commissionBizId
)
})
ElMessage
.
success
(
'生成成功
,正在前往出账管理页面
'
)
ElMessage
.
success
(
'生成成功'
)
// 这里可以添加路由跳转到 financialBilling 组件
// router.push('/financial/billing')
// router.push('/financial
Center/financial
/billing')
}
catch
(
error
)
{
console
.
error
(
'生成失败:'
,
error
)
ElMessage
.
error
(
'生成失败'
)
...
...
src/views/sign/underwritingMain/index.vue
View file @
8f8977d8
...
...
@@ -4,18 +4,18 @@
<el-card
class=
"search-card"
>
<!-- 第一行筛选条件 -->
<el-row
:gutter=
"20"
class=
"search-row"
>
<el-col
:span=
"8"
>
<
!--
<
el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
新单编号
</label>
<el-input
v-model=
"searchForm.newOrderNo"
placeholder=
"请输入"
clearable
size=
"
medium
"
size=
"
default
"
@
keyup
.
enter=
"handleSearch"
/>
</div>
</el-col>
</el-col>
-->
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
保单号
</label>
...
...
@@ -23,7 +23,7 @@
v-model=
"searchForm.policyNo"
placeholder=
"请输入"
clearable
size=
"
medium
"
size=
"
default
"
@
keyup
.
enter=
"handleSearch"
/>
</div>
...
...
@@ -35,11 +35,26 @@
v-model=
"searchForm.customerName"
placeholder=
"请输入"
clearable
size=
"
medium
"
size=
"
default
"
@
keyup
.
enter=
"handleSearch"
/>
</div>
</el-col>
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
新单状态
</label>
<el-select
v-model=
"searchForm.newOrderStatus"
placeholder=
"请选择"
clearable
size=
"default"
>
<!-- 增加全部,默认传空字符串 -->
<el-option
label=
"全部"
value=
" "
/>
<el-option
v-for=
"item in policyFollowStatusList"
:key=
"item.itemValue"
:label=
"item.itemLabel"
:value=
"item.itemValue"
/>
</el-select>
</div>
</el-col>
</el-row>
<!-- 第二行筛选条件 -->
...
...
@@ -53,32 +68,15 @@
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
size=
"
medium
"
size=
"
default
"
/>
</div>
</el-col>
<el-col
:span=
"8"
>
<div
class=
"form-item"
>
<label
class=
"form-label"
>
新单状态
</label>
<el-select
v-model=
"searchForm.newOrderStatus"
placeholder=
"请选择"
clearable
size=
"medium"
>
<!-- 增加全部,默认传空字符串 -->
<el-option
label=
"全部"
value=
" "
/>
<el-option
v-for=
"item in policyFollowStatusList"
:key=
"item.itemValue"
:label=
"item.itemLabel"
:value=
"item.itemValue"
/>
</el-select>
</div>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"24"
class=
"search-buttons"
>
<el-col
:span=
"8"
class=
"search-buttons"
>
<el-button
type=
"primary"
@
click=
"handleSearch"
size=
"
medium
"
size=
"
default
"
:icon=
"Search"
class=
"search-btn"
>
...
...
@@ -86,7 +84,7 @@
</el-button>
<el-button
@
click=
"resetForm"
size=
"
medium
"
size=
"
default
"
:icon=
"RefreshLeft"
>
重置
...
...
@@ -94,13 +92,14 @@
<!--
<el-button
type=
"info"
@
click=
"toggleAdvancedSearch"
size=
"
medium
"
size=
"
default
"
:icon=
"expandSearch ? ArrowUp : ArrowDown"
>
{{
expandSearch
?
'收起筛选'
:
'更多筛选'
}}
</el-button>
-->
</el-col>
</el-row>
<!-- 可展开的高级筛选区域 -->
<el-collapse
v-model=
"activeNames"
v-if=
"expandSearch"
class=
"advanced-search"
>
...
...
@@ -113,7 +112,7 @@
v-model=
"searchForm.productType"
placeholder=
"请选择"
clearable
size=
"
small
"
size=
"
default
"
>
<el-option
label=
"全部"
value=
""
/>
<el-option
label=
"寿险"
value=
"life"
/>
...
...
@@ -130,7 +129,7 @@
v-model=
"searchForm.salesman"
placeholder=
"请选择"
clearable
size=
"
small
"
size=
"
default
"
>
<el-option
label=
"全部"
value=
""
/>
<el-option
label=
"张三"
value=
"zhangsan"
/>
...
...
@@ -146,7 +145,7 @@
v-model=
"searchForm.premium"
placeholder=
"请输入"
clearable
size=
"
small
"
size=
"
default
"
/>
</div>
</el-col>
...
...
@@ -170,7 +169,7 @@
<el-button
type=
"success"
:icon=
"UploadFilled"
size=
"
medium
"
size=
"
default
"
>
上传Excel文件
</el-button>
...
...
@@ -178,7 +177,7 @@
<el-button
text
@
click=
"downloadTemplate"
size=
"
small
"
size=
"
default
"
class=
"download-template-btn"
>
下载模板
...
...
@@ -195,7 +194,7 @@
<el-button
type=
"primary"
@
click=
"handleImport"
size=
"
medium
"
size=
"
default
"
:loading=
"importLoading"
class=
"confirm-import-btn"
>
...
...
@@ -208,11 +207,12 @@
<!-- 列表区域 -->
<el-card
class=
"table-card"
>
<!--
<div
class=
"table-actions"
>
<el-button
<div
class=
"table-actions"
>
<el-button
type=
"primary"
@
click=
"handleUpdateToPolicyLib"
>
更新至保单库
</el-button>
<!--
<el-button
type=
"danger"
:icon=
"Delete"
size=
"
small
"
size=
"
default
"
@
click=
"handleDeleteSelected"
:disabled=
"selectedRows.length === 0"
>
...
...
@@ -221,12 +221,12 @@
<el-button
type=
"primary"
:icon=
"Plus"
size=
"
small
"
size=
"
default
"
@
click=
"handleAdd"
>
新增
</el-button>
</div>
-->
</el-button>
-->
</div>
<el-table
v-loading=
"tableLoading"
:data=
"tableData"
...
...
@@ -241,7 +241,7 @@
<!-- 新单状态需要通过policyFollowStatusList和value匹配,显示label -->
<el-table-column
prop=
"status"
label=
"新单状态"
min-width=
"100"
align=
"center"
sortable
>
<template
#
default=
"scope"
>
<span>
{{
convertStatusToDict
(
scope
.
row
.
status
)
}}
</span>
<span>
{{
convertStatusToDict
(
1
,
scope
.
row
.
status
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
prop=
"policyNo"
label=
"保单号"
min-width=
"100"
align=
"center"
sortable
/>
...
...
@@ -249,47 +249,18 @@
<el-table-column
prop=
"signDate"
label=
"签单日期"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"signer"
label=
"签单人"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"paymentTerm"
label=
"供款年期"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"paymentPremium"
label=
"期交保费"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"productName"
label=
"产品名称"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"insurer
"
label=
"保险公司"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"insurer"
label=
"保险公司"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"reconciliationCompany"
label=
"对账公司"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"policyHolder"
label=
"保单持有人"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"insured"
label=
"受保人"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"currency"
label=
"币种"
min-width=
"100"
align=
"center"
sortable
/>
<el-table-column
prop=
"initialPremium"
label=
"首期保费"
min-width=
"100"
align=
"center"
sortable
/>
<!-- 转介人信息列 -->
<el-table-column
label=
"转介人信息"
min-width=
"150"
align=
"center"
sortable
>
<el-table-column
prop=
"initialPremium"
label=
"首期保费"
min-width=
"100"
align=
"center"
sortable
>
<
template
#
default=
"scope"
>
<div
v-if=
"scope.row.brokerList && scope.row.brokerList.length > 0"
>
<el-popover
placement=
"top-start"
title=
"转介人详情"
:width=
"300"
trigger=
"hover"
>
<template
#
reference
>
<el-button
text
size=
"small"
type=
"primary"
>
查看转介人(
{{
scope
.
row
.
brokerList
.
length
}}
)
</el-button>
</
template
>
<div
class=
"broker-details"
>
<div
v-for=
"(broker, index) in scope.row.brokerList"
:key=
"index"
class=
"broker-item"
>
<p><strong>
姓名:
</strong>
{{ broker.brokerName || '未填写' }}
</p>
<p><strong>
团队:
</strong>
{{ broker.team || '未填写' }}
</p>
<p><strong>
备注:
</strong>
{{ broker.remark || '无' }}
</p>
<el-divider
v-if=
"index < scope.row.brokerList.length - 1"
/>
</div>
</div>
</el-popover>
</div>
<span
v-else
class=
"no-broker"
>
无转介人
</span>
{{
numberWithCommas
(
scope
.
row
.
initialPremium
)
}}
</
template
>
</el-table-column>
<
!-- <
el-table-column
<el-table-column
label=
"操作"
min-width=
"180"
align=
"center"
...
...
@@ -297,29 +268,21 @@
<
template
#
default=
"scope"
>
<el-button
text
size="
small
"
size=
"
default
"
@
click=
"handleView(scope.row)"
>
查看
</el-button>
<el-button
text
size="
small
"
size=
"
default
"
type=
"primary"
@
click=
"handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
text
size="small"
type="danger"
@click="handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
-->
</el-table-column>
</el-table>
<!-- 分页 -->
...
...
@@ -335,7 +298,18 @@
/>
</div>
</el-card>
<!-- 使用查看数据详情组件 -->
<PolicyDetailDialog
:visible=
"viewDialogVisible"
:detail-data=
"currentRow"
:policy-follow-status-list=
"policyFollowStatusList"
title=
"新单跟进详情"
:expected-commission-list=
"expectedCommissionList"
@
close=
"handleDetailClose"
/>
</div>
</template>
<
script
setup
>
...
...
@@ -344,19 +318,26 @@ import { Search, RefreshLeft, UploadFilled, Delete, Plus, Document } from '@elem
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
*
as
XLSX
from
'xlsx'
import
axios
from
'axios'
import
{
getPolicyFollowList
}
from
'@/api/sign/underwritingMain'
import
{
getPolicyFollowList
,
getExpectedCommissionList
}
from
'@/api/sign/underwritingMain'
import
{
getToken
}
from
"@/utils/auth"
import
{
listType
}
from
'@/api/system/dict/type'
import
date
from
'@/utils/date'
import
PolicyDetailDialog
from
'@/components/PolicyDetailDialog/index.vue'
import
{
numberWithCommas
}
from
'@/utils/index.js'
// 通过dictType=csf_policy_follow_status获取新单状态字典值,获取对象中的dictItemList
const
policyFollowStatusList
=
ref
([]);
const
commissionStatusList
=
ref
([]);
const
getLists
=
()
=>
{
listType
({
typeList
:
[
'csf_policy_follow_status'
]}).
then
(
res
=>
{
listType
({
typeList
:
[
'csf_policy_follow_status'
,
'csf_expected_commission_status'
]}).
then
(
res
=>
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
statusData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'csf_policy_follow_status'
);
policyFollowStatusList
.
value
=
statusData
?.
dictItemList
||
[];
const
commissionStatusData
=
res
.
data
.
find
(
item
=>
item
.
dictType
===
'csf_expected_commission_status'
);
commissionStatusList
.
value
=
commissionStatusData
?.
dictItemList
||
[];
}
else
{
policyFollowStatusList
.
value
=
[];
commissionStatusList
.
value
=
[];
}
}).
catch
(
error
=>
{
console
.
error
(
'获取状态列表失败:'
,
error
);
...
...
@@ -364,8 +345,9 @@ const getLists = ()=>{
})
}
// 返回数据中状态需要转换为字典值
const
convertStatusToDict
=
(
status
)
=>
{
const
dictItem
=
policyFollowStatusList
.
value
.
find
(
item
=>
item
.
status
===
status
)
const
convertStatusToDict
=
(
type
=
1
,
status
)
=>
{
const
arr
=
type
===
1
?
policyFollowStatusList
:
commissionStatusList
const
dictItem
=
arr
.
value
.
find
(
item
=>
item
.
itemValue
==
status
)
return
dictItem
?.
itemLabel
??
status
}
...
...
@@ -392,12 +374,16 @@ const toggleAdvancedSearch = () => {
expandSearch
.
value
=
!
expandSearch
.
value
}
// 预计来佣列表
const
expectedCommissionList
=
ref
([])
// 表格数据
const
tableData
=
ref
([])
const
tableLoading
=
ref
(
false
)
const
selectedRows
=
ref
([])
// 查看详情弹窗相关
const
viewDialogVisible
=
ref
(
false
)
const
currentRow
=
ref
({})
// 分页数据
const
pagination
=
reactive
({
currentPage
:
1
,
// 当前页码(对应接口的pageNo)
...
...
@@ -406,6 +392,21 @@ const pagination = reactive({
sortField
:
''
,
// 排序字段
sortOrder
:
''
// 排序方向
})
// 处理查看
const
handleView
=
async
(
row
)
=>
{
console
.
log
(
'查看详情:'
,
row
)
currentRow
.
value
=
{
...
row
}
viewDialogVisible
.
value
=
true
fetchExpectedCommissionList
(
row
.
policyNo
)
}
// 处理详情弹窗关闭
const
handleDetailClose
=
()
=>
{
viewDialogVisible
.
value
=
false
console
.
log
(
'详情弹窗已关闭'
)
}
// Excel导入相关
const
selectedFile
=
ref
(
null
)
const
importLoading
=
ref
(
false
)
...
...
@@ -436,8 +437,8 @@ const fetchTableData = async () => {
// 签单时间范围需要根据后端要求的参数名进行调整
// 例如:如果后端需要startSignDate和endSignDate
...(
searchForm
.
signDateRange
&&
searchForm
.
signDateRange
.
length
===
2
&&
{
startSignDate
:
searchForm
.
signDateRange
[
0
]
,
endSignDate
:
searchForm
.
signDateRange
[
1
]
startSignDate
:
date
.
formatToDate
(
searchForm
.
signDateRange
[
0
])
+
' 00:00:00'
,
endSignDate
:
date
.
formatToDate
(
searchForm
.
signDateRange
[
1
])
+
' 23:59:59'
})
}
...
...
@@ -450,7 +451,7 @@ const fetchTableData = async () => {
tableData
.
value
=
result
.
records
.
map
(
record
=>
({
...
record
}))
console
.
log
(
'tableData'
,
tableData
.
value
)
//
console.log('tableData',tableData.value)
// 更新分页信息
pagination
.
total
=
result
.
total
...
...
@@ -471,8 +472,42 @@ const fetchTableData = async () => {
}
finally
{
tableLoading
.
value
=
false
}
}
// 获取预计来佣列表
const
fetchExpectedCommissionList
=
async
(
policyNo
,
pageNo
=
1
,
pageSize
=
100
)
=>
{
try
{
// 构造接口请求参数
const
params
=
{
pageNo
:
pageNo
,
// 注意:如果后端是从0开始的页码,需要减1
pageSize
:
pageSize
,
policyNo
:
policyNo
,
}
// 调用后台接口
const
response
=
await
getExpectedCommissionList
(
params
)
// 处理接口响应
if
(
response
.
code
===
200
)
{
const
result
=
response
.
data
// 将接口返回的数据映射到表格
expectedCommissionList
.
value
=
result
.
records
.
map
(
record
=>
({
...
record
,
commissionStatusLabel
:
convertStatusToDict
(
2
,
record
.
status
)
}))
}
else
{
// 接口返回错误信息
ElMessage
.
error
(
`获取数据失败:
${
response
.
data
.
msg
||
'未知错误'
}
`
)
expectedCommissionList
.
value
=
[]
}
}
catch
(
error
)
{
// 捕获网络或其他异常
console
.
error
(
'请求失败:'
,
error
)
ElMessage
.
error
(
'网络异常,请稍后重试'
)
expectedCommissionList
.
value
=
[]
}
finally
{
}
}
// 增加通过表格排序,排序字段sortField,升降序sortOrder
const
handleSortChange
=
(
column
)
=>
{
pagination
.
sortField
=
column
.
prop
...
...
@@ -652,12 +687,30 @@ const downloadTemplate = () => {
// ElMessage.info(`编辑 ID: ${row.id} 的数据`)
// // 实际项目中这里会打开编辑数据的对话框
// }
// 处理查看
// const handleView = (row) => {
// ElMessage.info(`查看 ID: ${row.id} 的数据详情`)
// // 实际项目中这里会打开查看数据详情的对话框
// }
import
{
updateToPolicyLib
}
from
'@/api/sign/underwritingMain'
// 处理更新至保单库
const
handleUpdateToPolicyLib
=
()
=>
{
ElMessageBox
.
confirm
(
`确定要更新选中的
${
selectedRows
.
value
.
length
}
条数据至保单库吗?`
,
'更新确认'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
}
).
then
(()
=>
{
// 调用更新至保单库接口
updateToPolicyLib
({
policyNoList
:
selectedRows
.
value
.
map
(
row
=>
row
.
policyNo
).
join
(
','
)
}).
then
(
response
=>
{
if
(
response
.
code
===
200
)
{
ElMessage
.
success
(
'更新成功'
)
}
else
{
ElMessage
.
error
(
`更新失败:
${
response
.
msg
||
'未知错误'
}
`
)
}
})
})
}
// 格式化文件大小
...
...
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