## 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` 需同步更新