Commit db5627e8 by yuzhenWang

Merge branch 'test' into 'feature-20250827wyz-写业务'

Test

See merge request !88
parents f79510d0 0194c18b
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
"jsencrypt": "3.3.2", "jsencrypt": "3.3.2",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "3.0.2", "pinia": "3.0.2",
"spark-md5": "^3.0.2",
"splitpanes": "^4.0.4", "splitpanes": "^4.0.4",
"vue": "3.5.16", "vue": "3.5.16",
"vue-cropper": "1.1.1", "vue-cropper": "1.1.1",
......
<template>
<div class="upload-container">
<h2>多文件分片上传 (Vue3 + Element Plus)</h2>
<el-card shadow="hover">
<el-upload
ref="uploadRef"
class="multi-uploader"
action="#"
:auto-upload="false"
multiple
:limit="10"
:on-change="handleFileChange"
:on-remove="handleRemove"
:file-list="fileList"
>
<template #trigger>
<el-button type="primary">选择文件</el-button>
</template>
<!-- 自定义文件列表项 -->
<template #file="{ file }">
<div class="el-upload-list__item-custom">
<div class="file-info">
<el-icon><Document /></el-icon>
<span class="file-name">{{ file.name }}</span>
<span class="file-size">{{ formatSize(file.size) }}</span>
</div>
<!-- 状态与进度区域 -->
<div class="file-action-area">
<!-- 等待上传状态 -->
<div v-if="getTaskStatus(file.uid)?.status === 'idle' || !getTaskStatus(file.uid)" class="status-wait">
<el-tag size="small">待上传</el-tag>
<el-button link type="primary" @click="startSingleUpload(file)">开始</el-button>
</div>
<!-- 进行中/暂停/合并状态 -->
<div v-else-if="['checking', 'uploading', 'merging', 'paused'].includes(getTaskStatus(file.uid)?.status)" class="status-progress">
<el-progress
:percentage="getTaskStatus(file.uid)?.progress || 0"
:status="getTaskStatus(file.uid)?.status === 'paused' ? 'exception' : undefined"
:format="(percent) => getTaskStatus(file.uid)?.message || `${percent}%`"
/>
<div class="btn-group">
<el-button
v-if="getTaskStatus(file.uid)?.status !== 'paused'"
link type="warning"
@click="handlePause(file.uid)"
>暂停</el-button>
<el-button
v-else
link type="success"
@click="handleResume(file.uid)"
>继续</el-button>
<el-button link type="danger" @click="handleCancel(file.uid)">取消</el-button>
</div>
</div>
<!-- 成功状态 -->
<div v-else-if="getTaskStatus(file.uid)?.status === 'success'" class="status-success">
<el-tag type="success" effect="plain">完成</el-tag>
<span class="success-text">{{ getTaskStatus(file.uid)?.message }}</span>
</div>
<!-- 失败状态 -->
<div v-else-if="getTaskStatus(file.uid)?.status === 'error'" class="status-error">
<el-tag type="danger" effect="plain">失败</el-tag>
<span class="error-text">{{ getTaskStatus(file.uid)?.message }}</span>
<el-button link type="primary" @click="startSingleUpload(file)">重试</el-button>
</div>
</div>
</div>
</template>
</el-upload>
<div class="global-actions" v-if="fileList.length > 0">
<el-button type="success" @click="startAllUploads" :disabled="isUploadingAny">全部开始</el-button>
<el-button type="info" @click="clearAll">清空列表</el-button>
</div>
</el-card>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { Document } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { useMultiFileUpload } from '@/composables/useMultiFileUpload';
const uploadRef = ref(null);
const fileList = ref([]); // Element Plus 管理的文件列表
// 引入我们的逻辑钩子
const { startUpload, pauseFile, resumeFile, cancelFile, getTaskStatus } = useMultiFileUpload();
// 格式化大小
const formatSize = (bytes) => {
if (!bytes) return '';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
// 当用户选择文件时
const handleFileChange = (uploadFile, uploadFiles) => {
fileList.value = uploadFiles;
// 初始化状态为 idle (实际上 useMultiFileUpload 会在 start 时初始化)
};
// 移除文件
const handleRemove = (uploadFile, uploadFiles) => {
fileList.value = uploadFiles;
cancelFile(uploadFile.uid); // 如果正在传,先取消
};
// 单个开始上传
const startSingleUpload = (file) => {
// 这里的 file 是 element-plus 的 UploadFile 对象,raw 才是原生 File 对象
if (!file.raw) return;
// 定义回调,用于强制刷新视图(虽然 uploadTasks 是响应式的,但有时 EL 的 slot 更新不及时,可加 forceUpdate 逻辑,此处依赖响应式)
const updateCallback = (uid, status, progress, msg) => {
// 如果需要更激进的 UI 更新,可以在这里操作 fileList 中的对应项
// 但通常响应式对象足够
};
startUpload(file.raw, updateCallback);
};
// 全部开始 (简单实现:遍历所有未成功的文件)
const startAllUploads = () => {
fileList.value.forEach(file => {
const status = getTaskStatus(file.uid)?.status;
if (!status || status === 'error' || status === 'idle' || status === 'paused') {
// 如果是 paused,调用 resume 逻辑可能需要特殊处理,这里简化为重新触发 start (我们的 logic 支持断点)
if (status === 'paused') {
resumeFile(file.uid);
} else {
startSingleUpload(file);
}
}
});
};
const handlePause = (uid) => pauseFile(uid);
const handleResume = (uid) => resumeFile(uid);
const handleCancel = (uid) => {
cancelFile(uid);
// 从列表中移除视觉上的文件(可选,看需求是保留记录还是直接删掉)
// fileList.value = fileList.value.filter(f => f.uid !== uid);
};
const clearAll = () => {
fileList.value = [];
// 清理内部状态逻辑略
};
const isUploadingAny = computed(() => {
return fileList.value.some(f => {
const s = getTaskStatus(f.uid)?.status;
return s === 'uploading' || s === 'checking' || s === 'merging';
});
});
</script>
<style scoped>
.upload-container {
max-width: 800px;
margin: 20px auto;
}
.el-upload-list__item-custom {
display: flex;
flex-direction: column;
padding: 10px;
border-bottom: 1px solid #ebeef5;
transition: background-color 0.2s;
}
.el-upload-list__item-custom:hover {
background-color: #f5f7fa;
}
.file-info {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.file-info .el-icon {
margin-right: 8px;
color: #409eff;
font-size: 20px;
}
.file-name {
font-weight: bold;
color: #606266;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 10px;
}
.file-size {
font-size: 12px;
color: #909399;
}
.file-action-area {
display: flex;
align-items: center;
justify-content: space-between;
}
.status-wait, .status-success, .status-error {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
}
.status-progress {
width: 100%;
display: flex;
align-items: center;
gap: 15px;
}
.status-progress .el-progress {
flex: 1;
}
.btn-group {
display: flex;
gap: 5px;
}
.global-actions {
margin-top: 20px;
text-align: right;
border-top: 1px solid #eee;
padding-top: 15px;
}
</style>
\ No newline at end of file
// composables/useMultiFileUpload.js
import { ref, reactive } from 'vue';
import SparkMD5 from 'spark-md5';
const CHUNK_SIZE = 2 * 1024 * 1024; // 2MB
const FILE_CONCURRENT_LIMIT = 3; // 同时上传几个文件(宏观并发)
const CHUNK_CONCURRENT_LIMIT = 3; // 每个文件内部同时传几片(微观并发)
export function useMultiFileUpload() {
// 存储所有文件的上传任务状态
// key: file.uid (element-plus生成的唯一ID), value: taskObject
const uploadTasks = reactive({});
const calculateFileMD5 = (file) => {
return new Promise((resolve, reject) => {
const spark = new SparkMD5.ArrayBuffer();
const fileReader = new FileReader();
let currentChunk = 0;
const chunks = Math.ceil(file.size / CHUNK_SIZE);
fileReader.onload = (e) => {
spark.append(e.target.result);
currentChunk++;
if (currentChunk < chunks) {
loadNext();
} else {
resolve(spark.end());
}
};
fileReader.onerror = () => reject(new Error('文件读取失败'));
const loadNext = () => {
const start = currentChunk * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, file.size);
fileReader.readAsArrayBuffer(file.slice(start, end));
};
loadNext();
});
};
const uploadChunkWithRetry = async (formData, chunkIndex, maxRetries = 3) => {
let retryCount = 0;
while (retryCount < maxRetries) {
try {
const response = await fetch('/upload/chunk', { method: 'POST', body: formData });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
retryCount++;
if (retryCount === maxRetries) throw error;
await new Promise((r) => setTimeout(r, 1000 * retryCount));
}
}
};
// 单个文件的上传主逻辑
const processFile = async (rawFile, updateCallback) => {
const uid = rawFile.uid;
// 初始化任务状态
uploadTasks[uid] = {
status: 'checking', // checking, uploading, merging, success, error, paused
progress: 0,
message: '正在检查文件...',
cancelFlag: false,
pauseFlag: false
};
const updateState = (status, progress, message) => {
if (uploadTasks[uid]) {
uploadTasks[uid].status = status;
uploadTasks[uid].progress = progress;
uploadTasks[uid].message = message;
}
// 通知组件更新 UI
if (updateCallback) updateCallback(uid, status, progress, message);
};
try {
// 1. 计算 MD5
const fileMd5 = await calculateFileMD5(rawFile);
// 2. 检查秒传/断点
updateState('checking', 5, '正在检查服务器记录...');
const checkResult = await fetch(
`/upload/check?fileName=${encodeURIComponent(rawFile.name)}&fileMd5=${fileMd5}&fileSize=${rawFile.size}`
).then(res => res.json());
if (checkResult.uploaded) {
updateState('success', 100, '秒传成功');
return { success: true, message: '秒传' };
}
const uploadedChunks = new Set(checkResult.uploadedChunks || []);
const totalChunks = Math.ceil(rawFile.size / CHUNK_SIZE);
const initialProgress = Math.round((uploadedChunks.size / totalChunks) * 100);
updateState('uploading', initialProgress, `准备上传 (已存在 ${uploadedChunks.size}/${totalChunks} 片)`);
// 3. 准备分片队列
const pendingChunks = [];
for (let i = 0; i < totalChunks; i++) {
if (!uploadedChunks.has(i)) pendingChunks.push(i);
}
// 4. 并发上传分片
const runChunkTask = async () => {
while (pendingChunks.length > 0 && !uploadTasks[uid].cancelFlag) {
// 处理暂停
while (uploadTasks[uid].pauseFlag && !uploadTasks[uid].cancelFlag) {
await new Promise(r => setTimeout(r, 500));
}
if (uploadTasks[uid].cancelFlag) break;
const chunkIndex = pendingChunks.shift();
const start = chunkIndex * CHUNK_SIZE;
const end = Math.min(start + CHUNK_SIZE, rawFile.size);
const chunk = rawFile.slice(start, end);
const formData = new FormData();
formData.append('file', chunk);
formData.append('chunkIndex', chunkIndex);
formData.append('totalChunks', totalChunks);
formData.append('fileName', rawFile.name);
formData.append('fileMd5', fileMd5);
await uploadChunkWithRetry(formData, chunkIndex);
// 更新进度
const currentUploaded = totalChunks - pendingChunks.length + uploadedChunks.size;
const percent = Math.min(99, Math.round((currentUploaded / totalChunks) * 100));
updateState('uploading', percent, `上传中 ${percent}%`);
}
};
// 启动微观并发
const workers = Array.from({ length: Math.min(CHUNK_CONCURRENT_LIMIT, pendingChunks.length) }, () => runChunkTask());
await Promise.all(workers);
if (uploadTasks[uid].cancelFlag) {
updateState('error', 0, '用户取消');
return { success: false, message: 'Cancelled' };
}
// 5. 合并
updateState('merging', 99, '正在合并文件...');
await fetch('/upload/merge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ fileName: rawFile.name, fileMd5: fileMd5, totalChunks })
}).then(res => res.json());
updateState('success', 100, '上传完成');
return { success: true, message: 'Success' };
} catch (error) {
if (!uploadTasks[uid].cancelFlag) {
updateState('error', 0, error.message || '上传失败');
}
return { success: false, error };
}
};
// 对外暴露的方法
const startUpload = (rawFile, updateCallback) => {
if (!rawFile) return;
// 如果该文件已经在上传,先忽略或提示
if (uploadTasks[rawFile.uid]?.status === 'uploading') return;
processFile(rawFile, updateCallback);
};
const pauseFile = (uid) => {
if (uploadTasks[uid]) uploadTasks[uid].pauseFlag = true;
};
const resumeFile = (uid) => {
if (uploadTasks[uid]) uploadTasks[uid].pauseFlag = false;
};
const cancelFile = (uid) => {
if (uploadTasks[uid]) {
uploadTasks[uid].cancelFlag = true;
uploadTasks[uid].pauseFlag = false;
uploadTasks[uid].status = 'error';
uploadTasks[uid].message = '已取消';
}
};
const getTaskStatus = (uid) => uploadTasks[uid] || null;
return {
startUpload,
pauseFile,
resumeFile,
cancelFile,
getTaskStatus,
uploadTasks // 响应式对象,可直接在模板中使用
};
}
\ No newline at end of file
...@@ -116,6 +116,7 @@ ...@@ -116,6 +116,7 @@
label="累积已入账金额" label="累积已入账金额"
width="120" width="120"
sortable sortable
:formatter="row=>formatCurrency(row.commissionPaidAmount || 0)"
/> />
<el-table-column <el-table-column
prop="commissionPaidRatio" prop="commissionPaidRatio"
...@@ -130,16 +131,17 @@ ...@@ -130,16 +131,17 @@
<el-table-column prop="broker" label="转介人" width="130" sortable /> <el-table-column prop="broker" label="转介人" width="130" sortable />
<el-table-column prop="team" label="所属团队" width="120" sortable /> <el-table-column prop="team" label="所属团队" width="120" sortable />
<el-table-column prop="exchangeRate" label="结算汇率(估)" width="140" sortable /> <el-table-column prop="exchangeRate" label="结算汇率(估)" width="140" sortable />
<el-table-column prop="hkdAmount" label="应出账金额(HKD)" width="160" sortable /> <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="currency" label="出账币种" width="130" sortable />
<el-table-column prop="fortunePaidAmount" label="已出账金额" width="160" 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 /> <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="currentPaymentAmount" label="本期出账金额" width="120" sortable/> -->
<el-table-column <el-table-column
prop="currentPaymentHkdAmount" prop="currentPaymentHkdAmount"
label="本期出账金额(HKD)" label="本期出账金额(HKD)"
width="160" width="160"
sortable sortable
:formatter="row=>formatCurrency(row.currentPaymentHkdAmount || 0)"
/> />
<el-table-column <el-table-column
prop="fortuneUnpaidRatio" prop="fortuneUnpaidRatio"
...@@ -153,7 +155,7 @@ ...@@ -153,7 +155,7 @@
{{ selectDictLabel(csf_fortune_status, row.status) }} {{ selectDictLabel(csf_fortune_status, row.status) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="premium" label="期交保费" width="120" sortable /> <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="policyCurrency" label="保单币种" width="120" sortable />
<el-table-column prop="payoutDate" label="出账日(估)" width="120" sortable /> <el-table-column prop="payoutDate" label="出账日(估)" width="120" sortable />
<el-table-column prop="actualPayoutDate" label="出账日(实)" width="120" sortable /> <el-table-column prop="actualPayoutDate" label="出账日(实)" width="120" sortable />
......
...@@ -509,7 +509,7 @@ const handleSelect = async (e, row) => { ...@@ -509,7 +509,7 @@ const handleSelect = async (e, row) => {
payRecordDialogTableColumns.value = [ payRecordDialogTableColumns.value = [
{ property: 'broker', label: '转介人', width: '100', }, { property: 'broker', label: '转介人', width: '100', },
{ property: 'fortuneName', label: '出账项目', width: '150' }, { property: 'fortuneName', label: '出账项目', width: '150' },
{ property: 'currentPaymentAmount', label: '出账金额', width: '150' }, { property: 'currentPaymentHkdAmount', label: '出账金额', width: '150',formatter:(row)=> formatCurrency(row.currentPaymentHkdAmount || 0)},
{ property: 'currency', label: '出账币种', width: '150' }, { property: 'currency', label: '出账币种', width: '150' },
{ property: 'currentPaymentRatio', label: '出账比例', width: '150', formatter: (row) => `${row.currentPaymentRatio}%` }, { property: 'currentPaymentRatio', label: '出账比例', width: '150', formatter: (row) => `${row.currentPaymentRatio}%` },
{ property: 'fortuneUnpaidRatio', label: '待出账比例', width: '150', formatter: (row) => `${row.fortuneUnpaidRatio}%` }, { property: 'fortuneUnpaidRatio', label: '待出账比例', width: '150', formatter: (row) => `${row.fortuneUnpaidRatio}%` },
......
...@@ -13,13 +13,31 @@ ...@@ -13,13 +13,31 @@
<div class="statistics-container" v-if="statisticsData.totalPolicyCount > 0"> <div class="statistics-container" v-if="statisticsData.totalPolicyCount > 0">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="4" class="text-center mb-4"> <el-col :xs="24" :sm="12" :md="4" class="text-center mb-4">
<el-statistic title="应收款总金额" :value="statisticsData.totalAmount" /> <el-statistic :value="formatCurrency(statisticsData.totalAmount)">
<template #title>
<div style="display: inline-flex; align-items: center">
应收款总金额
</div>
</template>
</el-statistic>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="4" class="text-center mb-4"> <el-col :xs="24" :sm="12" :md="4" class="text-center mb-4">
<el-statistic title="已入账金额" :value="statisticsData.totalPaidAmount" /> <el-statistic :value="formatCurrency(statisticsData.totalPaidAmount)">
<template #title>
<div style="display: inline-flex; align-items: center">
已入账金额
</div>
</template>
</el-statistic>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="4" class="text-center mb-4"> <el-col :xs="24" :sm="12" :md="4" class="text-center mb-4">
<el-statistic title="待入账金额(估)" :value="statisticsData.pendingPaidAmount" /> <el-statistic :value="formatCurrency(statisticsData.pendingPaidAmount)">
<template #title>
<div style="display: inline-flex; align-items: center">
待入账金额(估)
</div>
</template>
</el-statistic>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="4" class="text-center mb-4"> <el-col :xs="24" :sm="12" :md="4" class="text-center mb-4">
<el-statistic :value="formatCurrency(statisticsData.paidAmountRatio)"> <el-statistic :value="formatCurrency(statisticsData.paidAmountRatio)">
...@@ -60,7 +78,7 @@ ...@@ -60,7 +78,7 @@
<el-col :xs="24" :sm="12" :md="4" :lg="4"> <el-col :xs="24" :sm="12" :md="4" :lg="4">
<el-card shadow="hover" class="statistics-card"> <el-card shadow="hover" class="statistics-card">
<div class="card-content"> <div class="card-content">
<div class="card-label">账总金额</div> <div class="card-label">账总金额</div>
<div class="card-value">{{ formatCurrency(detailRecordStatistics.totalExpectedAmount) }} <div class="card-value">{{ formatCurrency(detailRecordStatistics.totalExpectedAmount) }}
</div> </div>
</div> </div>
...@@ -69,7 +87,7 @@ ...@@ -69,7 +87,7 @@
<el-col :xs="24" :sm="12" :md="4" :lg="4"> <el-col :xs="24" :sm="12" :md="4" :lg="4">
<el-card shadow="hover" class="statistics-card"> <el-card shadow="hover" class="statistics-card">
<div class="card-content"> <div class="card-content">
<div class="card-label">账金额</div> <div class="card-label">账金额</div>
<div class="card-value">{{ formatCurrency(detailRecordStatistics.totalPaidAmount) }} <div class="card-value">{{ formatCurrency(detailRecordStatistics.totalPaidAmount) }}
</div> </div>
</div> </div>
...@@ -78,7 +96,7 @@ ...@@ -78,7 +96,7 @@
<el-col :xs="24" :sm="12" :md="4" :lg="4"> <el-col :xs="24" :sm="12" :md="4" :lg="4">
<el-card shadow="hover" class="statistics-card"> <el-card shadow="hover" class="statistics-card">
<div class="card-content"> <div class="card-content">
<div class="card-label">账金额</div> <div class="card-label">账金额</div>
<div class="card-value">{{ formatCurrency(detailRecordStatistics.totalUnpaidAmount) }} <div class="card-value">{{ formatCurrency(detailRecordStatistics.totalUnpaidAmount) }}
</div> </div>
</div> </div>
...@@ -87,7 +105,7 @@ ...@@ -87,7 +105,7 @@
<el-col :xs="24" :sm="12" :md="4" :lg="4"> <el-col :xs="24" :sm="12" :md="4" :lg="4">
<el-card shadow="hover" class="statistics-card"> <el-card shadow="hover" class="statistics-card">
<div class="card-content"> <div class="card-content">
<div class="card-label">账比例</div> <div class="card-label">账比例</div>
<div class="card-value">{{ detailRecordStatistics.paidAmountRatio }}%</div> <div class="card-value">{{ detailRecordStatistics.paidAmountRatio }}%</div>
</div> </div>
</el-card> </el-card>
...@@ -104,7 +122,7 @@ ...@@ -104,7 +122,7 @@
<el-card shadow="hover" class="statistics-card"> <el-card shadow="hover" class="statistics-card">
<div class="card-content"> <div class="card-content">
<div class="card-label">总保费</div> <div class="card-label">总保费</div>
<div class="card-value">{{ formatCurrency(detailRecordStatistics.totalPremiumAmount) }} <div class="card-value">{{ formatCurrency(detailRecordStatistics.totalPremium) }}
</div> </div>
</div> </div>
</el-card> </el-card>
...@@ -140,7 +158,7 @@ ...@@ -140,7 +158,7 @@
:showAction="false" :showClose="true" @close="entryRecordDialogTableVisible = false"> :showAction="false" :showClose="true" @close="entryRecordDialogTableVisible = false">
<el-table :data="entryRecordDialogTableData" border style="width: 100%"> <el-table :data="entryRecordDialogTableData" border style="width: 100%">
<el-table-column v-for="item in entryRecordDialogTableColumns" :key="item.property" <el-table-column v-for="item in entryRecordDialogTableColumns" :key="item.property"
:prop="item.property" :label="item.label" :width="item.width" /> :prop="item.property" :label="item.label" :width="item.width" :formatter="item.formatter" />
<el-table-column fixed="right" label="操作" min-width="120"> <el-table-column fixed="right" label="操作" min-width="120">
<template #default> <template #default>
<el-button link type="primary" size="small" @click="handleClick"> <el-button link type="primary" size="small" @click="handleClick">
...@@ -649,10 +667,10 @@ const handleSelect = async (e, row) => { ...@@ -649,10 +667,10 @@ const handleSelect = async (e, row) => {
{ property: 'totalPeriod', label: '总期数', width: '150' }, { property: 'totalPeriod', label: '总期数', width: '150' },
{ property: 'exchangeRate', label: '结算汇率(实)', width: '150' }, { property: 'exchangeRate', label: '结算汇率(实)', width: '150' },
{ property: 'currency', label: '入账币种', width: '150' }, { property: 'currency', label: '入账币种', width: '150' },
{ property: 'amount', label: '入账金额', width: '150' }, { property: 'amount', label: '入账金额', width: '150',formatter:(row)=> formatCurrency(row.amount || 0) },
{ property: 'currentCommissionRatio', label: '入账比例', width: '150' }, { property: 'currentCommissionRatio', label: '入账比例', width: '150', formatter: (row) => `${row.currentCommissionRatio || ''}%` },
{ property: 'commissionDate', label: '入账日', width: '150' }, { property: 'commissionDate', label: '入账日', width: '150' },
{ property: 'commissionStatus', label: '入账状态', width: '150' } { property: 'commissionStatusName', label: '入账状态', width: '150' }
] ]
// 加载真实数据 // 加载真实数据
const records = await loadEntryRecordData(row.commissionExpectedBizId) const records = await loadEntryRecordData(row.commissionExpectedBizId)
......
...@@ -194,6 +194,7 @@ ...@@ -194,6 +194,7 @@
@close="((fileUploadDialogFlag = false), (files = ''))" @close="((fileUploadDialogFlag = false), (files = ''))"
@confirm="((fileUploadDialogFlag = false), (files = ''))" @confirm="((fileUploadDialogFlag = false), (files = ''))"
> >
<!-- <FileUploader/> -->
<FileUpload <FileUpload
v-model="files" v-model="files"
:data="{ obiectTableName: 'policy_follow', objectBizId: props.policyBizId }" :data="{ obiectTableName: 'policy_follow', objectBizId: props.policyBizId }"
...@@ -223,6 +224,8 @@ import { getNowTime, formatToDate, formatToDateTime } from '@/utils/date' ...@@ -223,6 +224,8 @@ import { getNowTime, formatToDate, formatToDateTime } from '@/utils/date'
import EditableTable from '@/components/csf-common/EditableTable.vue' import EditableTable from '@/components/csf-common/EditableTable.vue'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import FileUploader from '@/components/LargeFileUploader/index.vue';
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
proxy.useDictLists([ proxy.useDictLists([
'sys_no_yes', 'sys_no_yes',
...@@ -282,7 +285,8 @@ const introducerConfig = [ ...@@ -282,7 +285,8 @@ const introducerConfig = [
brokerName: 'realName', brokerName: 'realName',
internalCode: 'internalNumber', internalCode: 'internalNumber',
team: 'deptName', team: 'deptName',
phone: 'phone' phone: 'phone',
teamBizId:'deptBizId'
}, },
transform: res => { transform: res => {
return (res?.data.records || []).map(item => ({ return (res?.data.records || []).map(item => ({
......
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