卡不激活的问题

This commit is contained in:
2026-04-23 16:58:16 +08:00
parent a7f2c4480a
commit c250a47651
4 changed files with 82 additions and 22 deletions

View File

@@ -881,13 +881,11 @@ func (s *Service) StopDevice(ctx context.Context, deviceID uint) (*dto.DeviceSus
}
now := time.Now()
if dbErr := s.db.WithContext(ctx).Model(&model.IotCard{}).
Where("id = ?", card.ID).
Updates(map[string]any{
"network_status": constants.NetworkStatusOffline,
"stopped_at": now,
"stop_reason": constants.StopReasonManual,
}).Error; dbErr != nil {
if dbErr := s.iotCardStore.UpdateFields(ctx, card.ID, map[string]any{
"network_status": constants.NetworkStatusOffline,
"stopped_at": now,
"stop_reason": constants.StopReasonManual,
}); dbErr != nil {
log.Error("设备停机-更新卡状态失败",
zap.Uint("card_id", card.ID),
zap.Error(dbErr))
@@ -986,13 +984,11 @@ func (s *Service) StartDevice(ctx context.Context, deviceID uint) error {
}
now := time.Now()
if dbErr := s.db.WithContext(ctx).Model(&model.IotCard{}).
Where("id = ?", card.ID).
Updates(map[string]any{
"network_status": constants.NetworkStatusOnline,
"resumed_at": now,
"stop_reason": "",
}).Error; dbErr != nil {
if dbErr := s.iotCardStore.UpdateFields(ctx, card.ID, map[string]any{
"network_status": constants.NetworkStatusOnline,
"resumed_at": now,
"stop_reason": "",
}); dbErr != nil {
log.Error("设备复机-更新卡状态失败",
zap.Uint("card_id", card.ID),
zap.Error(dbErr))

View File

@@ -373,7 +373,7 @@ func (s *Service) updateCardNetworkStatus(ctx context.Context, enterpriseID, car
return errors.New(errors.CodeForbidden, "无权限操作此卡")
}
return s.db.WithContext(ctx).Model(&model.IotCard{}).
Where("id = ?", cardID).
Update("network_status", networkStatus).Error
return s.iotCardStore.UpdateFields(ctx, cardID, map[string]any{
"network_status": networkStatus,
})
}

View File

@@ -877,9 +877,7 @@ func (s *Service) RefreshCardDataFromGateway(ctx context.Context, iccid string)
}
}
if err := s.db.WithContext(ctx).Model(&model.IotCard{}).
Where("id = ?", card.ID).
Updates(updates).Error; err != nil {
if err := s.iotCardStore.UpdateFields(ctx, card.ID, updates); err != nil {
return errors.Wrap(errors.CodeInternalError, err, "更新卡数据失败")
}

View File

@@ -165,11 +165,77 @@ func (s *IotCardStore) Update(ctx context.Context, card *model.IotCard) error {
return s.db.WithContext(ctx).Save(card).Error
}
// UpdateFields 按 ID 部分更新卡字段,供轮询系统的 Handler 使用
// UpdateFields 按 ID 部分更新卡字段
// 当更新包含 network_status/real_name_status/card_category 时,自动同步 activation_status
func (s *IotCardStore) UpdateFields(ctx context.Context, cardID uint, fields map[string]any) error {
if len(fields) == 0 {
return nil
}
updates := make(map[string]any, len(fields)+1)
for k, v := range fields {
updates[k] = v
}
if shouldSyncActivationStatus(fields) {
updates["activation_status"] = buildActivationStatusExpr(fields)
}
return s.db.WithContext(ctx).Model(&model.IotCard{}).
Where("id = ?", cardID).
Updates(fields).Error
Updates(updates).Error
}
func shouldSyncActivationStatus(fields map[string]any) bool {
if fields == nil {
return false
}
if _, ok := fields["network_status"]; ok {
return true
}
if _, ok := fields["real_name_status"]; ok {
return true
}
if _, ok := fields["card_category"]; ok {
return true
}
return false
}
// buildActivationStatusExpr 构造激活状态表达式(与本次更新同 SQL 执行)
// 规则:开机 且(行业卡 或 已实名)=> 已激活;否则未激活
// 若本次未更新某字段,则回退使用该字段当前值。
func buildActivationStatusExpr(fields map[string]any) any {
var networkStatus any
var cardCategory any
var realNameStatus any
if v, ok := fields["network_status"]; ok {
networkStatus = v
}
if v, ok := fields["card_category"]; ok {
cardCategory = v
}
if v, ok := fields["real_name_status"]; ok {
realNameStatus = v
}
return gorm.Expr(`
CASE
WHEN COALESCE(?, network_status) = ?
AND (COALESCE(?, card_category) = ? OR COALESCE(?, real_name_status) = ?)
THEN ?
ELSE ?
END`,
networkStatus,
constants.NetworkStatusOnline,
cardCategory,
constants.CardCategoryIndustry,
realNameStatus,
constants.RealNameStatusVerified,
constants.ActivationStatusActive,
constants.ActivationStatusInactive,
)
}
// UpdatePollingStatus 更新卡的轮询启用状态