diff --git a/internal/dto/dto.go b/internal/dto/dto.go index 057586b..c0c6ce5 100644 --- a/internal/dto/dto.go +++ b/internal/dto/dto.go @@ -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 格式化时间 diff --git a/internal/handler/system_message_handler.go b/internal/handler/system_message_handler.go index 44f1989..acc6715 100644 --- a/internal/handler/system_message_handler.go +++ b/internal/handler/system_message_handler.go @@ -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) { diff --git a/internal/repository/system_notification_repo.go b/internal/repository/system_notification_repo.go index 2506fd4..5e3cb72 100644 --- a/internal/repository/system_notification_repo.go +++ b/internal/repository/system_notification_repo.go @@ -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 +}