From 4bde09837abc2d3d63b227f89cfdb241c6e12455 Mon Sep 17 00:00:00 2001 From: huang Date: Thu, 23 Apr 2026 17:02:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BF=80=E6=B4=BB=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/store/postgres/iot_card_store.go | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/internal/store/postgres/iot_card_store.go b/internal/store/postgres/iot_card_store.go index 27b2c8f..8a1c8e9 100644 --- a/internal/store/postgres/iot_card_store.go +++ b/internal/store/postgres/iot_card_store.go @@ -179,6 +179,10 @@ func (s *IotCardStore) UpdateFields(ctx context.Context, cardID uint, fields map if shouldSyncActivationStatus(fields) { updates["activation_status"] = buildActivationStatusExpr(fields) + // 激活状态从 0→1 时补写激活时间;仅写首次,不覆盖已有值。 + if _, hasActivatedAt := fields["activated_at"]; !hasActivatedAt { + updates["activated_at"] = buildActivatedAtExpr(fields, time.Now()) + } } return s.db.WithContext(ctx).Model(&model.IotCard{}). @@ -238,6 +242,42 @@ func buildActivationStatusExpr(fields map[string]any) any { ) } +// buildActivatedAtExpr 构造激活时间表达式(与本次更新同 SQL 执行) +// 仅在激活状态从 0→1 时写入当前时间,且不覆盖已有 activated_at。 +func buildActivatedAtExpr(fields map[string]any, now time.Time) 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 activation_status = ? + AND COALESCE(?, network_status) = ? + AND (COALESCE(?, card_category) = ? OR COALESCE(?, real_name_status) = ?) + THEN COALESCE(activated_at, ?) + ELSE activated_at + END`, + constants.ActivationStatusInactive, + networkStatus, + constants.NetworkStatusOnline, + cardCategory, + constants.CardCategoryIndustry, + realNameStatus, + constants.RealNameStatusVerified, + now, + ) +} + // UpdatePollingStatus 更新卡的轮询启用状态 func (s *IotCardStore) UpdatePollingStatus(ctx context.Context, cardID uint, enablePolling bool) error { return s.db.WithContext(ctx).Model(&model.IotCard{}).