Files
junhong_cmp_fiber/internal/model/dto/device_dto.go
break 3b7b856e48
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m9s
企业授权增强与资产列表扩展
- 企业卡授权唯一约束:新增 DB 迁移(000154),卡级部分唯一索引防止同一张卡被多个企业同时持有,Service 层新增跨企业冲突检测
- 单卡列表新增 network_status 过滤参数
- 单卡/设备列表新增 asset_status、asset_status_name、generation 响应字段
- 单卡/设备列表新增企业维度过滤(authorized_enterprise_id、is_authorized_to_enterprise)及响应中企业授权信息(批量加载,无 N+1)
- 主钱包流水/退款列表新增 asset_identifier 精确过滤参数
- 企业卡授权/收回接口升级为三模式(list/range/filter),企业设备授权/收回升级为双模式(list/filter)
- 升级 sonic v1.14.2 → v1.15.2 以兼容 Go 1.26

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 16:23:03 +09:00

242 lines
17 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dto
import "time"
type ListDeviceRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码"`
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量"`
VirtualNo string `json:"virtual_no" query:"virtual_no" validate:"omitempty,max=100" maxLength:"100" description:"虚拟号(模糊查询)"`
IMEI string `json:"imei" query:"imei" validate:"omitempty,max=20" maxLength:"20" description:"设备IMEI(模糊查询)"`
DeviceName string `json:"device_name" query:"device_name" validate:"omitempty,max=255" maxLength:"255" description:"设备名称(模糊查询)"`
Status *int `json:"status" query:"status" validate:"omitempty,min=1,max=2" minimum:"1" maximum:"2" description:"归属状态 (1:在库, 2:已分销)"`
ActivationStatus *int `json:"activation_status" query:"activation_status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"激活状态 (0:未激活, 1:已激活;需有生效中主套餐且任意绑定卡已实名)"`
ShopID *uint `json:"shop_id" query:"shop_id" description:"店铺ID兼容旧参数单选NULL表示平台库存"`
ShopIDs []uint `json:"shop_ids" query:"shop_ids" validate:"omitempty,dive,min=1" description:"店铺ID列表多选"`
SeriesID *uint `json:"series_id" query:"series_id" description:"套餐系列ID"`
BatchNo string `json:"batch_no" query:"batch_no" validate:"omitempty,max=100" maxLength:"100" description:"批次号"`
DeviceType string `json:"device_type" query:"device_type" validate:"omitempty,max=50" maxLength:"50" description:"设备类型"`
Manufacturer string `json:"manufacturer" query:"manufacturer" validate:"omitempty,max=255" maxLength:"255" description:"制造商(模糊查询)"`
CreatedAtStart *time.Time `json:"created_at_start" query:"created_at_start" description:"创建时间起始"`
CreatedAtEnd *time.Time `json:"created_at_end" query:"created_at_end" description:"创建时间结束"`
HasActivePackage *bool `json:"has_active_package" query:"has_active_package" description:"是否有生效中的套餐true:有生效中主套餐, false:无生效中主套餐)"`
Keyword string `json:"keyword" query:"keyword" validate:"omitempty,max=100" maxLength:"100" description:"关键字搜索匹配虚拟号或IMEI(模糊查询与virtual_no/imei独立)"`
AuthorizedEnterpriseID *uint `json:"authorized_enterprise_id" query:"authorized_enterprise_id" description:"按有效授权企业ID过滤只返回当前授权给该企业的设备"`
IsAuthorizedToEnterprise *bool `json:"is_authorized_to_enterprise" query:"is_authorized_to_enterprise" description:"企业授权状态过滤 (true:已授权给某企业, false:未授权任何企业)"`
}
type DeviceResponse struct {
ID uint `json:"id" description:"设备ID"`
VirtualNo string `json:"virtual_no" description:"设备虚拟号/别名"`
IMEI string `json:"imei" description:"设备IMEI"`
SN string `json:"sn" description:"设备序列号"`
DeviceName string `json:"device_name" description:"设备名称"`
DeviceModel string `json:"device_model" description:"设备型号"`
DeviceType string `json:"device_type" description:"设备类型"`
MaxSimSlots int `json:"max_sim_slots" description:"最大插槽数"`
Manufacturer string `json:"manufacturer" description:"制造商"`
BatchNo string `json:"batch_no" description:"批次号"`
ShopID *uint `json:"shop_id" description:"店铺ID"`
ShopName string `json:"shop_name" description:"店铺名称"`
Status int `json:"status" description:"归属状态 (1:在库, 2:已分销)"`
StatusName string `json:"status_name" description:"归属状态名称(中文)"`
ActivationStatus int `json:"activation_status" description:"激活状态 (0:未激活, 1:已激活;需有生效中主套餐且任意绑定卡已实名)"`
ActivationStatusName string `json:"activation_status_name" description:"激活状态名称(中文)"`
BoundCardCount int `json:"bound_card_count" description:"已绑定卡数量"`
SeriesID *uint `json:"series_id" description:"套餐系列ID"`
SeriesName string `json:"series_name" description:"套餐系列名称"`
ActivatedAt *time.Time `json:"activated_at" description:"激活时间"`
RealnamePolicy string `json:"realname_policy" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"`
CreatedAt time.Time `json:"created_at" description:"创建时间"`
UpdatedAt time.Time `json:"updated_at" description:"更新时间"`
// 设备实时同步字段(由 sync-info 接口写入)
OnlineStatus int `json:"online_status" description:"在线状态0未知 1在线 2离线"`
LastOnlineTime *time.Time `json:"last_online_time" description:"最后在线时间"`
SoftwareVersion string `json:"software_version" description:"固件版本号"`
SwitchMode string `json:"switch_mode" description:"切卡模式0=自动1=手动"`
LastGatewaySyncAt *time.Time `json:"last_gateway_sync_at" description:"最后 sync-info 同步时间"`
// asset_status=3 表示该资产已换货且尚未执行"旧资产转新",不再流通
// generation>1 表示该资产历史上曾执行过换货后转新,目前仍在使用
AssetStatus int `json:"asset_status" description:"业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用)"`
AssetStatusName string `json:"asset_status_name" description:"业务状态名称(中文)"`
Generation int `json:"generation" description:"资产世代编号初始值1每次换货转新后+1"`
AuthorizedEnterpriseID *uint `json:"authorized_enterprise_id" description:"当前有效授权的企业ID未授权时为 null"`
AuthorizedEnterpriseName string `json:"authorized_enterprise_name" description:"当前有效授权的企业名称,未授权时为空字符串"`
}
type ListDeviceResponse struct {
List []*DeviceResponse `json:"items" description:"设备列表"`
Total int64 `json:"total" description:"总数"`
Page int `json:"page" description:"当前页码"`
PageSize int `json:"size" description:"每页数量"`
}
type GetDeviceRequest struct {
ID uint `path:"id" description:"设备ID" required:"true"`
}
// GetDeviceByIdentifierRequest 通过标识符查询设备请求
type GetDeviceByIdentifierRequest struct {
Identifier string `path:"identifier" description:"设备标识符(支持虚拟号/IMEI/SN)" required:"true"`
}
type DeleteDeviceRequest struct {
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
}
type ListDeviceCardsRequest struct {
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
}
type DeviceCardBindingResponse struct {
ID uint `json:"id" description:"绑定记录ID"`
SlotPosition int `json:"slot_position" description:"插槽位置 (1-4)"`
IotCardID uint `json:"iot_card_id" description:"IoT卡ID"`
ICCID string `json:"iccid" description:"ICCID"`
MSISDN string `json:"msisdn" description:"接入号"`
CarrierName string `json:"carrier_name" description:"运营商名称"`
Status int `json:"status" description:"卡状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)"`
StatusName string `json:"status_name" description:"卡状态名称(中文)"`
RealNameStatus int `json:"real_name_status" description:"实名状态 (0:未实名, 1:已实名)"`
RealNameStatusName string `json:"real_name_status_name" description:"实名状态名称(中文)"`
BindTime *time.Time `json:"bind_time" description:"绑定时间"`
IsCurrent bool `json:"is_current" description:"是否为当前使用的卡"`
RealnamePolicy string `json:"realname_policy" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"`
NetworkStatus int `json:"network_status" description:"网络状态0停机 1开机asset_type=card时有效"`
GatewayExtend string `json:"gateway_extend" description:"Gateway 卡状态扩展字段,原样返回上游 extend用于展示运营商侧实际停机原因"`
}
type ListDeviceCardsResponse struct {
Bindings []*DeviceCardBindingResponse `json:"bindings" description:"绑定列表"`
}
type BindCardToDeviceRequest struct {
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
ID uint `json:"-"`
IotCardID uint `json:"iot_card_id" validate:"required,min=1" required:"true" minimum:"1" description:"IoT卡ID"`
SlotPosition int `json:"slot_position" validate:"required,min=1,max=4" required:"true" minimum:"1" maximum:"4" description:"插槽位置 (1-4)"`
}
type BindCardToDeviceResponse struct {
BindingID uint `json:"binding_id" description:"绑定记录ID"`
Message string `json:"message" description:"提示信息"`
}
type UnbindCardFromDeviceRequest struct {
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
ICCID string `path:"iccid" description:"IoT卡ICCID" required:"true"`
}
type UnbindCardFromDeviceResponse struct {
Message string `json:"message" description:"提示信息"`
}
type AllocateDevicesRequest struct {
TargetShopID uint `json:"target_shop_id" validate:"required,min=1" required:"true" minimum:"1" description:"目标店铺ID"`
DeviceIDs []uint `json:"device_ids" validate:"required,min=1,max=100" required:"true" minItems:"1" maxItems:"100" description:"设备ID列表"`
Remark string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"备注"`
}
type AllocationDeviceFailedItem struct {
DeviceID uint `json:"device_id" description:"设备ID"`
VirtualNo string `json:"virtual_no" description:"设备虚拟号"`
Reason string `json:"reason" description:"失败原因"`
}
type AllocateDevicesResponse struct {
SuccessCount int `json:"success_count" description:"成功数量"`
FailCount int `json:"fail_count" description:"失败数量"`
FailedItems []AllocationDeviceFailedItem `json:"failed_items" description:"失败详情列表"`
}
type RecallDevicesRequest struct {
DeviceIDs []uint `json:"device_ids" validate:"required,min=1,max=100" required:"true" minItems:"1" maxItems:"100" description:"设备ID列表"`
Remark string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"备注"`
}
type RecallDevicesResponse struct {
SuccessCount int `json:"success_count" description:"成功数量"`
FailCount int `json:"fail_count" description:"失败数量"`
FailedItems []AllocationDeviceFailedItem `json:"failed_items" description:"失败详情列表"`
}
// BatchSetDeviceSeriesBindngRequest 批量设置设备的套餐系列绑定请求
type BatchSetDeviceSeriesBindngRequest struct {
SelectionType string `json:"selection_type" validate:"omitempty,oneof=list range filter" enum:"list,range,filter" description:"选设备方式 (list:设备ID列表, range:设备虚拟号范围, filter:筛选条件不传时兼容旧版设备ID列表)"`
DeviceIDs []uint `json:"device_ids" validate:"omitempty,max=1000,dive,required" maxItems:"1000" description:"设备ID列表selection_type=list时使用最多1000个"`
VirtualNoStart string `json:"virtual_no_start" validate:"omitempty,max=100" maxLength:"100" description:"起始设备虚拟号selection_type=range时使用"`
VirtualNoEnd string `json:"virtual_no_end" validate:"omitempty,max=100" maxLength:"100" description:"结束设备虚拟号selection_type=range时使用"`
VirtualNo string `json:"virtual_no" validate:"omitempty,max=100" maxLength:"100" description:"设备虚拟号模糊查询selection_type=filter时可选"`
DeviceName string `json:"device_name" validate:"omitempty,max=255" maxLength:"255" description:"设备名称模糊查询selection_type=filter时可选"`
Status *int `json:"status" validate:"omitempty,min=1,max=2" minimum:"1" maximum:"2" description:"归属状态 (1:在库, 2:已分销)selection_type=filter时可选"`
ActivationStatus *int `json:"activation_status" validate:"omitempty,min=0,max=1" minimum:"0" maximum:"1" description:"激活状态 (0:未激活, 1:已激活selection_type=filter时可选)"`
ShopID *uint `json:"shop_id" description:"店铺IDselection_type=filter时可选兼容旧参数单选"`
ShopIDs []uint `json:"shop_ids" validate:"omitempty,dive,min=1" description:"店铺ID列表selection_type=filter时可选多选"`
FilterSeriesID *uint `json:"filter_series_id" description:"当前绑定套餐系列IDselection_type=filter时可选目标套餐系列仍使用series_id"`
BatchNo string `json:"batch_no" validate:"omitempty,max=100" maxLength:"100" description:"批次号selection_type=filter时可选"`
DeviceType string `json:"device_type" validate:"omitempty,max=50" maxLength:"50" description:"设备类型selection_type=filter时可选"`
Manufacturer string `json:"manufacturer" validate:"omitempty,max=255" maxLength:"255" description:"制造商模糊查询selection_type=filter时可选"`
CreatedAtStart *time.Time `json:"created_at_start" description:"创建时间起始selection_type=filter时可选"`
CreatedAtEnd *time.Time `json:"created_at_end" description:"创建时间结束selection_type=filter时可选"`
SeriesID uint `json:"series_id" validate:"required,min=0" required:"true" minimum:"0" description:"目标套餐系列ID0表示清除关联"`
}
// DeviceSeriesBindngFailedItem 设备系列绑定失败项
type DeviceSeriesBindngFailedItem struct {
DeviceID uint `json:"device_id" description:"设备ID"`
VirtualNo string `json:"virtual_no" description:"设备虚拟号"`
Reason string `json:"reason" description:"失败原因"`
}
// BatchSetDeviceSeriesBindngResponse 批量设置设备的套餐系列绑定响应
type BatchSetDeviceSeriesBindngResponse struct {
SuccessCount int `json:"success_count" description:"成功数量"`
FailCount int `json:"fail_count" description:"失败数量"`
FailedItems []DeviceSeriesBindngFailedItem `json:"failed_items" description:"失败详情列表"`
}
// SetSpeedLimitRequest 设置设备限速请求
type SetSpeedLimitRequest struct {
Identifier string `path:"identifier" description:"设备标识符(支持虚拟号/IMEI/SN)" required:"true"`
SpeedLimit int `json:"speed_limit" validate:"required,min=1" required:"true" minimum:"1" description:"限速值KB/s"`
}
// SetWiFiRequest 设置设备 WiFi 请求
type SetWiFiRequest struct {
Identifier string `path:"identifier" description:"设备标识符(支持虚拟号/IMEI/SN)" required:"true"`
SSID string `json:"ssid" validate:"required,min=1,max=32" required:"true" minLength:"1" maxLength:"32" description:"WiFi 名称"`
Password string `json:"password,omitempty" description:"WiFi 密码"`
Enabled bool `json:"enabled" description:"启用状态"`
}
// SwitchCardRequest 切卡请求
type SwitchCardRequest struct {
Identifier string `path:"identifier" description:"设备标识符(支持虚拟号/IMEI/SN)" required:"true"`
TargetICCID string `json:"target_iccid" validate:"required" required:"true" description:"目标卡 ICCID"`
}
// SetSwitchModeRequest 设置切卡模式请求
type SetSwitchModeRequest struct {
Identifier string `path:"identifier" description:"设备标识符(支持虚拟号/IMEI/SN)" required:"true"`
SwitchMode *int `json:"switch_mode" validate:"required,oneof=0 1" required:"true" description:"切卡模式 (0:自动切卡, 1:手动切卡)"`
IotCardID uint `json:"iot_card_id" validate:"required,min=1" required:"true" minimum:"1" description:"目标卡资产ID必须是系统内状态正常且已实名的卡"`
}
type EmptyResponse struct {
Message string `json:"message,omitempty" description:"提示信息"`
}
// DeviceSuspendResponse 设备停机响应
type DeviceSuspendResponse struct {
SuccessCount int `json:"success_count" description:"成功停机卡数"`
FailCount int `json:"fail_count" description:"失败卡数"`
SkipCount int `json:"skip_count" description:"跳过卡数(未实名或已停机)"`
FailedItems []DeviceSuspendFailItem `json:"failed_items,omitempty" description:"失败详情"`
}
// DeviceSuspendFailItem 设备停机失败项
type DeviceSuspendFailItem struct {
ICCID string `json:"iccid" description:"卡ICCID"`
Reason string `json:"reason" description:"失败原因"`
}