bindbox-game/internal/api/admin/game_pass_packages_admin.go

313 lines
9.4 KiB
Go

package admin
import (
"net/http"
"strconv"
"time"
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/validation"
"bindbox-game/internal/repository/mysql/model"
)
// ==================== 套餐管理 API ====================
type createGamePassPackageRequest struct {
Name string `json:"name" binding:"required"`
PassCount int32 `json:"pass_count" binding:"required,min=1"`
Price int64 `json:"price" binding:"required,min=0"`
OriginalPrice *int64 `json:"original_price"`
ActivityID *int64 `json:"activity_id"`
ValidDays *int32 `json:"valid_days"`
SortOrder *int32 `json:"sort_order"`
Status *int32 `json:"status"` // 1=上架 2=下架
}
type createGamePassPackageResponse struct {
ID int64 `json:"id"`
Message string `json:"message"`
}
// CreateGamePassPackage 创建次数卡套餐
// @Summary 创建次数卡套餐
// @Description 创建可购买的次数卡套餐
// @Tags 管理端.次数卡套餐
// @Accept json
// @Produce json
// @Param RequestBody body createGamePassPackageRequest true "请求参数"
// @Success 200 {object} createGamePassPackageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/game-pass-packages [post]
// @Security LoginVerifyToken
func (h *handler) CreateGamePassPackage() core.HandlerFunc {
return func(ctx core.Context) {
req := new(createGamePassPackageRequest)
res := new(createGamePassPackageResponse)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
now := time.Now()
m := &model.GamePassPackages{
Name: req.Name,
PassCount: req.PassCount,
Price: req.Price,
Status: 1, // 默认上架
CreatedAt: now,
UpdatedAt: now,
}
if req.OriginalPrice != nil {
m.OriginalPrice = *req.OriginalPrice
}
if req.ActivityID != nil && *req.ActivityID > 0 {
m.ActivityID = *req.ActivityID
}
if req.ValidDays != nil {
m.ValidDays = *req.ValidDays
}
if req.SortOrder != nil {
m.SortOrder = *req.SortOrder
}
if req.Status != nil {
m.Status = *req.Status
}
if err := h.writeDB.GamePassPackages.WithContext(ctx.RequestContext()).Create(m); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
return
}
res.ID = m.ID
res.Message = "创建成功"
ctx.Payload(res)
}
}
type modifyGamePassPackageRequest struct {
Name *string `json:"name"`
PassCount *int32 `json:"pass_count"`
Price *int64 `json:"price"`
OriginalPrice *int64 `json:"original_price"`
ActivityID *int64 `json:"activity_id"`
ValidDays *int32 `json:"valid_days"`
SortOrder *int32 `json:"sort_order"`
Status *int32 `json:"status"`
}
// ModifyGamePassPackage 修改次数卡套餐
// @Summary 修改次数卡套餐
// @Description 修改次数卡套餐配置
// @Tags 管理端.次数卡套餐
// @Accept json
// @Produce json
// @Param package_id path integer true "套餐ID"
// @Param RequestBody body modifyGamePassPackageRequest true "请求参数"
// @Success 200 {object} simpleMessageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/game-pass-packages/{package_id} [put]
// @Security LoginVerifyToken
func (h *handler) ModifyGamePassPackage() core.HandlerFunc {
return func(ctx core.Context) {
req := new(modifyGamePassPackageRequest)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
idStr := ctx.Param("package_id")
id, _ := strconv.ParseInt(idStr, 10, 64)
if id <= 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "套餐ID无效"))
return
}
set := map[string]any{}
if req.Name != nil {
set["name"] = *req.Name
}
if req.PassCount != nil {
set["pass_count"] = *req.PassCount
}
if req.Price != nil {
set["price"] = *req.Price
}
if req.OriginalPrice != nil {
set["original_price"] = *req.OriginalPrice
}
if req.ActivityID != nil {
set["activity_id"] = *req.ActivityID
}
if req.ValidDays != nil {
set["valid_days"] = *req.ValidDays
}
if req.SortOrder != nil {
set["sort_order"] = *req.SortOrder
}
if req.Status != nil {
set["status"] = *req.Status
}
if len(set) == 0 {
ctx.Payload(simpleMessageResponse{Message: "无修改"})
return
}
if _, err := h.writeDB.GamePassPackages.WithContext(ctx.RequestContext()).
Where(h.writeDB.GamePassPackages.ID.Eq(id)).Updates(set); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
return
}
ctx.Payload(simpleMessageResponse{Message: "修改成功"})
}
}
// DeleteGamePassPackage 删除次数卡套餐
// @Summary 删除次数卡套餐
// @Description 软删除次数卡套餐
// @Tags 管理端.次数卡套餐
// @Accept json
// @Produce json
// @Param package_id path integer true "套餐ID"
// @Success 200 {object} simpleMessageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/game-pass-packages/{package_id} [delete]
// @Security LoginVerifyToken
func (h *handler) DeleteGamePassPackage() core.HandlerFunc {
return func(ctx core.Context) {
idStr := ctx.Param("package_id")
id, _ := strconv.ParseInt(idStr, 10, 64)
if id <= 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "套餐ID无效"))
return
}
if _, err := h.writeDB.GamePassPackages.WithContext(ctx.RequestContext()).
Where(h.writeDB.GamePassPackages.ID.Eq(id)).Delete(); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
return
}
ctx.Payload(simpleMessageResponse{Message: "删除成功"})
}
}
// ==================== 套餐列表 ====================
type listGamePassPackagesRequest struct {
ActivityID *int64 `form:"activity_id"`
Status *int32 `form:"status"`
Page int `form:"page"`
PageSize int `form:"page_size"`
}
type gamePassPackageItem struct {
ID int64 `json:"id"`
Name string `json:"name"`
PassCount int32 `json:"pass_count"`
Price int64 `json:"price"`
OriginalPrice int64 `json:"original_price"`
ActivityID int64 `json:"activity_id"`
ActivityName string `json:"activity_name"`
ValidDays int32 `json:"valid_days"`
SortOrder int32 `json:"sort_order"`
Status int32 `json:"status"`
CreatedAt string `json:"created_at"`
}
type listGamePassPackagesResponse struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int64 `json:"total"`
List []gamePassPackageItem `json:"list"`
}
// ListGamePassPackages 次数卡套餐列表
// @Summary 次数卡套餐列表
// @Description 查询次数卡套餐列表
// @Tags 管理端.次数卡套餐
// @Accept json
// @Produce json
// @Param activity_id query integer false "活动ID"
// @Param status query integer false "状态: 1=上架 2=下架"
// @Param page query integer false "页码"
// @Param page_size query integer false "每页条数"
// @Success 200 {object} listGamePassPackagesResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/game-pass-packages [get]
// @Security LoginVerifyToken
func (h *handler) ListGamePassPackages() core.HandlerFunc {
return func(ctx core.Context) {
req := new(listGamePassPackagesRequest)
res := new(listGamePassPackagesResponse)
if err := ctx.ShouldBindForm(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 20
}
q := h.readDB.GamePassPackages.WithContext(ctx.RequestContext()).ReadDB()
if req.ActivityID != nil && *req.ActivityID > 0 {
q = q.Where(h.readDB.GamePassPackages.ActivityID.Eq(*req.ActivityID))
}
if req.Status != nil {
q = q.Where(h.readDB.GamePassPackages.Status.Eq(*req.Status))
}
total, err := q.Count()
if err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
return
}
packages, err := q.Order(h.readDB.GamePassPackages.SortOrder.Desc(), h.readDB.GamePassPackages.ID.Desc()).
Limit(req.PageSize).
Offset((req.Page - 1) * req.PageSize).
Find()
if err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
return
}
// 获取活动名称
activityIDs := make([]int64, 0)
for _, p := range packages {
if p.ActivityID > 0 {
activityIDs = append(activityIDs, p.ActivityID)
}
}
activityMap := make(map[int64]string)
if len(activityIDs) > 0 {
activities, _ := h.readDB.Activities.WithContext(ctx.RequestContext()).Where(h.readDB.Activities.ID.In(activityIDs...)).Find()
for _, a := range activities {
activityMap[a.ID] = a.Name
}
}
res.Page = req.Page
res.PageSize = req.PageSize
res.Total = total
res.List = make([]gamePassPackageItem, len(packages))
for i, p := range packages {
res.List[i] = gamePassPackageItem{
ID: p.ID,
Name: p.Name,
PassCount: p.PassCount,
Price: p.Price,
OriginalPrice: p.OriginalPrice,
ActivityID: p.ActivityID,
ActivityName: activityMap[p.ActivityID],
ValidDays: p.ValidDays,
SortOrder: p.SortOrder,
Status: p.Status,
CreatedAt: p.CreatedAt.Format("2006-01-02 15:04:05"),
}
}
ctx.Payload(res)
}
}