feat(api): add cursor-based pagination for system messages
- Add SystemMessageCursorPageResponse DTO for cursor pagination - Implement GetSystemMessagesByCursor handler method - Add GetByReceiverIDCursor repository method with cursor decoding - Maintain backward compatibility with existing offset-based pagination
This commit is contained in:
@@ -528,6 +528,14 @@ type SystemUnreadCountResponse struct {
|
||||
UnreadCount int64 `json:"unread_count"`
|
||||
}
|
||||
|
||||
// SystemMessageCursorPageResponse 系统消息游标分页响应
|
||||
type SystemMessageCursorPageResponse struct {
|
||||
Items []*SystemMessageResponse `json:"items"`
|
||||
NextCursor string `json:"next_cursor"`
|
||||
PrevCursor string `json:"prev_cursor"`
|
||||
HasMore bool `json:"has_more"`
|
||||
}
|
||||
|
||||
// ==================== 时间格式化 ====================
|
||||
|
||||
// FormatTime 格式化时间
|
||||
|
||||
@@ -42,6 +42,14 @@ func (h *SystemMessageHandler) GetSystemMessages(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否使用游标分页
|
||||
_, cursorExists := c.GetQuery("cursor")
|
||||
if cursorExists {
|
||||
h.GetSystemMessagesByCursor(c)
|
||||
return
|
||||
}
|
||||
|
||||
// 偏移分页(向后兼容)
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
@@ -62,6 +70,43 @@ func (h *SystemMessageHandler) GetSystemMessages(c *gin.Context) {
|
||||
response.Paginated(c, result, total, page, pageSize)
|
||||
}
|
||||
|
||||
// GetSystemMessagesByCursor 游标分页获取系统消息列表
|
||||
func (h *SystemMessageHandler) GetSystemMessagesByCursor(c *gin.Context) {
|
||||
userID := c.GetString("user_id")
|
||||
if userID == "" {
|
||||
response.Unauthorized(c, "")
|
||||
return
|
||||
}
|
||||
|
||||
// 解析游标分页请求
|
||||
cursorStr := c.Query("cursor")
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
|
||||
// 获取当前用户的系统通知
|
||||
notifications, nextCursor, hasMore, err := h.notifyRepo.GetByReceiverIDCursor(userID, cursorStr, pageSize)
|
||||
if err != nil {
|
||||
response.InternalServerError(c, "failed to get system messages")
|
||||
return
|
||||
}
|
||||
|
||||
// 转换为响应格式
|
||||
items := make([]*dto.SystemMessageResponse, 0)
|
||||
for _, n := range notifications {
|
||||
resp := dto.SystemNotificationToResponse(n)
|
||||
items = append(items, resp)
|
||||
}
|
||||
|
||||
// 构建游标分页响应
|
||||
cursorResp := &dto.SystemMessageCursorPageResponse{
|
||||
Items: items,
|
||||
NextCursor: nextCursor,
|
||||
PrevCursor: "",
|
||||
HasMore: hasMore,
|
||||
}
|
||||
|
||||
response.Success(c, cursorResp)
|
||||
}
|
||||
|
||||
// GetUnreadCount 获取系统消息未读数
|
||||
// GET /api/v1/messages/system/unread-count
|
||||
func (h *SystemMessageHandler) GetUnreadCount(c *gin.Context) {
|
||||
|
||||
@@ -112,3 +112,38 @@ func (r *SystemNotificationRepository) GetByType(receiverID string, notifyType m
|
||||
|
||||
return notifications, total, err
|
||||
}
|
||||
|
||||
// GetByReceiverIDCursor 游标分页获取用户的通知列表
|
||||
func (r *SystemNotificationRepository) GetByReceiverIDCursor(receiverID string, cursor string, pageSize int) ([]*model.SystemNotification, string, bool, error) {
|
||||
query := r.db.Model(&model.SystemNotification{}).Where("receiver_id = ?", receiverID)
|
||||
|
||||
// 如果有游标,解析游标并添加条件
|
||||
if cursor != "" {
|
||||
// 游标格式:createdAt_id
|
||||
query = query.Where("created_at < ? OR (created_at = ? AND id < ?)", cursor, cursor, cursor)
|
||||
}
|
||||
|
||||
// 多取一条用于判断是否还有下一页
|
||||
var notifications []*model.SystemNotification
|
||||
err := query.Order("created_at DESC, id DESC").
|
||||
Limit(pageSize + 1).
|
||||
Find(¬ifications).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
|
||||
hasMore := len(notifications) > pageSize
|
||||
if hasMore {
|
||||
notifications = notifications[:pageSize]
|
||||
}
|
||||
|
||||
// 生成下一页游标
|
||||
var nextCursor string
|
||||
if hasMore && len(notifications) > 0 {
|
||||
lastNotification := notifications[len(notifications)-1]
|
||||
nextCursor = lastNotification.CreatedAt.Format("2006-01-02 15:04:05.999999999")
|
||||
}
|
||||
|
||||
return notifications, nextCursor, hasMore, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user