Commit 4f4b0e06 by Sweet Zhang

出入账管理第一阶段完成

parent 5f1a210e
......@@ -97,4 +97,26 @@ export function updatePolicyFortuneStatus(data) {
})
}
// 完成出账
// /csf/api/fortune/complete
export function completePolicyFortune(data) {
return request({
url: '/csf/api/fortune/complete/fortuneAccount',
method: 'post',
data: data
})
}
// 获取对账公司
// /csf/api/reconciliation_company/list/page
export function getReconciliationCompanyList(data) {
return request({
url: '/csf/api/reconciliation_company/list/page',
method: 'post',
data: data
})
}
......@@ -17,7 +17,7 @@
v-if="!disabled"
>
<!-- 上传按钮 -->
<el-button size="small" type="primary">{{ uploadBtnText }}</el-button>
<el-button size="default" type="primary" :disabled="isDisabled">{{ uploadBtnText }}</el-button>
<!-- 上传提示 -->
<div class="el-upload__tip" v-if="showTip">
请上传
......@@ -102,7 +102,12 @@ export default {
multiple:{
type: Boolean,
default: true
}
},
// 禁用上传按钮
isDisabled: {
type: Boolean,
default: false
},
},
data() {
return {
......
......@@ -64,15 +64,19 @@
<!-- 出账信息 -->
<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-table :data="policyFortuneList" border size="small">
<el-table-column type="index" width="30" />
<el-table-column prop="fortunePeriod" label="佣金期数" align="center" />
<el-table-column prop="fortuneTotalPeriod" label="总佣金期数" align="center" />
<el-table-column prop="broker" label="转介人" align="center" />
<el-table-column prop="team" label="所属团队" align="center" />
<el-table-column prop="fortuneName" label="出账名称" align="center" />
<el-table-column prop="amount" label="金额" align="center" />
<el-table-column prop="currency" label="币种" align="center" />
<el-table-column prop="payoutDate" label="出账日期" align="center" />
<el-table-column prop="fortuneStatusLabel" label="出账状态" align="center" />
<el-table-column prop="remark" label="备注" align="center" />
</el-table>
</el-tab-pane>
<!-- 转介人信息 -->
<el-tab-pane label="转介人信息" name="broker">
......@@ -85,7 +89,7 @@
</el-tab-pane>
<!-- 其他信息 -->
<el-tab-pane label="其他信息" name="other">
<!-- <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>
......@@ -93,7 +97,7 @@
<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-tab-pane> -->
</el-tabs>
<template #footer>
......@@ -130,6 +134,10 @@ const props = defineProps({
type: Array,
default: () => []
},
policyFortuneList: {
type: Array,
default: () => []
},
})
// 定义emits
......
......@@ -14,22 +14,6 @@
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="对账公司">
<el-select
v-model="queryParams.company"
placeholder="请选择对账公司"
clearable
>
<el-option
v-for="item in companyOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="出账日期">
<el-date-picker
v-model="queryParams.billingDate"
......@@ -51,19 +35,27 @@
</el-form>
</el-card>
<!-- 操作区域 -->
<el-card class="operation-card">
<el-row :gutter="10">
<el-col :span="12">
<!-- <el-button type="primary" @click="handleCreate">新建出账记录</el-button> -->
<!-- 数据表格 -->
<el-card>
<el-row :gutter="20">
<el-text class="mx-1" type="danger" style="margin-right: 20px;">勾选出账记录,点击“下载选中项”按钮,下载导入模版</el-text>
</el-row>
<div class="button-row" style="display: flex;gap: 1rem;justify-content: end;">
<el-button
type="primary"
:disabled="selectedRows.length === 0"
@click="downloadSelected"
>
下载选中项
</el-button>
<FileUpload :fileType="['xlsx', 'xls']"
:action="'/csf/api/fortune/upload/excel'"
:uploadBtnText="'批量导入'"
@input = 'getUploadFileFunc'
:isShowTip="false"
@uploadEnd = 'getUploadFileFunc'
:responseType="'onlyStatus'"
/>
</el-col>
<el-col :span="12" style="text-align: right;">
<el-button
type="success"
:disabled="selectedRows.length === 0"
......@@ -71,23 +63,7 @@
>
生成出账清单
</el-button>
</el-col>
</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>
</div>
<el-table
:data="tableData"
@selection-change="handleSelectionChange"
......@@ -109,7 +85,7 @@
<el-table-column prop="status" label="出账状态" width="100">
<template #default="{ row }">
<el-tag :type="getStatusType(row.status)">
{{ row.status }}
{{ convertStatusToDict(row.status) }}
</el-tag>
</template>
</el-table-column>
......@@ -208,7 +184,6 @@ import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
// 引入API
import { getPolicyFortuneList, downloadPolicyFortune ,downloadPolicyFortuneAccount} from "@/api/financial/commission"
import { download } from '@/utils/request' // 直接导入下载函数
// 查询参数
const queryParams = reactive({
......@@ -242,12 +217,6 @@ const formData = reactive({
remark: ''
})
// 对账公司选项
const companyOptions = [
{ label: '公司A', value: 'company_a' },
{ label: '公司B', value: 'company_b' },
{ label: '公司C', value: 'company_c' }
]
// 下载选中项
const downloadSelected = async () => {
......@@ -455,15 +424,44 @@ const formatCurrency = (amount) => {
// 获取状态标签类型
const getStatusType = (status) => {
const types = {
pending: 'warning',
completed: 'success',
cancelled: 'danger'
0: 'warning',
1: 'success',
2: 'info'
}
return types[status] || 'info'
}
import { listType } from '@/api/system/dict/type'
const dictLists = ref([])
// 获取出账状态字典值
const getDictLists = () => {
return new Promise((resolve, reject) => {
listType({typeList: ['csf_fortune_status']}).then(res => {
if (res.code === 200 && res.data) {
const dictData = res.data.find(item => item.dictType === 'csf_fortune_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;
}
// 初始化
onMounted(() => {
getDictLists()
getList()
})
</script>
......
......@@ -268,12 +268,29 @@ const searchForm = reactive({
incomeDateRange: []
})
// 对账公司选项(示例数据)
const companyOptions = ref([
{ label: '公司A', value: 'company_a' },
{ label: '公司B', value: 'company_b' },
{ label: '公司C', value: 'company_c' }
])
// 对账公司选项
const companyOptions = ref([])
// 获取对账公司列表
import { getReconciliationCompanyList } from '@/api/financial/commission'
const fetchReconciliationCompanyList = async () => {
try {
const response = await getReconciliationCompanyList({
pageNo: 1,
pageSize: 1000
})
if (response.code === 200) {
companyOptions.value = response.data.records.map(item => ({
label: item.companyName,
value: item.reconciliationCompanyBizId
}))
} else {
ElMessage.error(response.msg)
}
} catch (error) {
ElMessage.error('获取对账公司列表失败')
}
}
// 表格数据
const tableData = ref([])
......@@ -299,6 +316,7 @@ onMounted(() => {
const initialData = async () => {
await getLists();
fetchTableData();
fetchReconciliationCompanyList()
}
......
......@@ -218,6 +218,14 @@ const referrerOptions = [
{ label: '赵六', value: 'zhaoliu' }
]
// 初始化
onMounted(() => {
getDictLists()
getList()
})
// 获取数据列表
const getList = async () => {
loading.value = true
......@@ -232,7 +240,7 @@ const getList = async () => {
loading.value = false
} catch (error) {
loading.value = false
ElMessage.error('获取数据失败')
// ElMessage.error('获取数据失败')
}
}
......@@ -325,7 +333,7 @@ const completeBilling = async () => {
const arr = selectedRows.value.map(item => item.fortuneAccountBizId)
// 调用出账API
await updateStatus(arr)
await fetchCompletePolicyFortune(arr)
} catch (error) {
......@@ -428,11 +436,26 @@ const updateStatus = async (row) => {
}
}
// 初始化
onMounted(() => {
getDictLists()
// 完成出账
import { completePolicyFortune } from '@/api/financial/commission'
const fetchCompletePolicyFortune = async (row) => {
try {
const res = await completePolicyFortune({
fortuneBizIdList: row
});
console.log(res)
if (res.code === 200) {
// 显示完成弹窗
billingCompleteDialogVisible.value = true
getList()
})
} else {
ElMessage.error(res.msg)
}
} catch (error) {
}
}
</script>
<style scoped>
......
......@@ -4,18 +4,6 @@
<el-card class="search-card">
<!-- 第一行筛选条件 -->
<el-row :gutter="20" class="search-row">
<!-- <el-col :span="8">
<div class="form-item">
<label class="form-label">新单编号</label>
<el-input
v-model="searchForm.newOrderNo"
placeholder="请输入"
clearable
size="default"
@keyup.enter="handleSearch"
/>
</div>
</el-col> -->
<el-col :span="8">
<div class="form-item">
<label class="form-label">保单号</label>
......@@ -44,7 +32,7 @@
<div class="form-item">
<label class="form-label">新单状态</label>
<el-select
v-model="searchForm.newOrderStatus"
v-model="searchForm.status"
placeholder="请选择"
clearable
size="default"
......@@ -89,69 +77,9 @@
>
重置
</el-button>
<!-- <el-button
type="info"
@click="toggleAdvancedSearch"
size="default"
:icon="expandSearch ? ArrowUp : ArrowDown"
>
{{ expandSearch ? '收起筛选' : '更多筛选' }}
</el-button> -->
</el-col>
</el-row>
<!-- 可展开的高级筛选区域 -->
<el-collapse v-model="activeNames" v-if="expandSearch" class="advanced-search">
<el-collapse-item name="1" title="高级筛选">
<el-row :gutter="20">
<el-col :span="8">
<div class="form-item">
<label class="form-label">产品类型</label>
<el-select
v-model="searchForm.productType"
placeholder="请选择"
clearable
size="default"
>
<el-option label="全部" value="" />
<el-option label="寿险" value="life" />
<el-option label="健康险" value="health" />
<el-option label="意外险" value="accident" />
<el-option label="年金险" value="annuity" />
</el-select>
</div>
</el-col>
<el-col :span="8">
<div class="form-item">
<label class="form-label">业务员</label>
<el-select
v-model="searchForm.salesman"
placeholder="请选择"
clearable
size="default"
>
<el-option label="全部" value="" />
<el-option label="张三" value="zhangsan" />
<el-option label="李四" value="lisi" />
<el-option label="王五" value="wangwu" />
</el-select>
</div>
</el-col>
<el-col :span="8">
<div class="form-item">
<label class="form-label">保费金额</label>
<el-input
v-model="searchForm.premium"
placeholder="请输入"
clearable
size="default"
/>
</div>
</el-col>
</el-row>
</el-collapse-item>
</el-collapse>
</el-card>
<!-- Excel导入区域 -->
......@@ -209,23 +137,7 @@
<el-card class="table-card">
<div class="table-actions">
<el-button type="primary" @click="handleUpdateToPolicyLib">更新至保单库</el-button>
<!-- <el-button
type="danger"
:icon="Delete"
size="default"
@click="handleDeleteSelected"
:disabled="selectedRows.length === 0"
>
批量删除
</el-button>
<el-button
type="primary"
:icon="Plus"
size="default"
@click="handleAdd"
>
新增
</el-button> -->
<!-- <el-text class="mx-1" size="large">新单首期保费缴费完成后,勾选并点击更新至保单库,可前往保单中心查询</el-text> -->
</div>
<el-table
v-loading="tableLoading"
......@@ -268,19 +180,19 @@
<template #default="scope">
<el-button
text
size="default"
size="primary"
@click="handleView(scope.row)"
>
查看
</el-button>
<el-button
<!-- <el-button
text
size="default"
type="primary"
@click="handleEdit(scope.row)"
>
编辑
</el-button>
</el-button> -->
</template>
</el-table-column>
</el-table>
......@@ -305,6 +217,7 @@
:policy-follow-status-list="policyFollowStatusList"
title="新单跟进详情"
:expected-commission-list="expectedCommissionList"
:policy-fortune-list="policyFortuneList"
@close="handleDetailClose"
/>
</div>
......@@ -314,9 +227,7 @@
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { Search, RefreshLeft, UploadFilled, Delete, Plus, Document } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import * as XLSX from 'xlsx'
import axios from 'axios'
import { getPolicyFollowList, getExpectedCommissionList } from '@/api/sign/underwritingMain'
import { getToken } from "@/utils/auth"
......@@ -324,20 +235,25 @@ import { listType } from '@/api/system/dict/type'
import date from '@/utils/date'
import PolicyDetailDialog from '@/components/PolicyDetailDialog/index.vue'
import { numberWithCommas } from '@/utils/index.js'
import { getPolicyFortuneList } from '@/api/financial/commission'
// 通过dictType=csf_policy_follow_status获取新单状态字典值,获取对象中的dictItemList
const policyFollowStatusList = ref([]);
const commissionStatusList = ref([]);
const fortuneStatusList = ref([]);
const getLists = ()=>{
listType({typeList: ['csf_policy_follow_status','csf_expected_commission_status']}).then(res => {
listType({typeList: ['csf_policy_follow_status','csf_expected_commission_status','csf_fortune_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 || [];
const fortuneStatusData = res.data.find(item => item.dictType === 'csf_fortune_status');
fortuneStatusList.value = fortuneStatusData?.dictItemList || [];
} else {
policyFollowStatusList.value = [];
commissionStatusList.value = [];
fortuneStatusList.value = [];
}
}).catch(error => {
console.error('获取状态列表失败:', error);
......@@ -346,12 +262,13 @@ const getLists = ()=>{
}
// 返回数据中状态需要转换为字典值
const convertStatusToDict = (type=1,status) => {
const arr = type === 1 ? policyFollowStatusList : commissionStatusList
const arr = type === 1 ? policyFollowStatusList : type === 2 ? commissionStatusList : fortuneStatusList
const dictItem = arr.value.find(item => item.itemValue == status)
return dictItem?.itemLabel ?? status
}
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + '/csf/api/policy_follow/upload/excel')
// 搜索表单数据
const searchForm = reactive({
policyBizId: '', // 新单编号(对应接口的policyBizId)
......@@ -365,17 +282,27 @@ const searchForm = reactive({
productCode: '' // 产品代码(对应接口的productCode)
})
// 控制高级筛选的展开/收起
const expandSearch = ref(false)
const activeNames = ref(['1'])
// 切换高级筛选显示状态
const toggleAdvancedSearch = () => {
expandSearch.value = !expandSearch.value
}
// 预计来佣列表
const expectedCommissionList = ref([])
const policyFortuneList = ref([])
const getPolicyFortuneLists = async (policyNo) => {
try {
const response = await getPolicyFortuneList({ policyNo })
if (response.code === 200 && response.data) {
policyFortuneList.value = response.data.records || []
policyFortuneList.value.forEach(item => {
item.fortuneStatusLabel = convertStatusToDict(3,item.status)
})
} else {
policyFortuneList.value = []
}
} catch (error) {
console.error('获取预计来佣列表失败:', error)
policyFortuneList.value = []
}
}
// 表格数据
const tableData = ref([])
......@@ -399,6 +326,7 @@ const handleView = async (row) => {
currentRow.value = { ...row}
viewDialogVisible.value = true
fetchExpectedCommissionList(row.policyNo)
getPolicyFortuneLists(row.policyNo)
}
// 处理详情弹窗关闭
......@@ -526,7 +454,13 @@ const handleSearch = () => {
const resetForm = () => {
searchForm.name = ''
searchForm.status = ''
searchForm.dateRange = []
searchForm.policyBizId = ''
searchForm.policyNo = ''
searchForm.customerName = ''
searchForm.customerBizId = ''
searchForm.insurer = ''
searchForm.productCode = ''
searchForm.signDateRange = []
}
// 处理分页大小变化
......@@ -554,7 +488,6 @@ const tableRowClassName = ({ row }) => {
// 处理文件选择
const handleFileChange = (file) => {
selectedFile.value = file.raw
ElMessage.success(`已选择文件: ${file.name}`)
}
// 处理导入 - 调整为multipart/form-data格式
......@@ -587,7 +520,7 @@ const handleImport = async () => {
// 调用上传接口
const response = await axios.post(
'http://139.224.145.34:9002/csf/api/policy_follow/upload/excel',
uploadUrl.value,
formData,
{
headers: {
......@@ -596,18 +529,17 @@ const handleImport = async () => {
}
}
)
// 处理接口响应
if (response.data.code === 200) {
ElMessage.success(`导入成功,共 ${response.data?.successCount || 0} 条数据`)
ElMessage.success('导入成功')
selectedFile.value = null
// 重新获取表格数据
fetchTableData()
} else {
ElMessage.error(`导入失败: ${response.data.msg || '未知错误'}`)
// 如果有错误详情,可以展示
if (response.data.data?.errorMsg) {
console.error('导入错误详情:', response.data.errorMsg)
if (response.data.msg) {
console.error('导入错误详情:', response.data.msg)
}
}
} catch (error) {
......@@ -623,70 +555,10 @@ const handleImport = async () => {
}
// 下载模板
const downloadTemplate = () => {
// 模拟模板数据
const templateData = [
{ name: '示例1', category: '类别A', status: 'active' },
{ name: '示例2', category: '类别B', status: 'inactive' }
]
const worksheet = XLSX.utils.json_to_sheet(templateData)
const workbook = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(workbook, worksheet, '数据模板')
// 生成并下载文件
XLSX.writeFile(workbook, '数据导入模板.xlsx')
ElMessage.success('模板下载成功')
}
// // 处理批量删除
// const handleDeleteSelected = () => {
// ElMessageBox.confirm(
// `确定要删除选中的 ${selectedRows.value.length} 条数据吗?`,
// '删除确认',
// {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }
// ).then(() => {
// // 模拟删除操作
// setTimeout(() => {
// ElMessage.success('删除成功')
// fetchTableData()
// }, 500)
// })
// }
// // 处理单个删除
// const handleDelete = (row) => {
// ElMessageBox.confirm(
// `确定要删除 ${row.name} 吗?`,
// '删除确认',
// {
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// type: 'warning'
// }
// ).then(() => {
// // 模拟删除操作
// setTimeout(() => {
// ElMessage.success('删除成功')
// fetchTableData()
// }, 500)
// })
// }
// 处理新增
// const handleAdd = () => {
// ElMessage.info('打开新增对话框')
// // 实际项目中这里会打开新增数据的对话框
// }
// 处理编辑
// const handleEdit = (row) => {
// ElMessage.info(`编辑 ID: ${row.id} 的数据`)
// // 实际项目中这里会打开编辑数据的对话框
// }
// 下载地址
}
import { updateToPolicyLib } from '@/api/sign/underwritingMain'
// 处理更新至保单库
const handleUpdateToPolicyLib = () => {
......@@ -701,7 +573,7 @@ const handleUpdateToPolicyLib = () => {
).then(() => {
// 调用更新至保单库接口
updateToPolicyLib({
policyNoList: selectedRows.value.map(row => row.policyNo).join(',')
policyNoList: selectedRows.value.map(row => row.policyNo)
}).then(response => {
if (response.code === 200) {
ElMessage.success('更新成功')
......@@ -710,6 +582,12 @@ const handleUpdateToPolicyLib = () => {
}
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消更新至保单库',
})
})
}
......@@ -726,7 +604,7 @@ const formatFileSize = (bytes) => {
<style scoped>
.data-management-page {
padding: 20px;
max-width: 1600px;
/* max-width: 1600px; */
margin: 0 auto;
}
......
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