feat: 新增排行榜模块
- 新增 leaderboard 服务与 handler、前端排行榜页面 - 路由与首页入口适配
This commit is contained in:
@@ -37,6 +37,7 @@ type Handlers struct {
|
||||
Ads *service.AdService
|
||||
Sidebar *service.SidebarService
|
||||
Badge *service.BadgeService
|
||||
LeaderboardSvc *service.LeaderboardService
|
||||
}
|
||||
|
||||
// resolvePublishStatus 决定新帖/新评的初始状态:
|
||||
|
||||
71
backend/handler/leaderboard.go
Normal file
71
backend/handler/leaderboard.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/freefire/jiang13-bbs/service"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// 榜单参数白名单
|
||||
var (
|
||||
lbPeriods = map[string]bool{service.PeriodWeek: true, service.PeriodMonth: true, service.PeriodAll: true}
|
||||
lbMetrics = map[string]bool{service.MetricAll: true, service.MetricPost: true,
|
||||
service.MetricComment: true, service.MetricLike: true, service.MetricAnswer: true}
|
||||
)
|
||||
|
||||
// lbParams 解析并校验 period/metric,非法值回退默认并标记 400
|
||||
func lbParams(c *gin.Context) (period, metric string, bad bool) {
|
||||
period = c.DefaultQuery("period", service.PeriodAll)
|
||||
metric = c.DefaultQuery("metric", service.MetricAll)
|
||||
if !lbPeriods[period] || !lbMetrics[metric] {
|
||||
return "", "", true
|
||||
}
|
||||
return period, metric, false
|
||||
}
|
||||
|
||||
// Leaderboard 用户贡献榜:period=week|month|all × metric=all|post|comment|like|answer(公开接口)
|
||||
func (h *Handlers) Leaderboard(c *gin.Context) {
|
||||
period, metric, bad := lbParams(c)
|
||||
if bad {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的榜单参数"})
|
||||
return
|
||||
}
|
||||
limit := 50
|
||||
if v := c.Query("limit"); v != "" {
|
||||
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
||||
limit = n
|
||||
}
|
||||
}
|
||||
if limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
res, err := h.LeaderboardSvc.Board(period, metric, limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取排行榜失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
// LeaderboardMe 当前用户在指定榜单的排名(可选登录;游客返回 me:null)
|
||||
func (h *Handlers) LeaderboardMe(c *gin.Context) {
|
||||
period, metric, bad := lbParams(c)
|
||||
if bad {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的榜单参数"})
|
||||
return
|
||||
}
|
||||
if v, ok := c.Get("user"); ok {
|
||||
if claims, ok := v.(*service.UserClaims); ok && claims.ID > 0 {
|
||||
res, err := h.LeaderboardSvc.MyRank(period, metric, claims.ID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取排名失败"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"me": res})
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"me": nil})
|
||||
}
|
||||
Reference in New Issue
Block a user