## ADDED Requirements

### Requirement: IoT 卡列表展示绑定设备的虚拟号
`tb_iot_card` 表 SHALL 新增 `device_virtual_no VARCHAR(100) NOT NULL DEFAULT ''` 列，存储当前绑定设备的虚拟号快照。未绑定设备时该字段为空字符串。列表和详情接口 SHALL 在响应中返回 `device_virtual_no` 字段。

#### Scenario: 未绑定设备的卡响应 device_virtual_no 为空
- **WHEN** 请求 `GET /api/admin/iot-cards/standalone` 列表
- **THEN** `is_standalone = true` 的卡响应中 `device_virtual_no` 为空字符串 `""`

#### Scenario: 已绑定设备的卡响应包含设备虚拟号
- **WHEN** 请求 `GET /api/admin/iot-cards/standalone` 列表（不带 `is_standalone` 参数）
- **THEN** `is_standalone = false` 的卡也出现在结果中，且 `device_virtual_no` 等于绑定设备的 `virtual_no`

#### Scenario: 详情接口包含设备虚拟号
- **WHEN** 请求 `GET /api/admin/iot-cards/standalone/:iccid` 且该卡绑定了设备
- **THEN** 响应中 `device_virtual_no` 等于绑定设备的 `virtual_no`

### Requirement: `is_standalone` 作为可选查询参数
列表接口 `GET /api/admin/iot-cards/standalone` SHALL 接受可选布尔参数 `is_standalone`。不传时 SHALL 返回全部卡（含绑定设备的卡）；传 `true` 时仅返回未绑定设备的卡；传 `false` 时仅返回已绑定设备的卡。

#### Scenario: 不传 is_standalone 返回全部卡
- **WHEN** 请求列表且不携带 `is_standalone` 参数
- **THEN** 返回结果包含独立卡和绑定设备的卡

#### Scenario: 传 is_standalone=true 仅返回独立卡
- **WHEN** 请求列表携带 `is_standalone=true`
- **THEN** 返回结果只包含 `is_standalone = true` 的卡

#### Scenario: 传 is_standalone=false 仅返回绑定卡
- **WHEN** 请求列表携带 `is_standalone=false`
- **THEN** 返回结果只包含 `is_standalone = false` 的卡

### Requirement: 移除列表接口的 virtual_no 查询参数
`GET /api/admin/iot-cards/standalone` 请求 SHALL NOT 再接受 `virtual_no` 查询参数。

#### Scenario: 传入 virtual_no 参数不产生过滤效果
- **WHEN** 请求列表携带 `virtual_no=xxx`
- **THEN** 参数被忽略，接口正常返回全部卡（不报错，不过滤）

### Requirement: 绑定设备时快照写入 device_virtual_no
执行 `BindCard`（POST `/api/admin/devices/:virtual_no/cards`）成功后，系统 SHALL 将被绑定卡的 `device_virtual_no` 更新为设备的 `virtual_no`。

#### Scenario: 绑卡后卡的 device_virtual_no 被写入
- **WHEN** 成功调用 BindCard 将 IoT 卡绑定到设备
- **THEN** `tb_iot_card.device_virtual_no` = 对应设备的 `virtual_no`

### Requirement: 解绑设备时清空 device_virtual_no
执行 `UnbindCard`（DELETE `/api/admin/devices/:virtual_no/cards/:iccid`）成功后，系统 SHALL 将被解绑卡的 `device_virtual_no` 清空为空字符串。

#### Scenario: 解绑后卡的 device_virtual_no 被清空
- **WHEN** 成功调用 UnbindCard 将 IoT 卡从设备解绑
- **THEN** `tb_iot_card.device_virtual_no` = `""`

### Requirement: 设备导入时批量快照 device_virtual_no
设备导入任务处理成功绑定关系后，系统 SHALL 批量将被绑定卡的 `device_virtual_no` 更新为该设备的 `virtual_no`。

#### Scenario: 设备导入时绑定的卡 device_virtual_no 被写入
- **WHEN** 设备导入 Excel 中某行包含设备虚拟号和一组 ICCID，导入任务处理成功
- **THEN** 该组 ICCID 对应卡的 `device_virtual_no` = 设备的 `virtual_no`
