2026-02-08 17:19:27 +08:00

176 lines
6.4 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 app
import (
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/logger"
"bindbox-game/internal/pkg/validation"
"bindbox-game/internal/repository/mysql"
"bindbox-game/internal/repository/mysql/dao"
usersvc "bindbox-game/internal/service/user"
"net/http"
)
type storeHandler struct {
logger logger.CustomLogger
readDB *dao.Query
user usersvc.Service
}
func NewStore(logger logger.CustomLogger, db mysql.Repo, user usersvc.Service) *storeHandler {
return &storeHandler{logger: logger, readDB: dao.Use(db.GetDbR()), user: user}
}
type listStoreItemsRequest struct {
Kind string `form:"kind"`
Page int `form:"page"`
PageSize int `form:"page_size"`
Keyword string `form:"keyword"` // 关键词搜索
PriceMin *int64 `form:"price_min"` // 最低积分价格(积分单位)
PriceMax *int64 `form:"price_max"` // 最高积分价格(积分单位)
CategoryID *int64 `form:"category_id"` // 分类ID筛选仅对product有效
}
type listStoreItem struct {
ID int64 `json:"id"`
Kind string `json:"kind"`
Name string `json:"name"`
MainImage string `json:"main_image"`
Price int64 `json:"price"`
PointsRequired float64 `json:"points_required"` // 积分(分/rate`
InStock bool `json:"in_stock"`
Status int32 `json:"status"`
DiscountType int32 `json:"discount_type"`
DiscountValue int64 `json:"discount_value"`
MinSpend int64 `json:"min_spend"`
Supported bool `json:"supported"`
}
type listStoreItemsResponse struct {
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
List []listStoreItem `json:"list"`
}
// ListStoreItemsForApp 获取积分商城商品列表
// @Summary 获取积分商城商品列表
// @Description 分页获取积分商城商品列表,支持按类型筛选(product/item_card/coupon)
// @Tags APP端.积分商城
// @Accept x-www-form-urlencoded
// @Produce json
// @Security LoginVerifyToken
// @Param kind query string false "商品类型: product(默认), item_card, coupon"
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Success 200 {object} listStoreItemsResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/store/items [get]
func (h *storeHandler) ListStoreItemsForApp() core.HandlerFunc {
return func(ctx core.Context) {
req := new(listStoreItemsRequest)
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
}
if req.PageSize > 100 {
req.PageSize = 100
}
var total int64
var list []listStoreItem
offset := (req.Page - 1) * req.PageSize
limit := req.PageSize
// 将积分价格转换为分进行查询
var priceMinCents, priceMaxCents int64
if req.PriceMin != nil && *req.PriceMin > 0 {
centsVal, _ := h.user.PointsToCents(ctx.RequestContext(), *req.PriceMin)
priceMinCents = centsVal
}
if req.PriceMax != nil && *req.PriceMax > 0 {
centsVal, _ := h.user.PointsToCents(ctx.RequestContext(), *req.PriceMax)
priceMaxCents = centsVal
}
switch req.Kind {
case "item_card":
q := h.readDB.SystemItemCards.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.SystemItemCards.Status.Eq(1))
// 关键词筛选
if req.Keyword != "" {
q = q.Where(h.readDB.SystemItemCards.Name.Like("%" + req.Keyword + "%"))
}
// 价格区间筛选
if priceMinCents > 0 {
q = q.Where(h.readDB.SystemItemCards.Price.Gte(priceMinCents))
}
if priceMaxCents > 0 {
q = q.Where(h.readDB.SystemItemCards.Price.Lte(priceMaxCents))
}
total, _ = q.Count()
rows, _ := q.Order(h.readDB.SystemItemCards.ID.Desc()).Offset(offset).Limit(limit).Find()
list = make([]listStoreItem, len(rows))
for i, it := range rows {
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.Price)
list[i] = listStoreItem{ID: it.ID, Kind: "item_card", Name: it.Name, Price: it.Price, PointsRequired: pts, Status: it.Status, Supported: true}
}
case "coupon":
q := h.readDB.SystemCoupons.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.SystemCoupons.Status.Eq(1))
// 关键词筛选
if req.Keyword != "" {
q = q.Where(h.readDB.SystemCoupons.Name.Like("%" + req.Keyword + "%"))
}
// 价格区间筛选 (优惠券用 DiscountValue)
if priceMinCents > 0 {
q = q.Where(h.readDB.SystemCoupons.DiscountValue.Gte(priceMinCents))
}
if priceMaxCents > 0 {
q = q.Where(h.readDB.SystemCoupons.DiscountValue.Lte(priceMaxCents))
}
total, _ = q.Count()
rows, _ := q.Order(h.readDB.SystemCoupons.ID.Desc()).Offset(offset).Limit(limit).Find()
list = make([]listStoreItem, len(rows))
for i, it := range rows {
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.DiscountValue)
list[i] = listStoreItem{ID: it.ID, Kind: "coupon", Name: it.Name, DiscountType: it.DiscountType, DiscountValue: it.DiscountValue, PointsRequired: pts, MinSpend: it.MinSpend, Status: it.Status, Supported: it.DiscountType == 1}
}
default: // product
q := h.readDB.Products.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Products.Status.Eq(1))
// 分类筛选
if req.CategoryID != nil && *req.CategoryID > 0 {
q = q.Where(h.readDB.Products.CategoryID.Eq(*req.CategoryID))
}
// 关键词筛选
if req.Keyword != "" {
q = q.Where(h.readDB.Products.Name.Like("%" + req.Keyword + "%"))
}
// 价格区间筛选
if priceMinCents > 0 {
q = q.Where(h.readDB.Products.Price.Gte(priceMinCents))
}
if priceMaxCents > 0 {
q = q.Where(h.readDB.Products.Price.Lte(priceMaxCents))
}
total, _ = q.Count()
rows, _ := q.Order(h.readDB.Products.ID.Desc()).Offset(offset).Limit(limit).Find()
list = make([]listStoreItem, len(rows))
for i, it := range rows {
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.Price)
list[i] = listStoreItem{ID: it.ID, Kind: "product", Name: it.Name, MainImage: parseFirstImage(it.ImagesJSON), Price: it.Price, PointsRequired: pts, InStock: it.Stock > 0 && it.Status == 1, Status: it.Status, Supported: true}
}
}
ctx.Payload(&listStoreItemsResponse{
Total: total,
Page: req.Page,
PageSize: req.PageSize,
List: list,
})
}
}