package cursor import ( "errors" ) const ( // DefaultPageSize 默认页面大小 DefaultPageSize = 20 // MaxPageSize 最大页面大小 MaxPageSize = 100 ) // Direction 分页方向 type Direction string const ( // Forward 向前分页(下一页) Forward Direction = "forward" // Backward 向后分页(上一页) Backward Direction = "backward" ) // IsValid 检查分页方向是否有效 func (d Direction) IsValid() bool { return d == Forward || d == Backward } // PageRequest 游标分页请求参数 type PageRequest struct { Cursor string // 游标字符串 Direction Direction // 分页方向 PageSize int // 每页数量 } // NewPageRequest 创建新的游标请求 func NewPageRequest(cursor string, direction Direction, pageSize int) *PageRequest { req := &PageRequest{ Cursor: cursor, Direction: direction, PageSize: pageSize, } req.Normalize() return req } // Normalize 规范化分页参数 func (r *PageRequest) Normalize() { if r.Direction == "" { r.Direction = Forward } if r.PageSize <= 0 { r.PageSize = DefaultPageSize } if r.PageSize > MaxPageSize { r.PageSize = MaxPageSize } } // GetPageSize 获取有效的页面大小(默认20,最大100) func (r *PageRequest) GetPageSize() int { if r.PageSize <= 0 { return DefaultPageSize } if r.PageSize > MaxPageSize { return MaxPageSize } return r.PageSize } // Validate 验证分页请求 func (r *PageRequest) Validate() error { if r.Direction != "" && !r.Direction.IsValid() { return errors.New("invalid direction, must be 'forward' or 'backward'") } return nil } // GetCursor 解码游标 func (r *PageRequest) GetCursor() (*Cursor, error) { return DecodeCursor(r.Cursor) } // IsForward 是否向前分页 func (r *PageRequest) IsForward() bool { return r.Direction == Forward || r.Direction == "" } // IsBackward 是否向后分页 func (r *PageRequest) IsBackward() bool { return r.Direction == Backward } // PageResponse 游标分页响应结构 type PageResponse struct { Items any `json:"items"` NextCursor string `json:"next_cursor"` PrevCursor string `json:"prev_cursor,omitempty"` HasMore bool `json:"has_more"` } // CursorPageResult 游标分页结果(泛型版本,供内部使用) type CursorPageResult[T any] struct { Items []T NextCursor string PrevCursor string HasMore bool } // NewCursorPageResult 创建游标分页结果 func NewCursorPageResult[T any](items []T, nextCursor, prevCursor string, hasMore bool) *CursorPageResult[T] { return &CursorPageResult[T]{ Items: items, NextCursor: nextCursor, PrevCursor: prevCursor, HasMore: hasMore, } } // ToPageResponse 转换为通用分页响应 func (r *CursorPageResult[T]) ToPageResponse() *PageResponse { return &PageResponse{ Items: r.Items, NextCursor: r.NextCursor, PrevCursor: r.PrevCursor, HasMore: r.HasMore, } }