5bb072223f
- 新增 `/business/loading-manage/detail` 路由,详情页由独立页面承载 - 统一将新增、编辑、详情和重新派单均采用独立表单页/详情页显示 - 修改组件内逻辑,新增 `isStandalonePage` 计算属性统一控制页面与弹窗切换 - 修改列表页链接及操作行为,详情和重新派单按钮跳转至对应独立页面 - 去除旧详情弹窗模式,相关样式调整支持独立页面自然滚动 - 添加路由监听,支持页面刷新和切换时正确初始化详情或表单数据 - 兼容老链接 `/business/loading-manage?detailId=x` 自动跳详情新路由 - 修正弹窗底栏样式,去除写死间距,统一由全局规则控制 - 代码中禁止顶层 scoped style 使用 `//` 注释,改用 `/* */` 避免编译错误
10 KiB
10 KiB
2026-09-17 工作日志
配载管理(loading-manage):弹窗全部改为独立表单页/详情页
- 需求:
/business/loading-manage不再用弹窗,改成与新增合同(/business/contract-manage/form?mode=add&name=新增合同管理)一致的独立页面。 - 现状:新增/编辑已经是独立页(组件内
isStandaloneFormPage+/business/loading-manage/form路由),但「详情」和「重新派单」仍是 el-dialog(用户截图即详情弹窗)。 - 改动(3 个文件):
src/router/views/index.js:新增/business/loading-manage/detail(name 配载单详情,meta.keepAlive:false, activeMenu:'/business/loading-manage'),组件仍是loading-manage.vue。src/views/business/loading-manage.vue:- computed 新增
isStandaloneDetailPage(path==='/business/loading-manage/detail')、isStandalonePage(form|detail 并集,作为隐藏列表容器的统一开关)、detailPageTitle、formPageDefaultTitle(add/edit/reassign 映射);isStandaloneFormPage放行mode=reassign。 - 模板中所有控制「是否独立页/是否弹窗」的
isStandaloneFormPage改为isStandalonePage;顶部标题按详情/表单取detailPageTitle/formPageTitle。 - 新增
gotoLoadingDetail(row)(push/detail?id=&name=配载单详情,替换「配载单号」链接与操作列「详情」)、gotoLoadingReassign(row)(push/form?mode=reassign&id=&name=重新派单)、initStandaloneDetailPage();initStandaloneFormPage模式透传 edit/reassign;openLoadingDialog对 add/edit/reassign 一律转独立页;closeLoadingDialog判据改isStandalonePage。 mounted/watch $route增加详情页分支(直接打开与页内切换都要 init);detail 分支除 id 变化外,dialogMode !== 'view'也重新 init(防止从表单页切详情时残留表单态)。- 兼容旧链接:
/business/loading-manage?detailId=x仍可用,会 replace 到详情页。 - 样式:底栏去掉写死的
gap:8px(全站统一 12px);页面模式的内容区解除max-height:78vh内嵌滚动盒 —— 原:global(.loading-manage-form-page .loading-manage-dialog__body)权重 (0,2,0) 低于 scoped 规则 (0,3,0) 一直没生效,改为.loading-manage-page .loading-manage-form-dialog.loading-manage-form-page .loading-manage-dialog__body(0,4,0),内容改随#avue-view自然滚动(与合同页一致)。
- computed 新增
src/views/business/components/waybill-manage-page.vue:openLoadingDetail由/business/loading-manage?detailId=改为 push/business/loading-manage/detail?id=&name=配载单详情。
- 校验:dev server(2889)单独编译 4 个模块均 HTTP 200(含 scoped scss);
vite build仍会在无关文件src/page/login/facelogin.vue被沙箱敏感内容保护中断。 - 踩坑:
<style scoped lang="scss">顶层写//注释会让该样式模块编译 500(Unexpected '/'. Escaping special characters with \ may help.),已实测确认;顶层必须用/* */。 - 未做:登录态无法在浏览器实测(无测试账号),需用户点
/business/loading-manage→ 详情/重新派单 自测;voucher-manage-detail跳配载时带的?loadingNo=参数本来就未被列表消费(历史遗留)。
运单管理详情:打卡时间轴改为按打卡顺序展示
- 文件:
src/views/business/components/waybill-manage-page.vue(详情页「执行详情 → 打卡详情」tab) - 需求:时间轴不再固定按流程节点顺序(发货/在途/到货/卸货/签收/回单),改为按打卡时间先后展示。
- 实现(不改后端、不改原始数据):
- 新增 computed
orderedWaybillPunchRecords:映射出punchedAt(毫秒时间戳)后排序 —— 已打卡记录按打卡时间升序排在前,未打卡记录保持后端返回的节点顺序排在其后;时间相同用原索引稳定排序。 - 新增 method
waybillPunchRecordTimestamp(record):punched === false或statusName === '未打卡'直接返回 null(防止后端返回计划时间造成误序);优先this.$dayjs(text).valueOf(),失败兜底new Date(text.replace(/-/g,'/'))(兼容 Safari)。 - 模板
el-timeline的v-for改用orderedWaybillPunchRecords;key由record.nodeCode || record.id || index改为${nodeCode||id||'punch'}-${index},避免同节点多次打卡(在途)时 key 重复。
- 新增 computed
- 校验:项目根目录临时脚本
_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 保持原值)。 - 校验:本机 dev(localhost: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(带 numFmtyyyy-MM-dd,WPS 显示为日期)。 - 根因:Service 用 BladeX
org.springblade.core.tool.utils.BeanUtil(继承 SpringBeanUtils)做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 用 BladeXDateUtil.fromDate,Func.isEmpty判空),不改 Excel 类字段类型(避免影响自定义 converter 与导入模板)。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 时间。
保险记录保额 -1 问题排查(未结案,待用户验证 DB 环境)
- 症状:新增弹窗保额不填 → 再开编辑弹窗显示 -1,触发「不能小于 0」校验。
- 已排除:前端(源码/dist 构建/git 全历史)、后端 tms-api + tms-erp-api-ws(源码/编译产物 javap/git 历史)均无任何 -1 赋值逻辑;保额为 formslot el-input,空值传 ''。
- 关键链路:编辑弹窗 beforeOpen 走
/detail接口(getOne 原生查询),不经过列表 SQL 的CASE WHEN insured_amount<0 THEN 0兜底——所以表格显示 0、弹窗显示原始值。 - 数据库截图(用户 Navicat):该行 insured_amount=NULL,全表无负数 → 说明用户浏览的库与后端实际连接的库不是同一个/DDL 不一致。系统存在「空数值=-1」惯例(MaintenanceRecordMapper 里程
CASE WHEN mileage=-1 THEN NULL;前端 waybill-manage.js/process-config.js 均有Number(v)===-1?'':v掩码)→ 后端真实库的 insured_amount 列默认值很可能是 -1,MP 插入排除 null 列 → 默认值 -1 入库。 - 待验证:在后端 Nacos 数据源指向的库执行
SHOW CREATE TABLE blade_insurance_record+SELECT insured_amount FROM blade_insurance_record WHERE policy_no='11111' AND vehicle_no='沪AE31312'。 - 修复方案(待确认):1) ALTER 列默认值改 NULL + UPDATE 存量负数为 NULL;2) 前端 beforeOpen 对 insuredAmount/premium 做 null/-1 → '' 归一(参照 waybill-manage normalizeNumericDisplayValue);3) 列表 SQL 的 CASE 兜底与 detail 不一致,可顺手统一。