feat(vehicle): 归一化保险记录导入日期格式,修复设备台账批量删除按钮

- 保险记录批量导入时,前端读取 Excel 并规范日期格式为 YYYY-MM-DD,兼容多种日期写法
- 重写 `handleImport` 支持自定义上传逻辑,调用归一化处理后再上传文件
- 添加日期归一化相关方法,确保不合法或已标准格式保持原值
- 设备台账界面新增批量删除按钮及相关逻辑,支持多选数据批量删除并提示确认
- 补充导出含创建时间和更新时间的后端修复说明,避免导出时间字段为空问题
- 说明后端导出分配逻辑,强调导出字段由后端控制,前端修改导出列无效
This commit is contained in:
2026-09-17 21:21:33 +08:00
parent 82fbb99593
commit 3d6e297147
4 changed files with 147 additions and 2 deletions
+24
View File
@@ -10,3 +10,27 @@
3. 模板 `el-timeline``v-for` 改用 `orderedWaybillPunchRecords``key``record.nodeCode || record.id || index` 改为 `${nodeCode||id||'punch'}-${index}`,避免同节点多次打卡(在途)时 key 重复。
- 校验:项目根目录临时脚本 `_verify-sfc.mjs`@vue/compiler-sfc parse + compileScript + compileTemplate)通过,已删除脚本。
- 注意:`getPunchRecords``src/api/business/waybill-manage.js``/punch-records`)后端未提供节点排序字段,排序只能在前端做。
## 保险记录批量导入:前端归一化日期格式
- 文件:`src/views/vehicle/insurance-record.vue`(仅此一个文件)
- 背景:保险记录批量导入是**后端驱动**——前端 `handleImport``importBlob` 把原始 Excel 直接 POST 到 `/blade-transport/insurance-record/import-insurance-record`,前端不解析行。后端只认 `2026-09-01``2026-9-1` 导入失败。
- 决策:用户选择**前端归一化**(不动后端)。把 `openImportDialog` 改为自写 `httpRequest`:用 `xlsx` 读取 Excel → 把日期列(开始日期/结束日期/开票日期)`2026-9-1` 归一为 `2026-09-01` → 重写成新 File 再交给 `handleImportExcel` 上传;复用其失败明细下载与成功刷新逻辑。无日期列时回退为原文件(行为不变)。
- 关键方法:`normalizeExcelDates` / `readExcelRows` / `writeExcelFile` / `normalizeDateString`(正则 `^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$`,用 `new Date` 校验合法性后补零;非法/已标准格式返回 null 保持原值)。
- 校验:本机 devlocalhost:2889)待用户部署自测。注意所有单元格经 `sheet_to_json(raw:false)` 后均为字符串,与 transport-plan-import 的客户端解析模式一致。
## 车/船务模块导出 xlsx「创建时间/更新时间」为空(后端 tms-api 修复)
- 现象:`/vehicle/insurance-record` 批量导出的 xlsx 里「创建时间」「更新时间」两列空白,「更新人」有值。用户要求车/船务模块所有页面统一修。
- 定位:导出由**后端**生成(前端只传查询参数,`exportColumns` 参数后端未使用)。实测 `~/Downloads/保险记录2026-09-17 20_46_08.xlsx`K/M 列单元格无 `<v>` 节点(值 null),E/F/J 日期列是数值 46266.0(带 numFmt `yyyy-MM-dd`WPS 显示为日期)。
- 根因:Service 用 BladeX `org.springblade.core.tool.utils.BeanUtil`**继承 Spring `BeanUtils`**)做 `copyProperties`。实体 `TenantEntity.createTime/updateTime``java.util.Date`,导出类字段是 `java.time.LocalDateTime` → Spring BeanUtils **类型不兼容静默跳过**,值为 null。而「更新人」是手动 `UserCache.getUserRealName(...)` 赋值的,所以有值。(Hutool 的 BeanUtil 能转 Date→LocalDateTime,但本项目用的是 BladeX 版本,不能。)
- 佐证:项目里正常的导出(Waybill / LoadingManage / CustomerArchive / CommonCargo)时间字段一律用 `java.util.Date`,并在 Service 里手动 `excel.setCreateTime(record.getCreateTime())`
- 修复(后端仓库 `/Users/gxwebsoft/JAVA/tms-api`blade-transport 模块):在 13 个导出方法里补显式赋值(Date→LocalDateTime 用 BladeX `DateUtil.fromDate``Func.isEmpty` 判空),不改 Excel 类字段类型(避免影响自定义 converter 与导入模板)。
```java
excel.setCreateTime(Func.isEmpty(x.getCreateTime()) ? null : DateUtil.fromDate(x.getCreateTime()));
excel.setUpdateTime(Func.isEmpty(x.getUpdateTime()) ? null : DateUtil.fromDate(x.getUpdateTime()));
```
- 涉及文件(13 个 Service + 1 新建 Excel 类 + 设备台账 controller/接口):InsuranceRecord / ViolationRecord / MaintenanceRecord / MaintenancePlan / TireReplacementRecord / AccidentRecord / AnnualInspectionRecord / MileageRecord / TransportChangeRecord / EtcRecord / OilElectricRecord / OtherExpenseRecord / EquipmentLedger。
- 设备台账特殊:原 `EquipmentLedgerExcel` 根本没有审计列(前端列表有),新建 `EquipmentLedgerExportExcel extends EquipmentLedgerExcel`(创建时间/更新人/更新时间),导出链路改用新类,**导入模板仍用旧类不受影响**。
- 未验证:本机无 mvn(仅 IDEA 内置),且离线模式缺 `blade-bom` 无法编译;用 javap 确认 `DateUtil.fromDate(Date)` 存在 + 逐行 grep 复核代替。需用户在 IDEA 里编译并重新部署后自测。
- 同类隐患(本次未改,其他模块):TemporaryCreditLimit、ProcessConfig、CommonRoute、CommonAddress、ContractManage、ProjectApply、ShippingTemplate 的导出 Excel 也是 LocalDateTime 且未手动 set 时间。
+6
View File
@@ -111,3 +111,9 @@
- option 由 prop `crudOption` 经 `cloneOption` 克隆。
- 独立表单页走 `PageAvueForm`,不包 el-dialog。
- 自定义详情弹窗:`config.detailButton=true` + `detailSections:[{title, fields}]`。
## 配套后端工程与导出字段约定
- **本前端工程 tms-erp-web-ws 对应的后端是 `/Users/gxwebsoft/JAVA/tms-api`**(不是 `tms-erp-api-ws`,后者功能滞后,排查时不要看错仓库)。
- 所有列表导出(批量导出/下载模板)由后端 FastExcel 生成,前端 `exportColumns` 参数后端未使用 —— 导出列以 `XxxExportExcel.java` 为准,前端改 option 不影响导出。
- BladeX `org.springblade.core.tool.utils.BeanUtil` **继承 Spring `BeanUtils`**:字段类型不兼容时**静默跳过**(实体 `Date createTime` → Excel `LocalDateTime createTime` 会丢值)。所以 Excel 导出的审计时间必须在 Service 里手动赋值,并用 `DateUtil.fromDate(...)` 做 Date→LocalDateTime 转换(`Func.isEmpty` 判空)。参考写法见 Waybill/InsuranceRecord 的 `exportXxx()`。
- 排查导出文件问题:用 Python 标准库 `zipfile` + 解析 `xl/worksheets/sheet1.xml`、`xl/styles.xml` 直接看单元格有无 `<v>` 与 numFmt,无需装 openpyxl。