feat(api): add tab-based post feed endpoints with cursor pagination
Add support for different post feed types via tab parameter: - follow: posts from followed users (requires authentication) - hot: trending posts using Gorse most_liked_weekly or database fallback - recommend: personalized recommendations with random offset for diversity - latest: default chronological feed The cursor pagination detection is also improved to check for parameter existence rather than non-empty string value.
This commit is contained in:
@@ -906,3 +906,113 @@ func (r *PostRepository) GetUserPostsByCursor(ctx context.Context, userID string
|
||||
|
||||
return cursor.NewCursorPageResult(posts, nextCursor, prevCursor, hasMore), nil
|
||||
}
|
||||
|
||||
// GetFollowingPostsByCursor 游标分页获取关注用户的帖子
|
||||
func (r *PostRepository) GetFollowingPostsByCursor(ctx context.Context, userID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Post], error) {
|
||||
db := r.getDB(ctx).WithContext(ctx)
|
||||
|
||||
// 子查询:获取当前用户关注的所有用户ID
|
||||
subQuery := db.Model(&model.Follow{}).Where("follower_id = ?", userID).Select("following_id")
|
||||
|
||||
// 构建基础查询
|
||||
query := db.Model(&model.Post{}).Where("user_id IN (?) AND status = ?", subQuery, model.PostStatusPublished)
|
||||
|
||||
// 使用游标构建器
|
||||
builder := cursor.NewBuilder(query, cursor.SortByCreatedAtDesc).
|
||||
WithCursor(req.Cursor, req.Direction).
|
||||
WithPageSize(req.PageSize)
|
||||
|
||||
if builder.Error() != nil {
|
||||
// 无效游标,返回空列表
|
||||
return cursor.NewCursorPageResult[*model.Post]([]*model.Post{}, "", "", false), nil
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
var posts []*model.Post
|
||||
query = builder.Build().Preload("User").Preload("Images")
|
||||
if err := query.Find(&posts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
pageSize := builder.GetPageSize()
|
||||
hasMore := cursor.HasMore(len(posts), pageSize)
|
||||
if hasMore {
|
||||
posts = posts[:pageSize]
|
||||
}
|
||||
|
||||
// 生成游标
|
||||
var nextCursor, prevCursor string
|
||||
if len(posts) > 0 {
|
||||
if hasMore {
|
||||
lastPost := posts[len(posts)-1]
|
||||
nextCursor = cursor.NewCursor(
|
||||
cursor.FormatTime(lastPost.CreatedAt),
|
||||
lastPost.ID,
|
||||
cursor.SortByCreatedAtDesc,
|
||||
).Encode()
|
||||
}
|
||||
firstPost := posts[0]
|
||||
prevCursor = cursor.NewCursor(
|
||||
cursor.FormatTime(firstPost.CreatedAt),
|
||||
firstPost.ID,
|
||||
cursor.SortByCreatedAtDesc,
|
||||
).Encode()
|
||||
}
|
||||
|
||||
return cursor.NewCursorPageResult(posts, nextCursor, prevCursor, hasMore), nil
|
||||
}
|
||||
|
||||
// GetHotPostsByCursor 游标分页获取热门帖子
|
||||
func (r *PostRepository) GetHotPostsByCursor(ctx context.Context, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Post], error) {
|
||||
db := r.getDB(ctx).WithContext(ctx)
|
||||
|
||||
// 构建基础查询 - 热门帖子按热度分数排序
|
||||
query := db.Model(&model.Post{}).Where("status = ?", model.PostStatusPublished).
|
||||
Order("hot_score DESC, created_at DESC")
|
||||
|
||||
// 使用游标构建器
|
||||
builder := cursor.NewBuilder(query, cursor.SortByCreatedAtDesc).
|
||||
WithCursor(req.Cursor, req.Direction).
|
||||
WithPageSize(req.PageSize)
|
||||
|
||||
if builder.Error() != nil {
|
||||
// 无效游标,返回空列表
|
||||
return cursor.NewCursorPageResult[*model.Post]([]*model.Post{}, "", "", false), nil
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
var posts []*model.Post
|
||||
query = builder.Build().Preload("User").Preload("Images")
|
||||
if err := query.Find(&posts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 构建响应
|
||||
pageSize := builder.GetPageSize()
|
||||
hasMore := cursor.HasMore(len(posts), pageSize)
|
||||
if hasMore {
|
||||
posts = posts[:pageSize]
|
||||
}
|
||||
|
||||
// 生成游标
|
||||
var nextCursor, prevCursor string
|
||||
if len(posts) > 0 {
|
||||
if hasMore {
|
||||
lastPost := posts[len(posts)-1]
|
||||
nextCursor = cursor.NewCursor(
|
||||
cursor.FormatTime(lastPost.CreatedAt),
|
||||
lastPost.ID,
|
||||
cursor.SortByCreatedAtDesc,
|
||||
).Encode()
|
||||
}
|
||||
firstPost := posts[0]
|
||||
prevCursor = cursor.NewCursor(
|
||||
cursor.FormatTime(firstPost.CreatedAt),
|
||||
firstPost.ID,
|
||||
cursor.SortByCreatedAtDesc,
|
||||
).Encode()
|
||||
}
|
||||
|
||||
return cursor.NewCursorPageResult(posts, nextCursor, prevCursor, hasMore), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user