topfans/backend/gateway/controller/ranking_controller.go
2026-04-07 22:29:48 +08:00

261 lines
7.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controller
import (
"context"
"net/http"
"strconv"
"time"
"dubbo.apache.org/dubbo-go/v3/client"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"github.com/gin-gonic/gin"
"github.com/topfans/backend/gateway/pkg/response"
pbRanking "github.com/topfans/backend/pkg/proto/ranking"
pbCommon "github.com/topfans/backend/pkg/proto/common"
"github.com/topfans/backend/pkg/logger"
"go.uber.org/zap"
)
// RankingController 排行榜控制器
type RankingController struct {
rankingService pbRanking.RankingService
}
// NewRankingController 创建排行榜控制器
func NewRankingController(dubboClient *client.Client) (*RankingController, error) {
// 创建 RankingService 客户端
rankingService, err := pbRanking.NewRankingService(dubboClient)
if err != nil {
return nil, err
}
return &RankingController{
rankingService: rankingService,
}, nil
}
// GetHotRanking 获取热度排行榜
// @Summary 获取热度排行榜
// @Description 获取热度排行榜,支持按维度筛选(displaying:展示中, month:本月, total:全部)
// @Tags rankings
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param dimension query string false "统计维度: displaying(展示中), month(本月), total(全部)默认total"
// @Param star_id query int64 false "粉丝身份ID不传则使用当前身份"
// @Param page query int false "页码默认1"
// @Param page_size query int false "每页数量默认10"
// @Success 200 {object} response.Response
// @Router /api/v1/rankings/hot [get]
func (ctrl *RankingController) GetHotRanking(c *gin.Context) {
// 从上下文获取用户信息
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, http.StatusUnauthorized, "未授权")
return
}
starID, exists := c.Get("star_id")
if !exists {
response.Error(c, http.StatusUnauthorized, "未授权")
return
}
// 解析查询参数
dimension := c.DefaultQuery("dimension", "total")
starIDParam := c.Query("star_id")
var starIDParamInt int64
if starIDParam != "" {
var err error
starIDParamInt, err = strconv.ParseInt(starIDParam, 10, 64)
if err != nil {
response.Error(c, http.StatusBadRequest, "star_id 参数错误")
return
}
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
// 如果传了 star_id 参数,使用传入的值;否则使用当前用户的 star_id
reqStarID := starID.(int64)
if starIDParamInt > 0 {
reqStarID = starIDParamInt
}
logger.Logger.Info("GetHotRanking request",
zap.Int64("user_id", userID.(int64)),
zap.Int64("star_id", reqStarID),
zap.String("dimension", dimension),
zap.Int("page", page),
zap.Int("page_size", pageSize),
)
// 设置上下文
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{
"user_id": strconv.FormatInt(userID.(int64), 10),
"star_id": strconv.FormatInt(reqStarID, 10),
})
// 调用 RPC
resp, err := ctrl.rankingService.GetHotRanking(ctx, &pbRanking.GetRankingRequest{
Dimension: dimension,
StarId: reqStarID,
Page: int32(page),
PageSize: int32(pageSize),
UserId: userID.(int64),
})
if err != nil {
logger.Logger.Error("GetHotRanking RPC failed",
zap.Error(err),
)
response.Error(c, http.StatusInternalServerError, "获取排行榜失败")
return
}
if resp.Base.Code != pbCommon.StatusCode_STATUS_OK {
response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message)
return
}
// 转换响应
data := convertRankingResponse(resp)
response.Success(c, data)
}
// GetOriginalRanking 获取自制排行榜
// @Summary 获取自制排行榜
// @Description 获取自制藏品排行榜,支持按维度筛选(displaying:展示中, month:本月, total:全部)
// @Tags rankings
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param dimension query string false "统计维度: displaying(展示中), month(本月), total(全部)默认total"
// @Param star_id query int64 false "粉丝身份ID不传则使用当前身份"
// @Param page query int false "页码默认1"
// @Param page_size query int false "每页数量默认10"
// @Success 200 {object} response.Response
// @Router /api/v1/rankings/original [get]
func (ctrl *RankingController) GetOriginalRanking(c *gin.Context) {
// 从上下文获取用户信息
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, http.StatusUnauthorized, "未授权")
return
}
starID, exists := c.Get("star_id")
if !exists {
response.Error(c, http.StatusUnauthorized, "未授权")
return
}
// 解析查询参数
dimension := c.DefaultQuery("dimension", "total")
starIDParam := c.Query("star_id")
var starIDParamInt int64
if starIDParam != "" {
var err error
starIDParamInt, err = strconv.ParseInt(starIDParam, 10, 64)
if err != nil {
response.Error(c, http.StatusBadRequest, "star_id 参数错误")
return
}
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
// 如果传了 star_id 参数,使用传入的值;否则使用当前用户的 star_id
reqStarID := starID.(int64)
if starIDParamInt > 0 {
reqStarID = starIDParamInt
}
logger.Logger.Info("GetOriginalRanking request",
zap.Int64("user_id", userID.(int64)),
zap.Int64("star_id", reqStarID),
zap.String("dimension", dimension),
zap.Int("page", page),
zap.Int("page_size", pageSize),
)
// 设置上下文
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
ctx = context.WithValue(ctx, constant.AttachmentKey, map[string]interface{}{
"user_id": strconv.FormatInt(userID.(int64), 10),
"star_id": strconv.FormatInt(reqStarID, 10),
})
// 调用 RPC
resp, err := ctrl.rankingService.GetOriginalRanking(ctx, &pbRanking.GetRankingRequest{
Dimension: dimension,
StarId: reqStarID,
Page: int32(page),
PageSize: int32(pageSize),
UserId: userID.(int64),
})
if err != nil {
logger.Logger.Error("GetOriginalRanking RPC failed",
zap.Error(err),
)
response.Error(c, http.StatusInternalServerError, "获取自制排行榜失败")
return
}
if resp.Base.Code != pbCommon.StatusCode_STATUS_OK {
response.ErrorWithCode(c, int(resp.Base.Code), resp.Base.Message)
return
}
// 转换响应
data := convertRankingResponse(resp)
response.Success(c, data)
}
// convertRankingResponse 转换排行榜响应
func convertRankingResponse(resp *pbRanking.GetRankingResponse) map[string]interface{} {
// 转换 items
items := make([]map[string]interface{}, 0, len(resp.Items))
for _, item := range resp.Items {
items = append(items, map[string]interface{}{
"rank": item.Rank,
"asset_id": item.AssetId,
"asset_name": item.AssetName,
"cover_url": item.CoverUrl,
"owner_uid": item.OwnerUid,
"owner_nickname": item.OwnerNickname,
"owner_avatar": item.OwnerAvatar,
"like_count": item.LikeCount,
"is_original": item.IsOriginal,
})
}
// 转换 my_ranking
var myRanking map[string]interface{}
if resp.MyRanking != nil {
myRanking = map[string]interface{}{
"rank": resp.MyRanking.Rank,
"asset_id": resp.MyRanking.AssetId,
"asset_name": resp.MyRanking.AssetName,
"cover_url": resp.MyRanking.CoverUrl,
"like_count": resp.MyRanking.LikeCount,
"status": resp.MyRanking.Status,
"diff_to_rank": resp.MyRanking.DiffToRank,
"owner_nickname": resp.MyRanking.OwnerNickname,
"owner_avatar": resp.MyRanking.OwnerAvatar,
}
}
return map[string]interface{}{
"my_ranking": myRanking,
"items": items,
"page": resp.Page,
"page_size": resp.PageSize,
"total": resp.Total,
}
}