feat(vehicle): 归一化保险记录导入日期格式,修复设备台账批量删除按钮
- 保险记录批量导入时,前端读取 Excel 并规范日期格式为 YYYY-MM-DD,兼容多种日期写法 - 重写 `handleImport` 支持自定义上传逻辑,调用归一化处理后再上传文件 - 添加日期归一化相关方法,确保不合法或已标准格式保持原值 - 设备台账界面新增批量删除按钮及相关逻辑,支持多选数据批量删除并提示确认 - 补充导出含创建时间和更新时间的后端修复说明,避免导出时间字段为空问题 - 说明后端导出分配逻辑,强调导出字段由后端控制,前端修改导出列无效
This commit is contained in:
@@ -21,6 +21,15 @@
|
||||
@on-load="onLoad"
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
v-if="hasPermission('equipment_ledger_delete')"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
plain
|
||||
@click="handleDelete"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="hasPermission('equipment_ledger_import')"
|
||||
type="primary"
|
||||
@@ -310,6 +319,23 @@ export default {
|
||||
this.$message.success('操作成功');
|
||||
});
|
||||
},
|
||||
handleDelete() {
|
||||
if (this.selectionList.length === 0) {
|
||||
this.$message.warning('请选择至少一条数据');
|
||||
return;
|
||||
}
|
||||
this.$confirm('确认删除选中的数据?删除后将不可恢复!', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => remove(this.ids))
|
||||
.then(() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message.success('操作成功');
|
||||
this.$refs.crud.toggleSelection();
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
|
||||
@@ -217,7 +217,7 @@ import { getList as getOcrTemplateList } from '@/api/base/insurance-ocr-template
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { handleImportExcel } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { getUploadHeaders } from '@/utils/upload';
|
||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||
@@ -540,7 +540,96 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
openImportDialog(this, '保险记录');
|
||||
const column = this.findColumn(this.excelOption.column, 'excelFile');
|
||||
if (!column) {
|
||||
this.$message.error('导入配置异常,请稍后重试');
|
||||
return;
|
||||
}
|
||||
// 上传前先归一化日期列(2026-9-1 → 2026-09-01),兼容两种格式
|
||||
column.httpRequest = async (uploadOption, uploadColumn) => {
|
||||
try {
|
||||
const normalizedFile = await this.normalizeExcelDates(uploadOption.file);
|
||||
await handleImportExcel(
|
||||
this,
|
||||
{ ...uploadOption, file: normalizedFile },
|
||||
uploadColumn,
|
||||
'保险记录',
|
||||
null,
|
||||
{ timeout: 60000 }
|
||||
);
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '导入失败');
|
||||
if (typeof uploadOption.onError === 'function') {
|
||||
uploadOption.onError(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.excelBox = true;
|
||||
},
|
||||
// 读取 Excel,把指定日期列统一归一化为 YYYY-MM-DD,再写回新文件
|
||||
async normalizeExcelDates(file) {
|
||||
const rows = await this.readExcelRows(file);
|
||||
const dateHeaders = ['开始日期', '结束日期', '开票日期'];
|
||||
const headerIndex = (rows[0] || []).reduce((map, label, index) => {
|
||||
const key = String(label || '').trim();
|
||||
if (key) map[key] = index;
|
||||
return map;
|
||||
}, {});
|
||||
const targetIndexes = dateHeaders
|
||||
.map(label => headerIndex[label])
|
||||
.filter(index => index !== undefined);
|
||||
if (!targetIndexes.length) return file;
|
||||
rows.forEach((row, rowIndex) => {
|
||||
if (rowIndex === 0) return;
|
||||
targetIndexes.forEach(index => {
|
||||
if (row[index] !== undefined && row[index] !== '') {
|
||||
const normalized = this.normalizeDateString(String(row[index]));
|
||||
if (normalized) row[index] = normalized;
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.writeExcelFile(rows, file.name);
|
||||
},
|
||||
async readExcelRows(file) {
|
||||
const XLSX = await import('xlsx');
|
||||
const buffer = await file.arrayBuffer();
|
||||
const workbook = XLSX.read(buffer, { type: 'array', cellDates: false });
|
||||
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||
return XLSX.utils.sheet_to_json(worksheet, {
|
||||
header: 1,
|
||||
defval: '',
|
||||
raw: false,
|
||||
blankrows: false,
|
||||
});
|
||||
},
|
||||
async writeExcelFile(rows, fileName) {
|
||||
const XLSX = await import('xlsx');
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, XLSX.utils.aoa_to_sheet(rows), 'Sheet1');
|
||||
const binary = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
|
||||
return new File([binary], fileName || 'insurance-record.xlsx', {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
});
|
||||
},
|
||||
// 兼容 YYYY-M-D / YYYY-MM-DD / YYYY/M/D / YYYY.年.月.日,非法或已标准格式原样返回 null
|
||||
normalizeDateString(value) {
|
||||
const text = String(value || '').trim();
|
||||
if (!text) return null;
|
||||
const match = text.match(/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$/);
|
||||
if (!match) return null;
|
||||
const year = Number(match[1]);
|
||||
const month = Number(match[2]);
|
||||
const day = Number(match[3]);
|
||||
const date = new Date(year, month - 1, day);
|
||||
if (
|
||||
date.getFullYear() !== year ||
|
||||
date.getMonth() !== month - 1 ||
|
||||
date.getDate() !== day
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const pad = n => String(n).padStart(2, '0');
|
||||
return `${year}-${pad(month)}-${pad(day)}`;
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出保险记录数据?', '提示', {
|
||||
|
||||
Reference in New Issue
Block a user