## Why

卡和设备的详情体系严重割裂：查询入口散落三端（Admin/H5/Personal）、停复机实现重复三处、详情接口仅返回骨架数据、网关数据纯透传无业务聚合。前端无法依赖现有接口渲染完整的资产详情页，客服也因缺少虚拟号统一入口而无法快速定位资产。本次重构一次性完成资产详情体系的建设，引入统一资产入口、合并停复机接口、建立设备保护期机制。

## What Changes

- **新增** 统一资产解析入口 `GET /api/admin/assets/resolve/:identifier`，支持通过虚拟号/ICCID/MSISDN/IMEI/SN 查找卡或设备
- **新增** 资产轻量状态查询 `GET /api/admin/assets/:asset_type/:id/realtime-status`（只查持久化数据，不调网关）
- **新增** 手动刷新接口 `POST /api/admin/assets/:asset_type/:id/refresh`（调网关写回 DB，设备类型含 Redis 限频）
- **新增** 套餐历史列表 `GET /api/admin/assets/:asset_type/:id/packages`
- **新增** 当前套餐查询 `GET /api/admin/assets/:asset_type/:id/current-package`
- **新增** 设备停机/复机 `POST /api/admin/assets/device/:device_id/stop|start`（含 1 小时保护期机制）
- **新增** 卡停机/复机 `POST /api/admin/assets/card/:iccid/stop|start`（含保护期感知）
- **新增** 轮询系统第四种任务：保护期一致性检查（独立任务类型，与流量检查同频触发）
- **数据库变更** `tb_device.device_no` → `virtual_no`（**BREAKING** 字段改名，全量更新代码）
- **数据库变更** `tb_personal_customer_device.device_no` → `virtual_no`（同上）
- **数据库变更** `tb_iot_card` 新增 `virtual_no` 字段（可空，全局唯一索引）
- **数据库变更** `tb_package` 新增 `virtual_ratio` 字段（套餐创建时计算并存储）
- **重命名** `SyncCardStatusFromGateway` → `RefreshCardDataFromGateway`，增强为完整同步 NetworkStatus/RealNameStatus/CurrentMonthUsageMB/LastSyncTime
- **修改** 现有卡 ICCID 导入：模板新增可选 `virtual_no` 列（只补空白，重复则全批失败）
- **修改** 现有设备导入：`device_no` 列头随字段改名同步更新为 `virtual_no`
- **删除** 废弃停复机接口（Admin 企业卡端 suspend/resume、H5 企业设备端 suspend/resume、旧 Admin 按 ICCID 停复机）
- 企业账号暂不支持 resolve 接口

## Capabilities

### New Capabilities

- `asset-resolve`：统一资产解析入口，通过任意标识符查找卡或设备，返回资产类型、ID、虚拟号、状态、套餐流量概况、保护期状态、绑定信息等中等聚合数据
- `asset-queries`：资产状态查询族，包含轻量实时状态查询（realtime-status）、手动刷新（refresh）、套餐历史列表（packages）、当前主套餐详情（current-package）
- `asset-suspend-resume`：卡和设备的停复机统一接口，含设备 1 小时保护期机制（Redis 存储）、未实名卡跳过逻辑、批量停机部分失败策略
- `polling-protect-consistency`：轮询系统新增的第四种任务，检查绑定设备保护期并强制同步卡的网络状态

### Modified Capabilities

- `iot-card`：新增 `virtual_no` 字段（可空，全局唯一索引）；IotCard 导入模板新增可选 virtual_no 列
- `device`：`device_no` 字段全量改名为 `virtual_no`（含 tb_personal_customer_device）；设备导入模板同步更新
- `iot-package`：`Package` 模型新增 `virtual_ratio` 字段，创建/更新套餐时自动计算存储

## Impact

**Handler 层**：
- 新增 `internal/handler/admin/asset.go`（9 个新接口）
- 删除 `internal/handler/admin/enterprise_card.go` 中的废弃停复机 Handler
- 删除 `internal/handler/h5/enterprise_device.go` 中的废弃停复机 Handler

**Service 层**：
- 新增 `internal/service/asset/service.go`（资产解析、状态聚合逻辑）
- 修改 `internal/service/iot_card/service.go`：`SyncCardStatusFromGateway` → `RefreshCardDataFromGateway`，增强为完整同步
- 修改 `internal/service/iot_card/stop_resume_service.go`：扩展手动停复机逻辑
- 修改 `internal/service/device/service.go`：新增设备停复机 + 保护期逻辑
- 修改 `internal/service/package/service.go`：创建/更新套餐时自动计算 virtual_ratio

**Store 层**：
- 修改 `internal/store/postgres/device_store.go`：`GetByIdentifier` 改用 `virtual_no`
- 修改 `internal/store/postgres/personal_customer_device_store.go`：`device_no` → `virtual_no`

**Model 层**：
- `internal/model/iot_card.go`：新增 `VirtualNo` 字段
- `internal/model/device.go`：`DeviceNo` → `VirtualNo`
- `internal/model/package.go`：新增 `VirtualRatio` 字段
- `internal/model/personal_customer_device.go`：`DeviceNo` → `VirtualNo`

**常量层**：
- `pkg/constants/redis.go`：新增 `RedisDeviceProtectKey`、`RedisDeviceRefreshCooldownKey`

**轮询层**：
- `internal/task/polling_handler.go`：新增保护期一致性检查任务处理函数

**数据库迁移**：3 张表的结构变更（device、iot_card、package）

**API 文档**：`cmd/api/docs.go` 和 `cmd/gendocs/main.go` 需同步更新
