feat: 新增数据库迁移,重命名 device_no 为 virtual_no,新增 iot_card.virtual_no 和 package.virtual_ratio 字段
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m3s

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-03-14 18:27:28 +08:00
parent b5147d1acb
commit b9c3875c08
77 changed files with 5832 additions and 2393 deletions

View File

@@ -107,4 +107,7 @@ func RegisterAdminRoutes(router fiber.Router, handlers *bootstrap.Handlers, midd
if handlers.PollingManualTrigger != nil {
registerPollingManualTriggerRoutes(authGroup, handlers.PollingManualTrigger, doc, basePath)
}
if handlers.Asset != nil {
registerAssetRoutes(authGroup, handlers.Asset, doc, basePath)
}
}

94
internal/routes/asset.go Normal file
View File

@@ -0,0 +1,94 @@
package routes
import (
"github.com/gofiber/fiber/v2"
"github.com/break/junhong_cmp_fiber/internal/handler/admin"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/pkg/openapi"
)
func registerAssetRoutes(router fiber.Router, handler *admin.AssetHandler, doc *openapi.Generator, basePath string) {
assets := router.Group("/assets")
groupPath := basePath + "/assets"
Register(assets, doc, groupPath, "GET", "/resolve/:identifier", handler.Resolve, RouteSpec{
Summary: "解析资产",
Description: "通过虚拟号/ICCID/IMEI/SN/MSISDN 解析设备或卡的完整详情。企业账号禁止调用。",
Tags: []string{"资产管理"},
Input: new(dto.AssetResolveRequest),
Output: new(dto.AssetResolveResponse),
Auth: true,
})
Register(assets, doc, groupPath, "GET", "/:asset_type/:id/realtime-status", handler.RealtimeStatus, RouteSpec{
Summary: "资产实时状态",
Description: "读取 DB/Redis 中的持久化状态不调网关。asset_type 为 card 或 device。",
Tags: []string{"资产管理"},
Input: new(dto.AssetTypeIDRequest),
Output: new(dto.AssetRealtimeStatusResponse),
Auth: true,
})
Register(assets, doc, groupPath, "POST", "/:asset_type/:id/refresh", handler.Refresh, RouteSpec{
Summary: "刷新资产状态",
Description: "主动调网关同步最新状态。设备有30秒冷却期。",
Tags: []string{"资产管理"},
Input: new(dto.AssetTypeIDRequest),
Output: new(dto.AssetRealtimeStatusResponse),
Auth: true,
})
Register(assets, doc, groupPath, "GET", "/:asset_type/:id/packages", handler.Packages, RouteSpec{
Summary: "资产套餐列表",
Description: "查询该资产所有套餐记录,含虚流量换算结果。",
Tags: []string{"资产管理"},
Input: new(dto.AssetTypeIDRequest),
Output: new([]dto.AssetPackageResponse),
Auth: true,
})
Register(assets, doc, groupPath, "GET", "/:asset_type/:id/current-package", handler.CurrentPackage, RouteSpec{
Summary: "当前生效套餐",
Tags: []string{"资产管理"},
Input: new(dto.AssetTypeIDRequest),
Output: new(dto.AssetPackageResponse),
Auth: true,
})
Register(assets, doc, groupPath, "POST", "/device/:device_id/stop", handler.StopDevice, RouteSpec{
Summary: "设备停机",
Description: "批量停机设备下所有已实名卡。设置1小时停机保护期。",
Tags: []string{"资产管理"},
Input: new(dto.DeviceIDRequest),
Output: new(dto.DeviceSuspendResponse),
Auth: true,
})
Register(assets, doc, groupPath, "POST", "/device/:device_id/start", handler.StartDevice, RouteSpec{
Summary: "设备复机",
Description: "批量复机设备下所有已实名卡。设置1小时复机保护期。",
Tags: []string{"资产管理"},
Input: new(dto.DeviceIDRequest),
Output: nil,
Auth: true,
})
Register(assets, doc, groupPath, "POST", "/card/:iccid/stop", handler.StopCard, RouteSpec{
Summary: "单卡停机",
Description: "手动停机单张卡通过ICCID。受设备保护期约束。",
Tags: []string{"资产管理"},
Input: new(dto.CardICCIDRequest),
Output: nil,
Auth: true,
})
Register(assets, doc, groupPath, "POST", "/card/:iccid/start", handler.StartCard, RouteSpec{
Summary: "单卡复机",
Description: "手动复机单张卡通过ICCID。受设备保护期约束。",
Tags: []string{"资产管理"},
Input: new(dto.CardICCIDRequest),
Output: nil,
Auth: true,
})
}

View File

@@ -21,23 +21,6 @@ func registerDeviceRoutes(router fiber.Router, handler *admin.DeviceHandler, imp
Auth: true,
})
Register(devices, doc, groupPath, "GET", "/:id", handler.GetByID, RouteSpec{
Summary: "设备详情",
Tags: []string{"设备管理"},
Input: new(dto.GetDeviceRequest),
Output: new(dto.DeviceResponse),
Auth: true,
})
Register(devices, doc, groupPath, "GET", "/by-identifier/:identifier", handler.GetByIdentifier, RouteSpec{
Summary: "通过标识符查询设备详情",
Description: "支持通过虚拟号(device_no)、IMEI、SN 任意一个标识符查询设备。",
Tags: []string{"设备管理"},
Input: new(dto.GetDeviceByIdentifierRequest),
Output: new(dto.DeviceResponse),
Auth: true,
})
Register(devices, doc, groupPath, "DELETE", "/:id", handler.Delete, RouteSpec{
Summary: "删除设备",
Description: "仅平台用户可操作。删除设备时自动解绑所有卡(卡不会被删除)。",
@@ -146,15 +129,6 @@ func registerDeviceRoutes(router fiber.Router, handler *admin.DeviceHandler, imp
Auth: true,
})
Register(devices, doc, groupPath, "GET", "/by-identifier/:identifier/gateway-info", handler.GetGatewayInfo, RouteSpec{
Summary: "查询设备信息",
Description: "通过虚拟号/IMEI/SN 查询设备网关信息。设备必须已配置 IMEI。",
Tags: []string{"设备管理"},
Input: new(dto.GetDeviceByIdentifierRequest),
Output: new(gateway.DeviceInfoResp),
Auth: true,
})
Register(devices, doc, groupPath, "GET", "/by-identifier/:identifier/gateway-slots", handler.GetGatewaySlots, RouteSpec{
Summary: "查询卡槽信息",
Description: "通过虚拟号/IMEI/SN 查询设备卡槽信息。设备必须已配置 IMEI。",

View File

@@ -36,19 +36,4 @@ func registerEnterpriseCardRoutes(router fiber.Router, handler *admin.Enterprise
Auth: true,
})
Register(enterprises, doc, groupPath, "POST", "/:id/cards/:card_id/suspend", handler.SuspendCard, RouteSpec{
Summary: "停机卡",
Tags: []string{"企业卡授权"},
Input: new(dto.SuspendCardReq),
Output: nil,
Auth: true,
})
Register(enterprises, doc, groupPath, "POST", "/:id/cards/:card_id/resume", handler.ResumeCard, RouteSpec{
Summary: "复机卡",
Tags: []string{"企业卡授权"},
Input: new(dto.ResumeCardReq),
Output: nil,
Auth: true,
})
}

View File

@@ -28,19 +28,4 @@ func registerH5EnterpriseDeviceRoutes(router fiber.Router, handler *h5.Enterpris
Auth: true,
})
Register(devices, doc, groupPath, "POST", "/:device_id/cards/:card_id/suspend", handler.SuspendCard, RouteSpec{
Summary: "停机卡H5",
Tags: []string{"H5-企业设备"},
Input: new(dto.DeviceCardOperationReq),
Output: new(dto.DeviceCardOperationResp),
Auth: true,
})
Register(devices, doc, groupPath, "POST", "/:device_id/cards/:card_id/resume", handler.ResumeCard, RouteSpec{
Summary: "复机卡H5",
Tags: []string{"H5-企业设备"},
Input: new(dto.DeviceCardOperationReq),
Output: new(dto.DeviceCardOperationResp),
Auth: true,
})
}

View File

@@ -21,14 +21,6 @@ func registerIotCardRoutes(router fiber.Router, handler *admin.IotCardHandler, i
Auth: true,
})
Register(iotCards, doc, groupPath, "GET", "/by-iccid/:iccid", handler.GetByICCID, RouteSpec{
Summary: "通过ICCID查询单卡详情",
Tags: []string{"IoT卡管理"},
Input: new(dto.GetIotCardByICCIDRequest),
Output: new(dto.IotCardDetailResponse),
Auth: true,
})
Register(iotCards, doc, groupPath, "POST", "/import", importHandler.Import, RouteSpec{
Summary: "批量导入IoT卡ICCID+MSISDN",
Description: `仅平台用户可操作。
@@ -109,30 +101,6 @@ func registerIotCardRoutes(router fiber.Router, handler *admin.IotCardHandler, i
Auth: true,
})
Register(iotCards, doc, groupPath, "GET", "/:iccid/gateway-status", handler.GetGatewayStatus, RouteSpec{
Summary: "查询卡实时状态",
Tags: []string{"IoT卡管理"},
Input: new(dto.GetIotCardByICCIDRequest),
Output: new(gateway.CardStatusResp),
Auth: true,
})
Register(iotCards, doc, groupPath, "GET", "/:iccid/gateway-flow", handler.GetGatewayFlow, RouteSpec{
Summary: "查询流量使用",
Tags: []string{"IoT卡管理"},
Input: new(dto.GetIotCardByICCIDRequest),
Output: new(gateway.FlowUsageResp),
Auth: true,
})
Register(iotCards, doc, groupPath, "GET", "/:iccid/gateway-realname", handler.GetGatewayRealname, RouteSpec{
Summary: "查询实名认证状态",
Tags: []string{"IoT卡管理"},
Input: new(dto.GetIotCardByICCIDRequest),
Output: new(gateway.RealnameStatusResp),
Auth: true,
})
Register(iotCards, doc, groupPath, "GET", "/:iccid/realname-link", handler.GetRealnameLink, RouteSpec{
Summary: "获取实名认证链接",
Tags: []string{"IoT卡管理"},
@@ -141,19 +109,4 @@ func registerIotCardRoutes(router fiber.Router, handler *admin.IotCardHandler, i
Auth: true,
})
Register(iotCards, doc, groupPath, "POST", "/:iccid/stop", handler.StopCard, RouteSpec{
Summary: "停机",
Tags: []string{"IoT卡管理"},
Input: new(dto.GetIotCardByICCIDRequest),
Output: nil,
Auth: true,
})
Register(iotCards, doc, groupPath, "POST", "/:iccid/start", handler.StartCard, RouteSpec{
Summary: "复机",
Tags: []string{"IoT卡管理"},
Input: new(dto.GetIotCardByICCIDRequest),
Output: nil,
Auth: true,
})
}