feat(cargo-type): 优化货物类型导入失败明细的错误标记和提示

- 新增导入失败明细的加工函数,给违规字段自动标红并丰富错误提示信息
- 在导入弹窗调用中增加失败明细装饰器处理,提升用户体验
- 将货物类型组件option配置提取为单独模块,简化代码逻辑
- 调整货物类型表单禁用逻辑,避免非新增时的错误操作
- 移除原有表单校验函数,相关验证由导入失败明细装饰器替代
- 引入exceljs依赖以支持导入失败Excel文件的读取和修改
- 修复导入失败明细导出时的文件命名和内容加工问题
- 优化代码结构,提升维护性和可读性
This commit is contained in:
2026-07-27 23:58:29 +08:00
parent 1c7532e0de
commit e76cf70a20
7 changed files with 801 additions and 182 deletions

View File

@@ -15,14 +15,45 @@ const parseBlobJson = async blob => {
return text ? JSON.parse(text) : {};
};
export const openImportDialog = (vm, businessName, onSuccess) => {
/**
* 加工后端返回的导入失败明细 Excel。
* 若传入 failDetailDecorator函数则动态加载 exceljs 读取 blob 流,
* 交由 decorator 完成标红 / 改写原因列等加工,再导出新的 blob
* 否则原样返回 blob保持旧行为不影响未使用 decorator 的模块)。
* @param {Blob} blob 后端返回的失败明细 Excel 流
* @param {String} businessName 业务名称(如「货物类型」)
* @param {Function} [failDetailDecorator] async (workbook, { businessName }) => void
* @returns {Promise<Blob>}
*/
const decorateFailExcel = async (blob, businessName, failDetailDecorator) => {
if (typeof failDetailDecorator !== 'function') return blob;
const ExcelJS = await import('exceljs');
const buf = await blob.arrayBuffer();
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.load(buf);
await failDetailDecorator(workbook, { businessName });
const out = await workbook.xlsx.writeBuffer();
return new Blob([out], { type: 'application/vnd.ms-excel' });
};
/**
* 打开导入弹窗
* @param {Object} vm 组件实例
* @param {String} businessName 业务名称,用于失败明细文件命名
* @param {Function} [onSuccess] 导入成功回调
* @param {Object} [options] 扩展项
* @param {Function} [options.failDetailDecorator] 失败明细加工函数,用于对后端返回的失败 Excel 标红/改写原因
*/
export const openImportDialog = (vm, businessName, onSuccess, options = {}) => {
const { failDetailDecorator } = options;
const column = vm.findColumn(vm.excelOption.column, 'excelFile');
column.httpRequest = (option, uploadColumn) =>
handleImportExcel(vm, option, uploadColumn, businessName, onSuccess);
handleImportExcel(vm, option, uploadColumn, businessName, onSuccess, { failDetailDecorator });
vm.excelBox = true;
};
export const handleImportExcel = async (vm, option, column, businessName, onSuccess) => {
export const handleImportExcel = async (vm, option, column, businessName, onSuccess, options = {}) => {
const { failDetailDecorator } = options;
const file = option.file;
const fileName = file && file.name ? file.name.toLowerCase() : '';
if (!excelPattern.test(fileName)) {
@@ -37,8 +68,9 @@ export const handleImportExcel = async (vm, option, column, businessName, onSucc
try {
const res = await importBlob(column.action, file);
if (isExcelResponse(res)) {
const decorated = await decorateFailExcel(res.data, businessName, failDetailDecorator);
downloadXls(
res.data,
decorated,
`${businessName}导入失败明细${vm.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`
);
vm.$message.warning('部分数据导入失败,已下载失败明细');