新增三个同步时间字段

This commit is contained in:
2026-05-18 10:47:07 +08:00
parent 480d4c4583
commit af5a21ed1e
6 changed files with 78 additions and 50 deletions

View File

@@ -126,6 +126,9 @@
| `real_name_status` | int | 实名状态(仅 card | | `real_name_status` | int | 实名状态(仅 card |
| `current_month_usage_mb` | float64 | 本月已用流量 MB仅 card | | `current_month_usage_mb` | float64 | 本月已用流量 MB仅 card |
| `last_sync_time` | time | 最后同步时间(仅 card | | `last_sync_time` | time | 最后同步时间(仅 card |
| `last_data_check_at` | time | 最后一次流量检查时间(仅 card |
| `last_real_name_check_at` | time | 最后一次实名检查时间(仅 card |
| `last_card_status_check_at` | time | 最后一次卡状态检查时间(仅 card |
| `device_protect_status` | string | 保护期:`none` / `stop` / `start`(仅 device | | `device_protect_status` | string | 保护期:`none` / `stop` / `start`(仅 device |
| `cards[]` | array | 所有绑定卡的状态(仅 device同 resolve 的 cards 结构 | | `cards[]` | array | 所有绑定卡的状态(仅 device同 resolve 的 cards 结构 |

View File

@@ -71,35 +71,42 @@ type AssetResolveResponse struct {
// BoundCardInfo 设备绑定的卡信息 // BoundCardInfo 设备绑定的卡信息
type BoundCardInfo struct { type BoundCardInfo struct {
CardID uint `json:"card_id" description:"卡ID"` CardID uint `json:"card_id" description:"卡ID"`
ICCID string `json:"iccid" description:"ICCID"` ICCID string `json:"iccid" description:"ICCID"`
MSISDN string `json:"msisdn,omitempty" description:"手机号"` MSISDN string `json:"msisdn,omitempty" description:"手机号"`
NetworkStatus int `json:"network_status" description:"网络状态0停机 1开机"` NetworkStatus int `json:"network_status" description:"网络状态0停机 1开机"`
RealNameStatus int `json:"real_name_status" description:"实名状态0未实名 1已实名"` RealNameStatus int `json:"real_name_status" description:"实名状态0未实名 1已实名"`
RealNameAt *time.Time `json:"real_name_at" description:"该卡最近一次完成实名的时间,未实名时为 null"` RealNameAt *time.Time `json:"real_name_at" description:"该卡最近一次完成实名的时间,未实名时为 null"`
SlotPosition int `json:"slot_position,omitempty" description:"插槽位置"` SlotPosition int `json:"slot_position,omitempty" description:"插槽位置"`
IsCurrent bool `json:"is_current" description:"是否为当前使用的卡"` IsCurrent bool `json:"is_current" description:"是否为当前使用的卡"`
CarrierID uint `json:"carrier_id,omitempty" description:"运营商ID"` CarrierID uint `json:"carrier_id,omitempty" description:"运营商ID"`
CarrierType string `json:"carrier_type,omitempty" description:"运营商类型"` CarrierType string `json:"carrier_type,omitempty" description:"运营商类型"`
CarrierName string `json:"carrier_name,omitempty" description:"运营商名称"` CarrierName string `json:"carrier_name,omitempty" description:"运营商名称"`
RealnamePolicy string `json:"realname_policy" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"` RealnamePolicy string `json:"realname_policy" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"`
GatewayExtend string `json:"gateway_extend" description:"Gateway 卡状态扩展字段,原样返回上游 extend用于展示运营商侧实际停机原因"` GatewayExtend string `json:"gateway_extend" description:"Gateway 卡状态扩展字段,原样返回上游 extend用于展示运营商侧实际停机原因"`
LastSyncTime *time.Time `json:"last_sync_time" description:"最后同步时间"`
LastDataCheckAt *time.Time `json:"last_data_check_at" description:"最后一次流量检查时间"`
LastRealNameCheckAt *time.Time `json:"last_real_name_check_at" description:"最后一次实名检查时间"`
LastCardStatusCheckAt *time.Time `json:"last_card_status_check_at" description:"最后一次卡状态检查时间"`
} }
// AssetRealtimeStatusResponse 资产实时状态只读DB/Redis // AssetRealtimeStatusResponse 资产实时状态只读DB/Redis
type AssetRealtimeStatusResponse struct { type AssetRealtimeStatusResponse struct {
AssetType string `json:"asset_type" description:"资产类型card 或 device"` AssetType string `json:"asset_type" description:"资产类型card 或 device"`
AssetID uint `json:"asset_id" description:"资产ID"` AssetID uint `json:"asset_id" description:"资产ID"`
NetworkStatus int `json:"network_status" description:"网络状态asset_type=card时有效0停机 1开机"` NetworkStatus int `json:"network_status" description:"网络状态asset_type=card时有效0停机 1开机"`
GatewayExtend string `json:"gateway_extend" description:"Gateway 卡状态扩展字段,原样返回上游 extend用于展示运营商侧实际停机原因"` GatewayExtend string `json:"gateway_extend" description:"Gateway 卡状态扩展字段,原样返回上游 extend用于展示运营商侧实际停机原因"`
RealNameStatus int `json:"real_name_status" description:"实名状态asset_type=card时有效0未实名 1已实名"` RealNameStatus int `json:"real_name_status" description:"实名状态asset_type=card时有效0未实名 1已实名"`
RealnamePolicy string `json:"realname_policy,omitempty" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"` RealnamePolicy string `json:"realname_policy,omitempty" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"`
CurrentMonthUsageMB float64 `json:"current_month_usage_mb,omitempty" description:"系统自然月累计流量(MBasset_type=card时有效不等于运营商周期口径)"` CurrentMonthUsageMB float64 `json:"current_month_usage_mb,omitempty" description:"系统自然月累计流量(MBasset_type=card时有效不等于运营商周期口径)"`
LastGatewayReadingMB float64 `json:"last_gateway_reading_mb,omitempty" description:"运营商当前周期累计流量读数(MBasset_type=card时有效运营商口径展示建议读取该字段)"` LastGatewayReadingMB float64 `json:"last_gateway_reading_mb,omitempty" description:"运营商当前周期累计流量读数(MBasset_type=card时有效运营商口径展示建议读取该字段)"`
LastSyncTime *time.Time `json:"last_sync_time,omitempty" description:"最后同步时间asset_type=card时有效"` LastSyncTime *time.Time `json:"last_sync_time" description:"最后同步时间asset_type=card时有效"`
DeviceProtectStatus string `json:"device_protect_status,omitempty" description:"保护期状态asset_type=device时有效none/stop/start"` LastDataCheckAt *time.Time `json:"last_data_check_at" description:"最后一次流量检查时间asset_type=card时有效"`
Cards []BoundCardInfo `json:"cards,omitempty" description:"绑定卡状态列表asset_type=device时有效)"` LastRealNameCheckAt *time.Time `json:"last_real_name_check_at" description:"最后一次实名检查时间asset_type=card时有效)"`
DeviceRealtime *DeviceGatewayInfo `json:"device_realtime" description:"设备实时状态(来自 Gateway sync-info始终返回失败时仅含 gateway_msg"` LastCardStatusCheckAt *time.Time `json:"last_card_status_check_at" description:"最后一次卡状态检查时间asset_type=card时有效"`
DeviceProtectStatus string `json:"device_protect_status,omitempty" description:"保护期状态asset_type=device时有效none/stop/start"`
Cards []BoundCardInfo `json:"cards,omitempty" description:"绑定卡状态列表asset_type=device时有效"`
DeviceRealtime *DeviceGatewayInfo `json:"device_realtime" description:"设备实时状态(来自 Gateway sync-info始终返回失败时仅含 gateway_msg"`
} }
// AssetPackageResponse 资产套餐信息 // AssetPackageResponse 资产套餐信息

View File

@@ -188,19 +188,23 @@ func (s *Service) buildDeviceResolveResponse(ctx context.Context, device *model.
} }
for _, c := range cards { for _, c := range cards {
resp.Cards = append(resp.Cards, dto.BoundCardInfo{ resp.Cards = append(resp.Cards, dto.BoundCardInfo{
CardID: c.ID, CardID: c.ID,
ICCID: c.ICCID, ICCID: c.ICCID,
MSISDN: c.MSISDN, MSISDN: c.MSISDN,
NetworkStatus: c.NetworkStatus, NetworkStatus: c.NetworkStatus,
RealNameStatus: c.RealNameStatus, RealNameStatus: c.RealNameStatus,
RealNameAt: c.FirstRealnameAt, RealNameAt: c.FirstRealnameAt,
SlotPosition: slotMap[c.ID], SlotPosition: slotMap[c.ID],
IsCurrent: isCurrentMap[c.ID], IsCurrent: isCurrentMap[c.ID],
CarrierID: c.CarrierID, CarrierID: c.CarrierID,
CarrierType: c.CarrierType, CarrierType: c.CarrierType,
CarrierName: c.CarrierName, CarrierName: c.CarrierName,
RealnamePolicy: c.RealnamePolicy, RealnamePolicy: c.RealnamePolicy,
GatewayExtend: c.GatewayExtend, GatewayExtend: c.GatewayExtend,
LastSyncTime: c.LastSyncTime,
LastDataCheckAt: c.LastDataCheckAt,
LastRealNameCheckAt: c.LastRealNameCheckAt,
LastCardStatusCheckAt: c.LastCardStatusCheckAt,
}) })
} }
@@ -368,6 +372,9 @@ func (s *Service) GetRealtimeStatus(ctx context.Context, assetType string, id ui
resp.CurrentMonthUsageMB = card.CurrentMonthUsageMB resp.CurrentMonthUsageMB = card.CurrentMonthUsageMB
resp.LastGatewayReadingMB = card.LastGatewayReadingMB resp.LastGatewayReadingMB = card.LastGatewayReadingMB
resp.LastSyncTime = card.LastSyncTime resp.LastSyncTime = card.LastSyncTime
resp.LastDataCheckAt = card.LastDataCheckAt
resp.LastRealNameCheckAt = card.LastRealNameCheckAt
resp.LastCardStatusCheckAt = card.LastCardStatusCheckAt
case "device": case "device":
// 查绑定卡状态列表 // 查绑定卡状态列表
@@ -389,18 +396,22 @@ func (s *Service) GetRealtimeStatus(ctx context.Context, assetType string, id ui
} }
for _, c := range cards { for _, c := range cards {
resp.Cards = append(resp.Cards, dto.BoundCardInfo{ resp.Cards = append(resp.Cards, dto.BoundCardInfo{
CardID: c.ID, CardID: c.ID,
ICCID: c.ICCID, ICCID: c.ICCID,
MSISDN: c.MSISDN, MSISDN: c.MSISDN,
NetworkStatus: c.NetworkStatus, NetworkStatus: c.NetworkStatus,
RealNameStatus: c.RealNameStatus, RealNameStatus: c.RealNameStatus,
SlotPosition: slotMap[c.ID], SlotPosition: slotMap[c.ID],
IsCurrent: isCurrentMap[c.ID], IsCurrent: isCurrentMap[c.ID],
CarrierID: c.CarrierID, CarrierID: c.CarrierID,
CarrierType: c.CarrierType, CarrierType: c.CarrierType,
CarrierName: c.CarrierName, CarrierName: c.CarrierName,
RealnamePolicy: c.RealnamePolicy, RealnamePolicy: c.RealnamePolicy,
GatewayExtend: c.GatewayExtend, GatewayExtend: c.GatewayExtend,
LastSyncTime: c.LastSyncTime,
LastDataCheckAt: c.LastDataCheckAt,
LastRealNameCheckAt: c.LastRealNameCheckAt,
LastCardStatusCheckAt: c.LastCardStatusCheckAt,
}) })
} }
} }

View File

@@ -90,6 +90,9 @@ func (h *PollingCarddataHandler) Handle(ctx context.Context, t *asynq.Task) erro
resetDay := h.carrierStore.GetDataResetDay(ctx, card.CarrierID) resetDay := h.carrierStore.GetDataResetDay(ctx, card.CarrierID)
updates, flowIncrementMB, isCrossMonth := h.calculateFlowUpdates(card, gatewayFlowMB, now, resetDay) updates, flowIncrementMB, isCrossMonth := h.calculateFlowUpdates(card, gatewayFlowMB, now, resetDay)
updates["last_data_check_at"] = now updates["last_data_check_at"] = now
if h.gateway != nil {
updates["last_sync_time"] = now
}
if h.base.verboseLog && h.gateway != nil { if h.base.verboseLog && h.gateway != nil {
h.base.logger.Info("流量轮询详情", h.base.logger.Info("流量轮询详情",

View File

@@ -107,6 +107,7 @@ func (h *PollingCardStatusHandler) Handle(ctx context.Context, t *asynq.Task) er
fields := map[string]any{"last_card_status_check_at": now} fields := map[string]any{"last_card_status_check_at": now}
if statusQueried { if statusQueried {
fields["gateway_extend"] = gatewayExtend fields["gateway_extend"] = gatewayExtend
fields["last_sync_time"] = now
} }
if statusChanged { if statusChanged {
fields["network_status"] = newNetworkStatus fields["network_status"] = newNetworkStatus

View File

@@ -121,6 +121,9 @@ func (h *PollingRealnameHandler) Handle(ctx context.Context, t *asynq.Task) erro
now := time.Now() now := time.Now()
fields := map[string]any{"last_real_name_check_at": now} fields := map[string]any{"last_real_name_check_at": now}
if h.gateway != nil {
fields["last_sync_time"] = now
}
if statusChanged { if statusChanged {
fields["real_name_status"] = newStatus fields["real_name_status"] = newStatus
} }