Files
tms-erp-web/.workbuddy/memory/2026-07-27.md
赵忠林 8ff9f6bb66 feat(import): 优化货物类型导入失败明细及下载模板功能
- 引入 exceljs 动态加载,支持对后端失败明细 Excel 进行内容加工
- 导入失败明细取消标红错误字段,改为清晰错误原因文本说明
- 调整失败明细各列宽度,增加失败原因列换行提升可读性
- 失败明细原因列格式统一为“第N行:错误,规则”方式,便于定位
- 下载模板由后端生成改为前端本地生成,并内置示例数据
- 模板表头严格使用真实模板列名,示例数据涵盖一级及二级货物类型
- 模板编码列设置为文本格式避免前导零丢失,表头自动换行显示完整说明
2026-07-28 00:16:43 +08:00

10 KiB
Raw Permalink Blame History

2026-07-27 工作日志

开发环境启动与登录排查

  • 终止了遗留的 2888 端口 dev server 进程,清理端口占用。
  • .env.developmentVITE_APP_APIhttp://172.16.203.228:8000/api 改为 /api,让前端请求走 Vite 代理。
  • vite.config.mjs/api 代理 target 从 http://localhost 改为 http://172.16.203.228:8000,并去掉 rewrite(后端接口本身就在 /api 前缀下,不能去掉)。
  • 修复后发现登录无响应的根因:后端 CORS 返回 Access-Control-Allow-Origin: *,与 axios withCredentials: true 冲突,浏览器拦截所有跨域请求;走 Vite 代理后同源CORS 问题消失。
  • 启动 dev server 于 http://localhost:2888
  • 使用 agent-browser系统 Chrome打开登录页填入账号 admin / 密码 admin,成功触发行为验证码弹窗。
  • 行为验证码(滑块/拼图)需人工在浏览器窗口完成。

货物类型导入模板模拟数据

  • 模板:/Users/gxwebsoft/Downloads/货物类型导入模板.xlsx,单 Sheet「货物类型导入模板」表头 6 列:类型(必填)、上级货物类型、上级货物类型编码、货物类型(必填)、货物类型编码(必填)、备注。一级类型上级字段留空。
  • /Users/gxwebsoft/Downloads/货物类型导入模板_模拟数据.xlsx 生成 5 条模拟数据2 条一级 + 3 条二级,演示层级)。原模板保持不变。

货物类型模块(/base/cargo-type按需求完善

  • 需求:新增默认二级;类型/上级/编码在编辑查看禁编辑;一级隐藏上级字段、二级显示;同上级名称唯一 + 编码全局唯一交后端;提交失败展示后端提示。
  • 抽出 src/option/base/cargo-type.js,导出工厂 getCargoTypeOption(ctx),依赖组件的校验/change 通过 ctx 闭包访问(ctx.formctx.handleTypeLevelChange 等),避免 Option API 写死 this。
  • cargo-type.vue 改动import 该 option新增默认 typeLevel:2beforeOpen 设置 dialogTypeadd/edit/view上级下拉框 :disabled="dialogType!=='add' || typeLevel!==2";列配置加 editDisabled:true(类型/编码/上级编码控制编辑禁用view 模式 Avue 自动禁用其余字段。
  • 提交失败处理axios 拦截器已对非 200 弹 ElMessage(后端 msg故 rowSave/rowUpdate 的 error 仅 loading(),不再 console/重复 toast。
  • 导入失败明细下载已合规:src/utils/import-excel.jshandleImportExcel 已实现 content-type 区分 JSON/Excel、失败下载 货物类型导入失败明细时间.xlsx、错误提示businessName='货物类型'。
  • 注意:导入/下载模板由后端 /blade-system/cargo-type/import-cargo-type/export-template 控制,前端模板列名由后端决定,需后端保证与需求卡字段一致。

货物类型批量导入失败排查19:12

  • 失败明细 货物类型导入失败明细2026-07-27 19_12_24.xlsx5 条全部「请选择货物类型级别」。
  • 根因(数据问题,非前端代码):模拟数据「类型」列误填为业务分类 普通货物/冷链货物,但需求卡 REQ-CARGO-007/008 规定「类型」是货物类型级别,仅允许填 一级货物类型/二级货物类型;且编码误用字母(GOODS-ELEC-001),违反 REQ-CARGO-006「一级 2 位数字、二级 4 位数字」。
  • 已重造 货物类型导入模板_模拟数据.xlsx:类型改为一级/二级编码改为纯数字01/02 一级0101/0102/0201 二级继承父级前 2 位)。
  • 风险:二级行依赖一级行已存在,若后端按 DB 校验而非按文件顺序处理,二级行可能报「请选择上级货物类型」,建议先导入 2 条一级、再导入 3 条二级。

货物类型导入失败复查23:27

  • 第二版失败明细 货物类型导入失败明细2026-07-27 19_17_21.xlsx:类型已正确,但一级报「货物类型编码格式不正确」、二级报「请选择上级货物类型」。
  • 根因:编码列被存成数字(int),前导零丢失('01'→1、'0101'→101一级编码非 2 位、二级非 4 位;一级失败未入库 → 二级找不到上级。
  • 修复:写入时强制 C/E 列 number_format='@'(文本)保留前导零;编码 '01'/'02'、'0101'/'0102'/'0201'。
  • 为消除级联风险拆成两个文件货物类型导入_一级.xlsx(2条)、货物类型导入_二级.xlsx(3条),先导入一级再导入二级确保成功。

货物类型导入第三次复查23:30

  • 第三版失败明细一级导入也失败报「该货物类型编码已存在」01/02 已被占用。根因01/02 极可能是用户此前测试新增功能时手动建的,导入撞车;失败导入不写库,说明编码 pre-exist。
  • 同期发现 2888 dev server 进程退出lsof 无监听),导致 Vite 代理对 localhost:2888 全返回 502含根路径。已重启 pnpm dev(端口 2888proxy target 172.16.203.228:8000代理恢复 200。后端直连一直正常。
  • 改用新编码重造:一级 11/12电子产品/生鲜食品),二级 1101/1102父11、1201父12文本格式保留前导零。三份文件一级/二级/合并)已更新。
  • 结论:导入功能本身 OK问题一直是造数类型值、编码格式、编码冲突+ dev server 偶发退出。建议导入前确认 dev server 在跑。

导入失败明细标红 + 原因改写23:50

  • 需求:导入失败后,失败明细 Excel 中仅违规那一栏标红,且「导入失败原因」列改写为清晰格式,如第2行货物类型编码格式不正确一级2位数字二级4位数字
  • 现状:失败明细 Excel 此前是后端生成、前端 import-excel.js 直接 downloadXls 原样下载,无加工。
  • 改动:
    1. pnpm add exceljs4.4.0,运行时依赖;import('exceljs') 动态加载,不进主包)。
    2. src/utils/import-excel.jsopenImportDialog 增加可选 options.failDetailDecoratorhandleImportExcel 在 Excel 响应分支用 exceljs 读取后端失败明细 blob → 调用 decorator 加工(标红+改写原因)→ 再下载。未传 decorator 的模块保持原行为(向后兼容、通用)
    3. src/views/base/cargo-type.vue:新增模块级 decorateCargoTypeFailDetail(workbook)建立「表头列名→列号」映射按错误文本匹配规则7 类错误 → 标红列 + 规则说明),遍历数据行标红违规栏并将原因列改写为第N行错误规则handleImport 传入 { failDetailDecorator: decorateCargoTypeFailDetail }。标红填充色 FFFFC7CE淡红物理行号表头第1行数据第2行起
  • 验证Node + exceljs 跑 decorator 等价逻辑全 PASS标红列命中、原因格式正确vite 将 import('exceljs') 重写为浏览器版 chunk/node_modules/.vite/deps/exceljs.jsHTTP 2001.46MB),浏览器运行时无 polyfill 报错cargo-type.vue 与 import-excel.js 经 vite 编译均 200。
  • 注意decorator 依赖后端失败明细 Excel 的「导入失败原因」列文本与模板列名(类型/上级货物类型/上级货物类型编码/货物类型/货物类型编码/备注/导入失败原因)精确一致;若后端改列名需同步更新 CARGO_TYPE_FAIL_RULES 的 col 值。

导入失败明细改为「不标红 + 加列宽」00:08 次晨)

  • 用户反馈两点:① 不要标红,只写清错误原因即可;② 失败明细 xls 列太挤,需加宽。
  • 改动(同一对文件):
    • src/views/base/cargo-type.vue:删除 FAIL_RED_FILL 常量与所有 cell.fill 标红逻辑,仅保留原因列改写为第N行错误规则;新增 CARGO_TYPE_FAIL_COL_WIDTH 列宽映射类型14/上级货物类型16/上级货物类型编码20/货物类型16/货物类型编码16/备注18/导入失败原因60遍历 colMap 设置 ws.getColumn(n).width;原因列额外 alignment={wrapText:true,vertical:'top'} 提升可读性。
    • src/utils/import-excel.js:注释由「标红 / 改写原因列」改为中性「改写原因列、调整列宽等加工」。
  • 验证Node + exceljs 等价逻辑全 PASS无红色填充=、原因含「第N行」、导入失败原因列宽=60cargo-type.vue 与 import-excel.js vite 编译均 200FAIL_RED_FILL 残留=0。

下载模板改为「前端本地生成 + 带示例」00:11 次晨)

  • 需求:点击「下载模板」给的导入模板要自带一个数据示例(参照可正常导入的 货物类型导入模板_模拟数据.xlsx)。
  • 现状:handleTemplate 原调用后端 /blade-system/cargo-type/export-template 下载空模板(无示例)。
  • 改动 src/views/base/cargo-type.vuehandleTemplate:改为 import('exceljs') 本地生成模板,不再依赖后端空模板。
    • 表头严格使用真实模板列名(含 * 与括号说明):*类型 / 上级货物类型(如为一级则不需填写) / 上级货物类型编码(如为一级则不需填写) / *货物类型 / *货物类型编码 / 备注(与可正常导入的本地模板一致)。
    • 示例数据 2 条:一级 电子产品2/117 + 二级 手机2/11014父117演示层级取值与用户确认可导入的模拟数据一致。
    • 列宽加宽类型14/上级货物类型24/上级货物类型编码26/货物类型16/货物类型编码16/备注18编码列(3、5) numFmt='@' 文本格式防前导零丢失;表头行 wrapText 完整显示长说明。
    • 下载文件名仍为 货物类型导入模板.xlsxexportBlob 仍被 handleExport 使用import 不冗余。
  • 验证Node + exceljs 等价逻辑确认表头/示例行/列宽/文本格式正确(稀疏 eachCell 跳过空单元格导致一次断言误报按列号复核确认数据无误cargo-type.vue vite 编译 200。
  • 注意:示例行若被直接导入会创建 电子产品2/手机2 两条演示数据;用户应按需删除/替换示例再填自己的数据。