261 lines
7.7 KiB
Go
261 lines
7.7 KiB
Go
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,
|
||
}
|
||
}
|