补贴批量 功能开发
This commit is contained in:
parent
6889f80321
commit
7f335c8610
|
|
@ -28,6 +28,12 @@
|
|||
@click="handleBatchEdit"
|
||||
>批量补贴</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
size="mini" type="primary"
|
||||
@click="handleImportRecharge"
|
||||
>导入充值</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
size="mini" type="danger"
|
||||
|
|
@ -539,16 +545,114 @@
|
|||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入充值对话框 -->
|
||||
<el-dialog title="导入充值" :visible.sync="openImport" width="600px" append-to-body>
|
||||
<div style="padding: 20px;">
|
||||
<!-- 下载模板区域 -->
|
||||
<div style="margin-bottom: 30px; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px; text-align: center;">
|
||||
<i class="el-icon-download" style="font-size: 48px; color: #fff; margin-bottom: 10px;"></i>
|
||||
<div style="color: #fff; font-size: 16px; margin-bottom: 15px;">下载补贴充值导入模板</div>
|
||||
<el-button type="primary" size="mini" @click="downloadTemplate" style="background: #fff; color: #667eea; border: none;">
|
||||
<i class="el-icon-download"></i> 下载模板
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 文件上传区域 -->
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div style="font-size: 14px; color: #606266; margin-bottom: 10px; font-weight: 500;">
|
||||
<i class="el-icon-upload2"></i> 上传文件
|
||||
</div>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:on-change="handleFileChange"
|
||||
:file-list="fileList"
|
||||
:auto-upload="false"
|
||||
:limit="1"
|
||||
:disabled="fileList.length > 0"
|
||||
accept=".xlsx,.xls"
|
||||
drag
|
||||
style="width: 100%;"
|
||||
>
|
||||
<i class="el-icon-upload" style="font-size: 67px; color: #C0C4CC; margin: 40px 0 16px;"></i>
|
||||
<div class="el-upload__text" style="color: #606266;">
|
||||
将文件拖到此处,或<em>点击上传</em>
|
||||
</div>
|
||||
<div class="el-upload__tip" slot="tip" style="color: #909399; font-size: 12px; margin-top: 10px;">
|
||||
只能上传 Excel 文件(.xlsx/.xls),且不超过 10MB
|
||||
</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
|
||||
<!-- 上传进度 -->
|
||||
<div v-if="uploadProgress > 0 && uploadProgress < 100" style="margin-bottom: 20px;">
|
||||
<el-progress :percentage="uploadProgress" :status="uploadProgress === 100 ? 'success' : ''"></el-progress>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleImportCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="submitUpload" :loading="uploading">开始上传</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 补贴充值预览对话框 -->
|
||||
<el-dialog title="补贴充值预览" :visible.sync="openImportPreview" width="800px" append-to-body>
|
||||
<div style="margin-bottom: 10px; text-align: center;">
|
||||
总记录数:{{ importPreviewData.totalCount || '--' }},
|
||||
有效记录数:{{ importPreviewData.validCount || '--' }},
|
||||
充值总额:{{ importPreviewData.validTotalAmount ? (importPreviewData.validTotalAmount/100).toFixed(2) : '--' }},
|
||||
无效记录数:{{ importPreviewData.invalidCount || '--' }}
|
||||
</div>
|
||||
<div v-if="importPreviewData.invalidList && importPreviewData.invalidList.length > 0" style="margin-bottom: 20px;">
|
||||
<div style="font-weight: 600; margin-bottom: 10px;">无效记录</div>
|
||||
<el-table :data="importPreviewData.invalidList" max-height="250">
|
||||
<!-- <el-table-column label="行号" align="center" prop="row" width="80" :show-overflow-tooltip="true" /> -->
|
||||
<el-table-column label="用户编号" align="center" prop="userId" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="用户姓名" align="center" prop="nickName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="用户手机号" align="center" prop="phoneNumber" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="所属组织" align="center" prop="deptFullName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="充值金额" align="center" prop="amount" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.amount ? (scope.row.amount/100).toFixed(2) : '--' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因" align="center" prop="errorMessage" :show-overflow-tooltip="true"/>
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-if="importPreviewData.successVoList && importPreviewData.successVoList.length > 0">
|
||||
<div style="font-weight: 600; margin-bottom: 10px;">有效记录</div>
|
||||
<el-table :data="importPreviewData.successVoList" max-height="250">
|
||||
<el-table-column label="用户编号" align="center" prop="userId" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="用户姓名" align="center" prop="nickName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="用户手机号" align="center" prop="phoneNumber" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="所属组织" align="center" prop="deptFullName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="充值金额" align="center" prop="amount" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.amount ? (scope.row.amount/100).toFixed(2) : '--' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="confirmImportSubmit" v-if="importPreviewData.validUserIdList && importPreviewData.validUserIdList.length > 0">继续</el-button>
|
||||
<el-button type="primary" @click="openImportPreview=false" v-else>确定</el-button>
|
||||
<el-button @click="openImportPreview=false">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deptTreeSelect } from '@/api/system/user'
|
||||
import { accInfoPageApi, accInfoSumPageApi } from "@/api/accountCenter/manager";
|
||||
import { updateAccRechargeSingleApi,checkAccRechargeBatchApi,updateAccRechargeBatchApi,clearAccRechargeSingleApi,checkClearAccRechargeBatchApi,clearAccRechargeBatchApi } from "@/api/accountCenter/butie";
|
||||
import { decryptWithSM4,encryptWithSM4 } from '@/utils/sm';
|
||||
export default {
|
||||
<script>
|
||||
import { deptTreeSelect } from '@/api/system/user'
|
||||
import { accInfoPageApi, accInfoSumPageApi } from "@/api/accountCenter/manager";
|
||||
import { updateAccRechargeSingleApi,checkAccRechargeBatchApi,updateAccRechargeBatchApi,clearAccRechargeSingleApi,checkClearAccRechargeBatchApi,clearAccRechargeBatchApi } from "@/api/accountCenter/butie";
|
||||
import { decryptWithSM4,encryptWithSM4 } from '@/utils/sm';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { downloadFileByUrl } from '@/utils/download'
|
||||
import { download } from '@/utils/request';
|
||||
import request from '@/utils/request';
|
||||
export default {
|
||||
name: "",
|
||||
dicts: ['sys_user_type'],
|
||||
data() {
|
||||
|
|
@ -626,7 +730,15 @@
|
|||
openResult:false,
|
||||
resultData:{},
|
||||
openResult2:false,
|
||||
resultData2:{}
|
||||
resultData2:{},
|
||||
// 导入充值相关
|
||||
openImport: false,
|
||||
fileList: [],
|
||||
uploadProgress: 0,
|
||||
uploading: false,
|
||||
// 补贴充值预览相关
|
||||
openImportPreview: false,
|
||||
importPreviewData: {}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
|
@ -925,7 +1037,235 @@
|
|||
},800)
|
||||
});
|
||||
},
|
||||
// 打开导入充值对话框
|
||||
handleImportRecharge() {
|
||||
this.openImport = true;
|
||||
this.fileList = [];
|
||||
this.uploadProgress = 0;
|
||||
this.uploading = false;
|
||||
this.importPreviewData = {};
|
||||
if (this.$refs.upload) {
|
||||
this.$refs.upload.clearFiles();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
},
|
||||
// 文件选择变化
|
||||
handleFileChange(file, fileList) {
|
||||
// 限制只能选择一个文件
|
||||
if (fileList.length > 1) {
|
||||
this.fileList = [fileList[fileList.length - 1]];
|
||||
this.$refs.upload.fileList = [fileList[fileList.length - 1]];
|
||||
} else {
|
||||
this.fileList = fileList;
|
||||
}
|
||||
},
|
||||
// 下载模板
|
||||
downloadTemplate() {
|
||||
let url = window.location.origin + '/template/批量补贴导入.xlsx';
|
||||
console.log(url)
|
||||
downloadFileByUrl(url)
|
||||
},
|
||||
// 上传前验证
|
||||
beforeUpload(file) {
|
||||
const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
|
||||
file.type === 'application/vnd.ms-excel' ||
|
||||
file.name.endsWith('.xlsx') ||
|
||||
file.name.endsWith('.xls');
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
|
||||
if (!isExcel) {
|
||||
this.$modal.msgError('只能上传 Excel 文件!');
|
||||
return false;
|
||||
}
|
||||
if (!isLt10M) {
|
||||
this.$modal.msgError('上传文件大小不能超过 10MB!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 上传进度
|
||||
handleUploadProgress(event, file, fileList) {
|
||||
this.uploadProgress = Math.round(event.percent);
|
||||
},
|
||||
// 上传成功
|
||||
handleUploadSuccess(response, file, fileList) {
|
||||
this.uploading = false;
|
||||
this.uploadProgress = 100;
|
||||
// 兼容不同的响应格式
|
||||
const result = response.data || response;
|
||||
if (response.code === 200 || response.code === 0 || !response.code) {
|
||||
this.uploadResult = {
|
||||
success: true,
|
||||
data: result,
|
||||
message: response.msg || response.message || '导入成功'
|
||||
};
|
||||
this.$modal.msgSuccess('导入成功!');
|
||||
// 刷新列表
|
||||
setTimeout(() => {
|
||||
this.getList();
|
||||
}, 500);
|
||||
} else {
|
||||
this.uploadResult = {
|
||||
success: false,
|
||||
data: result,
|
||||
message: response.msg || response.message || '导入失败'
|
||||
};
|
||||
this.$modal.msgError(response.msg || response.message || '导入失败');
|
||||
}
|
||||
},
|
||||
// 上传失败
|
||||
handleUploadError(err, file, fileList) {
|
||||
this.uploading = false;
|
||||
this.uploadProgress = 0;
|
||||
this.uploadResult = {
|
||||
success: false,
|
||||
message: err.message || '上传失败,请重试'
|
||||
};
|
||||
this.$modal.msgError('上传失败,请重试');
|
||||
},
|
||||
// 提交上传(校验)
|
||||
submitUpload() {
|
||||
if (this.fileList.length === 0) {
|
||||
this.$modal.msgError('请先选择要上传的文件!');
|
||||
return;
|
||||
}
|
||||
const file = this.fileList[0].raw || this.fileList[0];
|
||||
if (!file) {
|
||||
this.$modal.msgError('文件不存在,请重新选择!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证文件类型和大小
|
||||
const isExcel = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
|
||||
file.type === 'application/vnd.ms-excel' ||
|
||||
file.name.endsWith('.xlsx') ||
|
||||
file.name.endsWith('.xls');
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
|
||||
if (!isExcel) {
|
||||
this.$modal.msgError('只能上传 Excel 文件!');
|
||||
return;
|
||||
}
|
||||
if (!isLt10M) {
|
||||
this.$modal.msgError('上传文件大小不能超过 10MB!');
|
||||
return;
|
||||
}
|
||||
|
||||
this.uploading = true;
|
||||
this.uploadProgress = 0;
|
||||
|
||||
// 使用FormData上传文件
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 调用校验接口
|
||||
request({
|
||||
url: '/smart-canteen/acc/subsidy/import/add/check',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Authorization': 'Bearer ' + getToken()
|
||||
},
|
||||
onUploadProgress: (progressEvent) => {
|
||||
if (progressEvent.total) {
|
||||
this.uploadProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
}
|
||||
}
|
||||
}).then(response => {
|
||||
this.uploading = false;
|
||||
this.uploadProgress = 100;
|
||||
|
||||
// 处理响应数据
|
||||
const result = response.data || response;
|
||||
if (response.code === 200 || response.code === 0) {
|
||||
// 组装预览数据,兼容批量补贴预览展示
|
||||
const amountMap = {};
|
||||
(result.sucVoListMap || []).forEach(item => {
|
||||
const key = Object.keys(item || {})[0];
|
||||
if (key) {
|
||||
amountMap[key] = item[key];
|
||||
}
|
||||
});
|
||||
const successVoList = (result.accInfoVOList || []).map(item => {
|
||||
const phoneNumber = item.phoneNumber ? decryptWithSM4(item.phoneNumber) : item.phoneNumber;
|
||||
return {
|
||||
...item,
|
||||
phoneNumber,
|
||||
amount: amountMap[item.userId] || amountMap[item.userId + ''] || item.amount
|
||||
};
|
||||
});
|
||||
const invalidList = [
|
||||
...(result.errVOList || []),
|
||||
...(result.invalidVOList || [])
|
||||
].map(item => ({
|
||||
...item,
|
||||
phoneNumber: item.phoneNumber ? decryptWithSM4(item.phoneNumber) : item.phoneNumber
|
||||
}));
|
||||
this.importPreviewData = {
|
||||
...result,
|
||||
totalCount: result.totalUserSum,
|
||||
successVoList,
|
||||
invalidList
|
||||
};
|
||||
// 关闭导入对话框,打开预览对话框
|
||||
this.openImport = false;
|
||||
this.openImportPreview = true;
|
||||
} else {
|
||||
this.$modal.msgError(response.msg || response.message || '校验失败');
|
||||
}
|
||||
}).catch(error => {
|
||||
this.uploading = false;
|
||||
this.uploadProgress = 0;
|
||||
this.$modal.msgError(error.message || '上传失败,请重试');
|
||||
});
|
||||
},
|
||||
// 确认提交导入
|
||||
confirmImportSubmit() {
|
||||
if (!this.importPreviewData.validUserIdList || this.importPreviewData.validUserIdList.length === 0) {
|
||||
this.$modal.msgError('没有有效的记录可以提交!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 仅提交有效人员及金额明细
|
||||
const userIdAmountMap = (this.importPreviewData.successVoList || [])
|
||||
.filter(item => this.importPreviewData.validUserIdList.includes(String(item.userId)))
|
||||
.map(item => ({ [item.userId]: item.amount }));
|
||||
const param = {
|
||||
userIds: this.importPreviewData.validUserIdList,
|
||||
userIdAmountMap
|
||||
};
|
||||
|
||||
// 调用提交接口
|
||||
request({
|
||||
url: '/smart-canteen/acc/subsidy/batch/import/add',
|
||||
method: 'post',
|
||||
data: param,
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + getToken()
|
||||
}
|
||||
}).then(response => {
|
||||
if (response.code === 200 || response.code === 0) {
|
||||
this.$modal.msgSuccess("操作成功");
|
||||
this.openImportPreview = false;
|
||||
this.getList();
|
||||
} else {
|
||||
this.$modal.msgError(response.msg || response.message || '提交失败');
|
||||
}
|
||||
}).catch(error => {
|
||||
this.$modal.msgError(error.message || '提交失败,请重试');
|
||||
});
|
||||
},
|
||||
// 取消导入
|
||||
handleImportCancel() {
|
||||
this.openImport = false;
|
||||
this.fileList = [];
|
||||
this.uploadProgress = 0;
|
||||
this.uploading = false;
|
||||
this.importPreviewData = {};
|
||||
if (this.$refs.upload) {
|
||||
this.$refs.upload.clearFiles();
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue