starbook 首页每个 grade/group 按 Asset.LikeCount DESC, Asset.ID ASC 取前三张,超三显示 has_more; GetAssetsByType 不截断返回全部匹配项。包含: - proto/asset.proto 声明 GetAssetsByType RPC + 消息,重新生成 .pb.go/.triple.go - gateway starbook controller 改用标准 AssetService 客户端 - assetService: 三个 build*GroupForAssets 增加 previewLimit 参数 - 新增 sortAndLimitAssetItems 共享助手 - 新增 asset_service_group_test.go DB-free 单测 - 新增 TestStarbookHomePreviewAndMoreUseAssetLikeRanking 端到端回归 - frontend pages/starbook/items.vue 适配嵌套 groups/grades/items 响应,单 grade 竖向展示 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
152 lines
4.7 KiB
Go
152 lines
4.7 KiB
Go
package controller
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
"strconv"
|
||
|
||
"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"
|
||
"github.com/topfans/backend/pkg/logger"
|
||
pbAsset "github.com/topfans/backend/pkg/proto/asset"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// StarbookController 星册控制器
|
||
//
|
||
// ★ 批次 4.2 起,星册路由由 gateway → assetService 接管(原 starbookService 已删除)。
|
||
// GetMyAssets(home) 与 GetAssetsByType(items) 均由 asset.proto 生成的标准 AssetService client 提供。
|
||
type StarbookController struct {
|
||
assetClient pbAsset.AssetService
|
||
}
|
||
|
||
// NewStarbookController 创建星册控制器
|
||
func NewStarbookController(assetClient *client.Client) (*StarbookController, error) {
|
||
assetService, err := pbAsset.NewAssetService(assetClient)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &StarbookController{assetClient: assetService}, nil
|
||
}
|
||
|
||
// GetStarbookHome 获取星册首页
|
||
// @Summary 获取星册首页
|
||
// @Description 获取当前用户的星册首页数据(按类型和分组展示)
|
||
// @Tags starbook
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security BearerAuth
|
||
// @Success 200 {object} response.Response
|
||
// @Router /api/v1/starbook/home [get]
|
||
func (ctrl *StarbookController) GetStarbookHome(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
|
||
}
|
||
|
||
// 设置 Dubbo attachments(供下游 provider 通过 ctx.Value(constant.AttachmentKey) 解析)
|
||
ctx := context.WithValue(c.Request.Context(), constant.AttachmentKey, map[string]interface{}{
|
||
"user_id": strconv.FormatInt(userID.(int64), 10),
|
||
"star_id": strconv.FormatInt(starID.(int64), 10),
|
||
})
|
||
|
||
logger.Logger.Debug("Calling GetStarbookHome",
|
||
zap.Int64("user_id", userID.(int64)),
|
||
zap.Int64("star_id", starID.(int64)),
|
||
)
|
||
|
||
// 调用 assetService.GetMyAssets(分组后的全部藏品)
|
||
// 响应形态 {base, data: AssetListData(groups, total, page, ...)} — 与旧 starbook HomeItems 一致
|
||
resp, err := ctrl.assetClient.GetMyAssets(ctx, &pbAsset.GetMyAssetsRequest{})
|
||
if err != nil {
|
||
logger.Logger.Error("GetStarbookHome RPC failed",
|
||
zap.Error(err),
|
||
zap.Int64("user_id", userID.(int64)),
|
||
zap.Int64("star_id", starID.(int64)),
|
||
)
|
||
response.Error(c, http.StatusInternalServerError, "获取星册首页失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, resp)
|
||
}
|
||
|
||
// GetStarbookItems 获取星册藏品列表
|
||
// @Summary 获取星册藏品列表
|
||
// @Description 按 type/category/grade 分页获取星册藏品
|
||
// @Tags starbook
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security BearerAuth
|
||
// @Param type query string true "资产类型: regular/collection/activity"
|
||
// @Param category query string false "子分类,regular 时固定为 castlove"
|
||
// @Param grade query int false "等级,仅 regular 类型有效"
|
||
// @Param page query int false "页码,默认1"
|
||
// @Param page_size query int false "每页数量,默认20"
|
||
// @Success 200 {object} response.Response
|
||
// @Router /api/v1/starbook/items [get]
|
||
func (ctrl *StarbookController) GetStarbookItems(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
|
||
}
|
||
|
||
assetType := c.Query("type")
|
||
if assetType == "" {
|
||
response.Error(c, http.StatusBadRequest, "type 参数不能为空")
|
||
return
|
||
}
|
||
|
||
category := c.DefaultQuery("category", "castlove")
|
||
grade, _ := strconv.Atoi(c.DefaultQuery("grade", "0"))
|
||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||
|
||
ctx := context.WithValue(c.Request.Context(), constant.AttachmentKey, map[string]interface{}{
|
||
"user_id": strconv.FormatInt(userID.(int64), 10),
|
||
"star_id": strconv.FormatInt(starID.(int64), 10),
|
||
})
|
||
|
||
req := &pbAsset.GetAssetsByTypeRequest{
|
||
Type: assetType,
|
||
Category: category,
|
||
Grade: int32(grade),
|
||
Page: int32(page),
|
||
PageSize: int32(pageSize),
|
||
}
|
||
|
||
logger.Logger.Debug("Calling GetStarbookItems",
|
||
zap.Int64("user_id", userID.(int64)),
|
||
zap.Int64("star_id", starID.(int64)),
|
||
zap.String("type", assetType),
|
||
zap.Int32("page", int32(page)),
|
||
)
|
||
|
||
resp, err := ctrl.assetClient.GetAssetsByType(ctx, req)
|
||
if err != nil {
|
||
logger.Logger.Error("GetStarbookItems RPC failed",
|
||
zap.Error(err),
|
||
zap.Int64("user_id", userID.(int64)),
|
||
zap.Int64("star_id", starID.(int64)),
|
||
)
|
||
response.Error(c, http.StatusInternalServerError, "获取星册藏品列表失败: "+err.Error())
|
||
return
|
||
}
|
||
|
||
response.Success(c, resp)
|
||
}
|