## 1. Excel 按列位置读取(IoT 卡) - [x] 1.1 重写 `parseCardRows`:移除 `findCardColumns` 调用,第1行固定跳过,按 col0=ICCID、col1=MSISDN、col2=VirtualNo 取值 - [x] 1.2 保留空行跳过逻辑:若 ICCID、MSISDN、VirtualNo 三列皆为空,`continue` 且不计入 total(与原实现一致,避免尾部空行被判失败) - [x] 1.3 对齐失败原因文案,与 spec 的 Scenario 完全一致("ICCID 不能为空"/"MSISDN 不能为空"/"虚拟号(virtual_no)不能为空",注意半角空格) - [x] 1.4 删除 `findCardColumns` 函数 ## 2. Excel 按列位置读取(设备) - [x] 2.1 重写 `ParseDeviceExcel`:移除 `buildDeviceColumnIndex` 调用,第1行固定跳过,按确认列顺序取值(col0=虚拟号、col1=设备名称、col2=设备型号、col3=设备类型、col4=IMEI、col5=制造商、col6=最大SIM槽数、col7~10=卡1~4) - [x] 2.2 保留空行跳过逻辑:若整行目标列皆为空,`continue` 且不计入 total - [x] 2.3 `MaxSimSlots` 范围校验:读取后若不在 [1,4],计入失败(原因:"最大SIM槽数必须在1-4之间");为空/0 时回填默认值 4 - [x] 2.4 删除 `buildDeviceColumnIndex` 函数 ## 3. IoT 卡导入支持卡业务类型 - [x] 3.1 `ImportIotCardRequest` DTO 新增 `CardCategory string` 字段,tag:`json:"card_category" validate:"omitempty,oneof=normal industry" description:"卡业务类型 (normal:普通卡, industry:行业卡),默认 normal"` - [x] 3.2 `IotCardImportTask` model 新增 `CardCategory` 字段,gorm tag:`column:card_category;type:varchar(20);default:normal;not null;comment:卡业务类型(normal/industry)` - [x] 3.3 创建数据库迁移 `000111_add_card_category_to_import_task`(up/down 成对),为 `tb_iot_card_import_task` 新增 `card_category VARCHAR(20) NOT NULL DEFAULT 'normal'` 列并加 COMMENT - [x] 3.4 修改 `internal/service/iot_card_import/service.go CreateImportTask`:构建 `IotCardImportTask` 时写入 `CardCategory`,空串时兜底为 `constants.CardCategoryNormal` - [x] 3.5 修改 `internal/task/iot_card_import.go` 的 `processBatch`:将写死的 `CardCategory: constants.CardCategoryNormal` 改为 `task.CardCategory` - [x] 3.6 更新 `ImportTaskResponse` DTO 增加 `card_category` 字段返回,便于列表/详情查询时展示批次类型 ## 4. 模板文件同步 - [x] 4.1 更新仓库内(若有)的 IoT 卡、设备导入模板 `.xlsx`,使列顺序与新实现完全一致;若模板由前端维护,在提案交接时通知前端同步更新下载模板 ## 5. 手动验证 - [ ] 5.1 准备中文表头的 IoT 卡样例 xlsx(含正常行、空行、ICCID/MSISDN/虚拟号为空行、虚拟号重复行),调用 `POST /api/admin/iot-cards/import` 指定 `card_category=industry`,用 PostgreSQL MCP 验证 `tb_iot_card_import_task.card_category='industry'` 且新增卡的 `tb_iot_card.card_category='industry'` - [ ] 5.2 准备中文表头的设备样例 xlsx(含 IMEI 在第5列),调用 `POST /api/admin/devices/import`,验证成功/失败行数与失败原因文案 - [ ] 5.3 不传 `card_category` 时验证默认值为 `normal` - [ ] 5.4 传入 `card_category=invalid` 时验证返回参数校验错误