Files
huang 21b73a750d
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m55s
c端当前套餐开始时间过期时间,以及excel导入字段
2026-05-06 09:57:58 +08:00

11 KiB
Raw Permalink Blame History

device-import Specification

Purpose

TBD - created by archiving change add-device-management. Update Purpose after archive.

Requirements

Requirement: 设备批量导入

系统 SHALL 提供设备批量导入功能,通过 Excel 文件导入设备并自动绑定卡,按固定列位置读取,表头行内容不影响解析结果,仅平台用户可操作。

API 端点: POST /api/admin/devices/import

请求参数:

  • batch_no: 批次号(必填)
  • file_key: 对象存储文件路径(必填,通过 /storage/upload-url 获取)

Excel 格式:

  • 文件格式: 仅支持 .xlsx (Excel 2007+)
  • Sheet: 读取第一个sheet或优先读取名为"导入数据"的sheet
  • 表头行: 第1行固定为表头永远跳过内容不限中文、英文均可
  • 列位置(固定,不可变):
    第1列索引0: 虚拟号(必填,全局唯一)
    第2列索引1: SN可选
    第3列索引2: 设备名称(可选)
    第4列索引3: 设备型号(可选)
    第5列索引4: 设备类型(可选)
    第6列索引5: IMEI可选
    第7列索引6: 制造商(可选)
    第8列索引7: 最大SIM槽数可选默认4范围1-4
    第9列索引8: 卡1 ICCID可选对应槽位1
    第10列索引9: 卡2 ICCID可选对应槽位2
    第11列索引10: 卡3 ICCID可选对应槽位3
    第12列索引11: 卡4 ICCID可选对应槽位4
    
  • 列格式: 所有列应设置为文本格式(避免数字被转为科学记数法)

失败原因文本:

  • VirtualNo 为空:"设备虚拟号(virtual_no)不能为空"
  • MaxSimSlots 越界:"最大SIM槽数必须在1-4之间"
  • ICCID 填写槽位超出最大槽位:"卡槽填写超出最大SIM槽数"

导入规则:

  • 按列索引取值,不识别列名,第一行永远跳过
  • 若整行目标列皆为空,视为空行跳过,不计入 total不计入失败
  • MaxSimSlots 为空或 0 回填默认值 4非空且不在 [1,4] 记录为失败
  • 卡1~卡4 的列位本身就是槽位定义,导入时必须保留原始列位信息,不得按非空 ICCID 顺序重排
  • 前置槽位允许为空;如果仅填写 卡2卡3,则表示设备只在槽位 2、3 上绑定卡
  • 任一已填写 ICCID 的槽位编号若大于 max_sim_slots,则该行导入失败
  • 导入的设备 shop_id = NULL平台库存
  • 导入的设备 status = 1在库
  • 设备号重复则该行跳过
  • ICCID 必须已存在于系统中(先导入卡,再导入设备)
  • ICCID 不存在则该行失败
  • ICCID 已绑定其他设备则该行失败
  • 导入通过异步任务处理,立即返回任务 ID

权限: 仅平台用户

响应:

  • task_id: 导入任务 ID
  • task_no: 任务编号
  • message: 提示信息

Scenario: 提交设备导入任务

  • WHEN 平台管理员上传 Excel 文件并提交导入请求
  • THEN 系统创建导入任务,返回任务 ID开始异步处理

Scenario: 中文表头正常导入

  • GIVEN Excel 文件第1行表头为 虚拟号 | SN | 设备名称 | 设备型号 | 设备类型 | IMEI | 制造商 | 最大SIM槽数 | 卡1 | 卡2 | 卡3 | 卡4
  • WHEN 系统解析该 Excel 文件
  • THEN 系统跳过第1行从第2行开始按列位置解析数据

Scenario: SN 列按固定顺序导入

  • GIVEN 某行第2列索引1填写 SN-001
  • WHEN 系统解析并导入该行
  • THEN 创建设备记录时 sn = "SN-001"

Scenario: 仅填写卡2和卡3时保留原始槽位

  • GIVEN 某行 最大SIM槽数 = 3
  • AND 卡1 为空,卡2 = ICCID_A卡3 = ICCID_B
  • WHEN 系统解析该行
  • THEN 系统将 ICCID_A 识别为槽位2的卡
  • AND 系统将 ICCID_B 识别为槽位3的卡
  • AND 系统不得将其重排为槽位1和槽位2

Scenario: 填写槽位超出最大SIM槽数

  • GIVEN 某行 最大SIM槽数 = 2
  • AND 卡3 = ICCID_C
  • WHEN 系统解析该行
  • THEN 该行导入失败
  • AND 失败原因为"卡槽填写超出最大SIM槽数"

Scenario: 代理尝试导入设备

  • WHEN 代理用户尝试导入设备
  • THEN 系统返回 403 错误,提示"无权限执行此操作"

Scenario: 文件格式错误

  • WHEN 平台管理员上传非 Excel 格式(.xlsx)的文件
  • THEN 系统创建任务但处理失败,任务状态为"失败",错误信息为"不支持的文件格式 .csv请上传Excel文件(.xlsx)"

Scenario: Excel结构错误

  • WHEN 平台管理员上传的Excel文件无工作表或无数据行
  • THEN 系统创建任务但处理失败,记录相应错误信息

Scenario: VirtualNo 为空的行记录为失败

  • WHEN Excel 中某行第1列虚拟号为空
  • THEN 该行计入失败(fail_count++),失败原因为"设备虚拟号(virtual_no)不能为空"
  • AND 其他合法行继续导入,不因此行中断

Requirement: 设备导入任务执行

系统 SHALL 异步执行设备导入任务,逐行处理 Excel 数据。

处理规则:

  • 打开Excel文件选择第一个sheet或优先"导入数据"sheet
  • 跳过第1行表头行从第2行开始按固定列位置解析数据
  • 若整行目标列皆为空,视为空行跳过,不计入 total
  • 逐行解析数据,并保留每个 ICCID 对应的原始槽位编号
  • 对每行数据执行以下校验:
    1. 设备号是否已存在(已存在则跳过)
    2. ICCID 是否存在于系统中(不存在则失败)
    3. ICCID 是否已绑定其他设备(已绑定则失败)
    4. 已填写 ICCID 的槽位是否超出该设备 max_sim_slots(超出则失败)
  • 校验通过后:
    1. 创建设备记录
    2. 按 ICCID 的原始槽位创建 slot_position 一致的设备-卡绑定记录
  • 记录处理结果(成功/跳过/失败)

任务状态:

  • 1: 待处理
  • 2: 处理中
  • 3: 已完成
  • 4: 失败

Scenario: 导入成功

  • WHEN Excel 中所有设备号不重复且 ICCID 有效
  • THEN 系统创建所有设备和绑定记录,任务状态为"已完成"

Scenario: 前置空槽导入成功

  • GIVEN 某行 卡1 为空,卡2 = ICCID_A卡3 = ICCID_B
  • WHEN 该行校验通过并执行导入
  • THEN 系统创建两条绑定记录
  • AND ICCID_Aslot_position = 2
  • AND ICCID_Bslot_position = 3

Scenario: 部分导入成功

  • WHEN Excel 中部分设备号已存在或部分 ICCID 无效
  • THEN 系统只导入有效的行,记录跳过和失败的详情,任务状态为"已完成"

Scenario: ICCID 不存在

  • WHEN Excel 中某行的 ICCID 在系统中不存在
  • THEN 该行导入失败,记录失败原因"ICCID 不存在"

Scenario: ICCID 已绑定其他设备

  • WHEN Excel 中某行的 ICCID 已绑定到其他设备
  • THEN 该行导入失败,记录失败原因"ICCID 已绑定其他设备"

Scenario: 设备号重复

  • WHEN Excel 中某行的设备号在系统中已存在
  • THEN 该行被跳过,记录跳过原因"设备号已存在"

Scenario: 填写槽位超出最大SIM槽数时任务记录失败

  • WHEN Excel 中某行声明 最大SIM槽数 = 2,但填写了 卡3卡4
  • THEN 该行计入失败(fail_count++
  • AND 失败明细中的 reason 字段为"卡槽填写超出最大SIM槽数"

Scenario: 导入任务结果报告包含 VirtualNo 失败原因

  • WHEN 导入任务处理完毕,含有 VirtualNo 为空的行
  • THEN 失败明细列表中,该行的 reason 字段为"设备虚拟号(virtual_no)不能为空"line 字段为对应行号

Requirement: 设备导入任务列表查询

系统 SHALL 提供设备导入任务列表查询功能,仅平台用户可操作。

API 端点: GET /api/admin/devices/import/tasks

查询条件:

  • status(可选): 任务状态 1-4
  • batch_no(可选): 批次号,模糊匹配
  • start_time(可选): 创建时间起始
  • end_time(可选): 创建时间结束

分页:

  • 默认每页 20 条,最大每页 100 条

响应字段:

  • id: 任务 ID
  • task_no: 任务编号
  • status: 任务状态
  • status_text: 任务状态文本
  • batch_no: 批次号
  • file_name: 文件名
  • total_count: 总数
  • success_count: 成功数
  • skip_count: 跳过数
  • fail_count: 失败数
  • started_at: 开始时间
  • completed_at: 完成时间
  • error_message: 错误信息
  • created_at: 创建时间

权限: 仅平台用户

Scenario: 查询导入任务列表

  • WHEN 平台管理员查询导入任务列表
  • THEN 系统返回所有导入任务,按创建时间倒序排列

Scenario: 按状态筛选任务

  • WHEN 平台管理员查询状态为 3已完成的任务
  • THEN 系统只返回已完成的任务

Scenario: 代理尝试查询导入任务

  • WHEN 代理用户尝试查询导入任务
  • THEN 系统返回 403 错误,提示"无权限执行此操作"

Requirement: 设备导入任务详情查询

系统 SHALL 提供设备导入任务详情查询功能,包含跳过和失败记录的详细信息。

API 端点: GET /api/admin/devices/import/tasks/:id

响应字段:

  • 包含任务列表的所有字段
  • skipped_items: 跳过记录详情列表
    • line: 行号
    • device_no: 设备号
    • reason: 跳过原因
  • failed_items: 失败记录详情列表
    • line: 行号
    • device_no: 设备号
    • reason: 失败原因

权限: 仅平台用户

Scenario: 查询导入任务详情

  • WHEN 平台管理员查询导入任务详情ID=1
  • THEN 系统返回任务的完整信息,包括跳过和失败记录详情

Scenario: 查询不存在的任务

  • WHEN 平台管理员查询不存在的任务ID=999
  • THEN 系统返回 404 错误,提示"导入任务不存在"

Requirement: 设备导入批次支持实名策略配置

系统 SHALL 在设备导入请求(ImportDeviceRequest)中支持 realname_policy 参数,以批次为单位指定导入设备的实名策略,默认为 none

请求字段新增

  • realname_policy:实名认证策略(枚举:none / before_order / after_order,可选,默认 none

任务字段新增

  • DeviceImportTask 新增 realname_policy 字段VARCHAR(20) NOT NULL DEFAULT 'none'

导入行为

  • 该批次导入的所有设备统一使用 realname_policy 的值写入 Device.realname_policy,不支持同一批次混用
  • 导入任务记录该字段用于审计

Scenario: 不传 realname_policy 时默认为 none

  • WHEN 设备导入请求未包含 realname_policy 字段
  • THEN 导入的所有设备 realname_policynone

Scenario: 指定 before_order 导入设备

  • WHEN 设备导入请求中 realname_policy = before_order
  • THEN 该批次导入的所有设备 realname_policy 均为 before_order

Scenario: 传入无效 realname_policy 被拒绝

  • WHEN 设备导入请求中 realname_policy = unknown
  • THEN 系统返回参数校验错误,提示实名策略值无效

Scenario: 设备导入任务响应返回 realname_policy

  • WHEN 管理员查询设备导入任务列表或详情
  • THEN 响应中包含 realname_policy 字段