// Package pollingpause 是不轮询清单的只读查询,供后台列表与导出共用(add-polling-pause-list-and-batch-toggle)。 package pollingpause import ( "context" "time" "gorm.io/gorm" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" ) // Filter 是不轮询清单筛选条件。 type Filter struct { AssetType string CarrierID *uint Source string Status *int Identifier string OperatorID *uint StartTime *time.Time EndTime *time.Time } // Row 是清单记录与资产当前状态、名称的投影。 type Row struct { model.CardPollingPause CarrierName string EnablePolling bool GatewayExtend string ClosedByName string RestoredByName string } // EnsureAllowed 不轮询清单仅超级管理员与平台账号可查看与导出。 func EnsureAllowed(userType int) error { if userType == constants.UserTypeSuperAdmin || userType == constants.UserTypePlatform { return nil } return errors.New(errors.CodeForbidden, "仅平台账号可查看不轮询清单") } // Query 不轮询清单只读查询。 type Query struct { db *gorm.DB } // NewQuery 创建不轮询清单查询。 func NewQuery(db *gorm.DB) *Query { return &Query{db: db} } func (q *Query) base(ctx context.Context, filter Filter) *gorm.DB { query := q.db.WithContext(ctx).Table("tb_card_polling_pause AS p") if filter.AssetType != "" { query = query.Where("p.asset_type = ?", filter.AssetType) } if filter.CarrierID != nil { query = query.Where("p.carrier_id = ?", *filter.CarrierID) } if filter.Source != "" { query = query.Where("p.close_source = ?", filter.Source) } if filter.Status != nil { query = query.Where("p.status = ?", *filter.Status) } if filter.Identifier != "" { query = query.Where("p.identifier = ?", filter.Identifier) } if filter.OperatorID != nil { query = query.Where("p.closed_by = ?", *filter.OperatorID) } if filter.StartTime != nil { query = query.Where("p.closed_at >= ?", *filter.StartTime) } if filter.EndTime != nil { query = query.Where("p.closed_at <= ?", *filter.EndTime) } return query } // Count 统计符合条件的记录数。 func (q *Query) Count(ctx context.Context, filter Filter) (int64, error) { var total int64 if err := q.base(ctx, filter).Count(&total).Error; err != nil { return 0, errors.Wrap(errors.CodeDatabaseError, err, "统计不轮询清单失败") } return total, nil } // Page 按关闭时间倒序返回一页记录,附带资产当前轮询开关、网关扩展状态、运营商账户与操作人名称。 func (q *Query) Page(ctx context.Context, filter Filter, offset, limit int) ([]Row, error) { var rows []Row err := q.base(ctx, filter). Select(`p.*, COALESCE(ca.carrier_name, '') AS carrier_name, COALESCE(c.enable_polling, d.enable_polling, FALSE) AS enable_polling, COALESCE(c.gateway_extend, '') AS gateway_extend, COALESCE(a1.username, '') AS closed_by_name, COALESCE(a2.username, '') AS restored_by_name`). Joins("LEFT JOIN tb_iot_card c ON p.asset_type = 'iot_card' AND c.id = p.asset_id"). Joins("LEFT JOIN tb_device d ON p.asset_type = 'device' AND d.id = p.asset_id"). Joins("LEFT JOIN tb_carrier ca ON ca.id = p.carrier_id"). Joins("LEFT JOIN tb_account a1 ON a1.id = p.closed_by"). Joins("LEFT JOIN tb_account a2 ON a2.id = p.restored_by"). Order("p.closed_at DESC, p.id DESC").Offset(offset).Limit(limit).Scan(&rows).Error if err != nil { return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询不轮询清单失败") } return rows, nil }