package device import ( "context" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "gorm.io/gorm" "gorm.io/gorm/clause" ) // BatchUpdateRealnamePolicy 批量更新设备实名认证策略,整批校验后在单事务内全成全败。 func (s *Service) BatchUpdateRealnamePolicy(ctx context.Context, req *dto.BatchUpdateAssetRealnamePolicyRequest) (*dto.BatchUpdateAssetRealnamePolicyResponse, error) { if middleware.GetUserTypeFromContext(ctx) == constants.UserTypeEnterprise { return nil, errors.New(errors.CodeForbidden, "企业账号无权修改设备实名认证策略") } ids, err := validateBatchRealnamePolicyRequest(req) if err != nil { return nil, err } err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { var devices []model.Device query := middleware.ApplyShopFilter(ctx, tx.Model(&model.Device{})).Clauses(clause.Locking{Strength: "UPDATE"}) if err := query.Where("id IN ?", ids).Find(&devices).Error; err != nil { return errors.Wrap(errors.CodeDatabaseError, err, "查询批量设备资产失败") } if len(devices) != len(ids) { return errors.New(errors.CodeForbidden, "无权限操作该资源或资源不存在") } result := tx.Model(&model.Device{}).Where("id IN ?", ids).Update("realname_policy", req.RealnamePolicy) if result.Error != nil { return errors.Wrap(errors.CodeDatabaseError, result.Error, "批量更新设备实名认证策略失败") } if result.RowsAffected != int64(len(ids)) { return errors.New(errors.CodeConflict, "设备资产状态已变化,请刷新后重试") } return nil }) if err != nil { return nil, err } s.logDeviceOperation( ctx, constants.AssetAuditOpAssetRealnamePolicy, "批量更新设备实名认证策略", constants.AssetAuditResultSuccess, nil, nil, map[string]any{"asset_ids": ids, "realname_policy": req.RealnamePolicy}, len(ids), len(ids), 0, nil, ) return &dto.BatchUpdateAssetRealnamePolicyResponse{SuccessCount: len(ids), RealnamePolicy: req.RealnamePolicy}, nil } func validateBatchRealnamePolicyRequest(req *dto.BatchUpdateAssetRealnamePolicyRequest) ([]uint, error) { if req == nil || len(req.AssetIDs) == 0 || len(req.AssetIDs) > 500 || !isValidRealnamePolicy(req.RealnamePolicy) { return nil, errors.New(errors.CodeInvalidParam) } seen := make(map[uint]struct{}, len(req.AssetIDs)) ids := make([]uint, 0, len(req.AssetIDs)) for _, id := range req.AssetIDs { if id == 0 { return nil, errors.New(errors.CodeInvalidParam) } if _, exists := seen[id]; exists { return nil, errors.New(errors.CodeInvalidParam, "资产ID不能重复") } seen[id] = struct{}{} ids = append(ids, id) } return ids, nil } func isValidRealnamePolicy(policy string) bool { return policy == constants.RealnamePolicyNone || policy == constants.RealnamePolicyBeforeOrder || policy == constants.RealnamePolicyAfterOrder }