feat(api): add cursor-based pagination for posts, comments, messages, groups, and notifications
Implement cursor-based pagination across multiple API endpoints to improve performance and enable efficient infinite scrolling. This replaces traditional offset-based pagination for high-volume data retrieval. Changes: - Add cursor pagination DTOs for all entity types (Post, Comment, Message, Conversation, Group, Notification, GroupMember, GroupAnnouncement) - Implement cursor pagination methods in repositories with support for various sort orders (created_at, updated_at, join_time, seq) - Add cursor pagination handlers that maintain backward compatibility with existing offset pagination - Add new API routes for cursor-based endpoints (/cursor suffix) - Add helper converter functions for pointer slice types in DTO conversions
This commit is contained in:
@@ -1179,3 +1179,92 @@ type PendingContentAuthor struct {
|
||||
type OnlineUsersResponse struct {
|
||||
Count int64 `json:"count"` // 在线用户数
|
||||
}
|
||||
|
||||
// ==================== Cursor Pagination DTOs ====================
|
||||
|
||||
// CursorPageRequest 游标分页请求
|
||||
type CursorPageRequest struct {
|
||||
Cursor string `json:"cursor" form:"cursor"` // 游标(首次请求为空)
|
||||
Direction string `json:"direction" form:"direction"` // forward | backward
|
||||
PageSize int `json:"page_size" form:"page_size"` // 每页数量
|
||||
}
|
||||
|
||||
// CursorPageResponse 游标分页响应(泛型版本)
|
||||
// 注意:由于 Go 的限制,这里使用 interface{} 作为 Items 类型
|
||||
// 实际使用时可以创建特定类型的响应结构体
|
||||
type CursorPageResponse struct {
|
||||
Items interface{} `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"` // 下一页游标
|
||||
PrevCursor string `json:"prev_cursor,omitempty"` // 上一页游标(可选)
|
||||
HasMore bool `json:"has_more"` // 是否有更多数据
|
||||
}
|
||||
|
||||
// CursorPageMeta 分页元信息
|
||||
type CursorPageMeta struct {
|
||||
PageSize int `json:"page_size"`
|
||||
Direction string `json:"direction"`
|
||||
}
|
||||
|
||||
// PostCursorPageResponse 帖子游标分页响应
|
||||
type PostCursorPageResponse struct {
|
||||
Items []*PostResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// CommentCursorPageResponse 评论游标分页响应
|
||||
type CommentCursorPageResponse struct {
|
||||
Items []*CommentResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// MessageCursorPageResponse 消息游标分页响应
|
||||
type MessageCursorPageResponse struct {
|
||||
Items []*MessageResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// ConversationCursorPageResponse 会话游标分页响应
|
||||
type ConversationCursorPageResponse struct {
|
||||
Items []*ConversationResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// GroupCursorPageResponse 群组游标分页响应
|
||||
type GroupCursorPageResponse struct {
|
||||
Items []*GroupResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// NotificationCursorPageResponse 通知游标分页响应
|
||||
type NotificationCursorPageResponse struct {
|
||||
Items []*NotificationResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// GroupMemberCursorPageResponse 群成员游标分页响应
|
||||
type GroupMemberCursorPageResponse struct {
|
||||
Items []*GroupMemberResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// GroupAnnouncementCursorPageResponse 群公告游标分页响应
|
||||
type GroupAnnouncementCursorPageResponse struct {
|
||||
Items []*GroupAnnouncementResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor,omitempty"`
|
||||
PrevCursor string `json:"prev_cursor,omitempty"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
@@ -94,3 +94,30 @@ func GroupAnnouncementsToResponse(announcements []model.GroupAnnouncement) []*Gr
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GroupsToResponseFromPtr 将Group指针切片转换为GroupResponse列表
|
||||
func GroupsToResponseFromPtr(groups []*model.Group) []*GroupResponse {
|
||||
result := make([]*GroupResponse, 0, len(groups))
|
||||
for _, group := range groups {
|
||||
result = append(result, GroupToResponse(group))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GroupMembersToResponseFromPtr 将GroupMember指针切片转换为GroupMemberResponse列表
|
||||
func GroupMembersToResponseFromPtr(members []*model.GroupMember) []*GroupMemberResponse {
|
||||
result := make([]*GroupMemberResponse, 0, len(members))
|
||||
for _, member := range members {
|
||||
result = append(result, GroupMemberToResponse(member))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// GroupAnnouncementsToResponseFromPtr 将GroupAnnouncement指针切片转换为GroupAnnouncementResponse列表
|
||||
func GroupAnnouncementsToResponseFromPtr(announcements []*model.GroupAnnouncement) []*GroupAnnouncementResponse {
|
||||
result := make([]*GroupAnnouncementResponse, 0, len(announcements))
|
||||
for _, announcement := range announcements {
|
||||
result = append(result, GroupAnnouncementToResponse(announcement))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user