# 套餐系列批量绑定选择方式优化

## 背景

运营人员为卡或设备设置套餐系列时，原接口只能提交当前页勾选的 `iccids` 或 `device_ids`。卡/设备列表存在分页限制，遇到按批次、店铺、运营商等条件批量处理时，需要跨页反复勾选，操作成本高。

## 涉及接口

- `PATCH /api/admin/iot-cards/series-binding`
- `PATCH /api/admin/devices/series-binding`

## 请求方式

两个接口都保留旧请求兼容：

```json
{
  "iccids": ["8986000000000000001"],
  "series_id": 12
}
```

```json
{
  "device_ids": [1001],
  "series_id": 12
}
```

新增 `selection_type` 后支持三种选择方式：

| selection_type | 卡接口 | 设备接口 | 用途 |
| --- | --- | --- | --- |
| `list` | `iccids` | `device_ids` | 显式列表选择，兼容旧勾选逻辑 |
| `range` | `iccid_start` + `iccid_end` | `virtual_no_start` + `virtual_no_end` | 按连续号段/虚拟号范围批量处理 |
| `filter` | 卡列表筛选条件 | 设备列表筛选条件 | 按完整筛选结果批量处理，不受分页限制 |

## 示例

按卡批次和运营商批量绑定：

```json
{
  "selection_type": "filter",
  "batch_no": "BATCH-2026-05",
  "carrier_id": 1,
  "series_id": 12
}
```

按 ICCID 号段清除绑定：

```json
{
  "selection_type": "range",
  "iccid_start": "8986000000000000001",
  "iccid_end": "8986000000000000999",
  "series_id": 0
}
```

按设备筛选条件批量绑定：

```json
{
  "selection_type": "filter",
  "shop_id": 10,
  "batch_no": "DEVICE-2026-05",
  "series_id": 12
}
```

## 权限与兼容性

- `series_id=0` 仍表示清除套餐系列关联。
- 代理用户仍只能操作自己店铺名下的卡/设备，保持旧接口权限语义不变。
- 代理用户设置非零 `series_id` 时，仍会校验当前店铺是否拥有该套餐系列授权。
- 旧请求不传 `selection_type` 时，只要传了 `iccids` 或 `device_ids`，后端仍按列表选择处理。

## 验证

- `go build ./...`
- `go vet ./...`
- `go run ./cmd/gendocs`
- `ccc index`
