Files
junhong_cmp_fiber/openspec/changes/excel-import-refactor/design.md
huang cd807e58e3
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m28s
feat: Excel 导入按列位置读取,IoT 卡导入支持卡业务类型
- 重写 parseCardRows:移除列名识别,固定跳过第1行表头,按 col0=ICCID、
  col1=MSISDN、col2=VirtualNo 取值,VirtualNo 升级为必填字段
- 重写 ParseDeviceExcel:移除 buildDeviceColumnIndex,IMEI 调整至第5列
  新增 MaxSimSlots 范围校验 [1,4],整行为空时不计入 total
- 删除 findCardColumns 和 buildDeviceColumnIndex 两个冗余函数
- ImportIotCardRequest 新增 card_category 字段(normal/industry,默认 normal)
- IotCardImportTask model 新增 card_category 字段
- 迁移 000111:tb_iot_card_import_task 新增 card_category 列
- CreateImportTask 将 req.CardCategory 写入任务,空串兜底 normal
- processBatch 改用 task.CardCategory 替代写死的 CardCategoryNormal
- ImportTaskResponse 新增 card_category 字段返回

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 17:16:31 +08:00

3.2 KiB
Raw Blame History

Context

当前 IoT 卡和设备的 Excel 导入依赖列名识别逻辑(findCardColumns / buildDeviceColumnIndex)。业务侧要求改用中文表头,但设备导入的大多数列名只支持英文,导致中文表头文件解析全部失败。

同时IoT 卡导入时 card_category 写死为 normal,无法在导入批次中指定行业卡。

Goals / Non-Goals

Goals:

  • Excel 导入不依赖表头内容,按固定列位置读取,支持任意语言表头
  • 锁定 IoT 卡和设备导入的列顺序为业务确认版本
  • IoT 卡导入支持批次级别的 card_category(行业卡/普通卡)

Non-Goals:

  • 不支持列顺序自定义(固定列位置就是合约)
  • 不支持每行独立设置 card_category(批次统一即可)
  • 不修改导入的其他业务逻辑(校验规则、权限等不变)

Decisions

决策1按列位置读取完全移除列名识别

选择: 直接按列索引取值,第一行永远跳过(表头行)。

备选方案: 在现有映射中添加中文列名别名。

理由: 中文别名方案需要为每个字段定义多套名称(中文/英文/变体),维护成本高且仍然脆弱(业务随时可能换叫法)。按位置读取更简单,也更明确——模板即契约,列顺序固定。

决策2card_category 放在请求参数而非 Excel 列

选择: 在 ImportIotCardRequestIotCardImportTask 中加 card_category 字段,不在 Excel 里加列。

理由: 业务现实是一批卡要么全是行业卡,要么全是普通卡,不会混批。前端用下拉选择比 Excel 里填枚举值更直观,也不影响 Excel 列顺序。

决策3card_category 默认值为 normal

选择: 不传时默认 normal(普通卡)。

理由: 存量接口调用不需要修改,向下兼容。

Risks / Trade-offs

  • [风险] 模板纪律性:按位置读取意味着列顺序必须严格匹配。用户如果自行调整 Excel 列顺序,数据会静默读错(没有报错提示)。→ 缓解:提供官方模板下载,文档中明确说明列顺序不可更改。
  • [权衡] 丢失了列名容错性:现有逻辑允许列顺序任意,改后不再支持。接受此代价,换取代码简单和中文支持。

Migration Plan

  1. 更新 pkg/utils/excel.go,替换解析逻辑(按列位置取值,删除 findCardColumns / buildDeviceColumnIndex
  2. tb_iot_card_import_task 创建迁移,新增 card_category VARCHAR(20) NOT NULL DEFAULT 'normal'
  3. 更新 DTOImportIotCardRequestcard_category、modelIotCardImportTaskCardCategory、serviceCreateImportTask 将请求字段写入 task、task handler创建 IoT 卡时使用 task.CardCategory 替代常量)
  4. 同步更新导入模板文件IoT 卡、设备的 .xlsx 模板列顺序需与新实现严格对齐;如模板由前端维护,需在变更交接时通知前端同步

说明:卡主表 tb_iot_card 早有 card_category 字段,本次迁移仅为批次级选择提供"载体列",让 Worker 从 DB 任务行读取批次类型,而非从 Asynq 载荷传递(保持现有"载荷只带 TaskID"的设计一致性)。

Open Questions

(无)