Commit 8f8977d8 by Sweet Zhang

对接保单来佣和发佣

parent 35ccd9f3
......@@ -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
})
}
......@@ -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
<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
<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
{
"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
}
}
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
}
......@@ -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
......@@ -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, ',')
}
......@@ -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: 100
})
// 表格数据
......@@ -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') {
......
......@@ -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="currentPeriod" label="当前入账期数" min-width="100" align="center" />
<el-table-column prop="commissionPeriod" 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('/financialCenter/financial/billing')
} catch (error) {
console.error('生成失败:', error)
ElMessage.error('生成失败')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment