Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 25s
feat(admin): 新增工会管理功能 feat(activity): 添加活动管理相关服务 feat(user): 实现用户道具卡和积分管理 feat(guild): 新增工会成员管理功能 fix: 修复数据库连接配置 fix: 修正jwtoken导入路径 fix: 解决端口冲突问题 style: 统一代码格式和注释风格 style: 更新项目常量命名 docs: 添加项目框架和开发规范文档 docs: 更新接口文档注释 chore: 移除无用代码和文件 chore: 更新Makefile和配置文件 chore: 清理日志文件 test: 添加道具卡测试脚本
378 lines
13 KiB
Go
378 lines
13 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"
|
||
)
|
||
|
||
type simpleMessageResponse struct {
|
||
Message string `json:"message"`
|
||
}
|
||
|
||
type createItemCardRequest struct {
|
||
Name string `json:"name" binding:"required"`
|
||
Status int32 `json:"status"`
|
||
CardType int32 `json:"card_type" binding:"required"`
|
||
ScopeType int32 `json:"scope_type" binding:"required"`
|
||
ActivityCategoryID int64 `json:"activity_category_id"`
|
||
ActivityID int64 `json:"activity_id"`
|
||
IssueID int64 `json:"issue_id"`
|
||
Price int64 `json:"price" binding:"required"`
|
||
ValidStartUnix *int64 `json:"valid_start_unix"`
|
||
ValidEndUnix *int64 `json:"valid_end_unix"`
|
||
EffectType int32 `json:"effect_type" binding:"required"`
|
||
RewardMultiplierX1000 int32 `json:"reward_multiplier_x1000"`
|
||
BoostRateX1000 int32 `json:"boost_rate_x1000"`
|
||
StackingStrategy int32 `json:"stacking_strategy"`
|
||
MaxEffectValueX1000 int32 `json:"max_effect_value_x1000"`
|
||
Remark string `json:"remark"`
|
||
}
|
||
|
||
type createItemCardResponse struct {
|
||
ID int64 `json:"id"`
|
||
Message string `json:"message"`
|
||
}
|
||
|
||
// CreateSystemItemCard 创建道具卡
|
||
// @Summary 创建道具卡
|
||
// @Description 管理员创建新的道具卡,支持设置类型、效果、有效期等属性
|
||
// @Tags 管理端.运营管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param RequestBody body createItemCardRequest true "创建道具卡请求参数"
|
||
// @Success 200 {object} createItemCardResponse
|
||
// @Failure 400 {object} code.Failure "参数错误"
|
||
// @Failure 401 {object} code.Failure "未授权"
|
||
// @Failure 403 {object} code.Failure "无权限,仅超管可操作"
|
||
// @Failure 500 {object} code.Failure "服务器内部错误"
|
||
// @Router /api/admin/system_item_cards [post]
|
||
func (h *handler) CreateSystemItemCard() core.HandlerFunc {
|
||
return func(ctx core.Context) {
|
||
req := new(createItemCardRequest)
|
||
res := new(createItemCardResponse)
|
||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||
return
|
||
}
|
||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||
return
|
||
}
|
||
item := &model.SystemItemCards{
|
||
Name: req.Name,
|
||
Status: func() int32 {
|
||
if req.Status == 0 {
|
||
return 1
|
||
}
|
||
return req.Status
|
||
}(),
|
||
CardType: req.CardType,
|
||
ScopeType: req.ScopeType,
|
||
ActivityCategoryID: req.ActivityCategoryID,
|
||
ActivityID: req.ActivityID,
|
||
IssueID: req.IssueID,
|
||
Price: req.Price,
|
||
EffectType: req.EffectType,
|
||
RewardMultiplierX1000: req.RewardMultiplierX1000,
|
||
BoostRateX1000: req.BoostRateX1000,
|
||
StackingStrategy: func() int32 {
|
||
if req.StackingStrategy == 0 {
|
||
return 1
|
||
}
|
||
return req.StackingStrategy
|
||
}(),
|
||
MaxEffectValueX1000: req.MaxEffectValueX1000,
|
||
Remark: req.Remark,
|
||
}
|
||
do := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext())
|
||
if req.ValidStartUnix != nil {
|
||
item.ValidStart = time.Unix(*req.ValidStartUnix, 0)
|
||
}
|
||
if req.ValidEndUnix != nil {
|
||
item.ValidEnd = time.Unix(*req.ValidEndUnix, 0)
|
||
} else {
|
||
do = do.Omit(h.writeDB.SystemItemCards.ValidEnd)
|
||
}
|
||
if err := do.Create(item); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
|
||
return
|
||
}
|
||
res.ID = item.ID
|
||
res.Message = "操作成功"
|
||
ctx.Payload(res)
|
||
}
|
||
}
|
||
|
||
type modifyItemCardRequest struct {
|
||
Name *string `json:"name"`
|
||
Status *int32 `json:"status"`
|
||
CardType *int32 `json:"card_type"`
|
||
ScopeType *int32 `json:"scope_type"`
|
||
ActivityCategoryID *int64 `json:"activity_category_id"`
|
||
ActivityID *int64 `json:"activity_id"`
|
||
IssueID *int64 `json:"issue_id"`
|
||
Price *int64 `json:"price"`
|
||
ValidStartUnix *int64 `json:"valid_start_unix"`
|
||
ValidEndUnix *int64 `json:"valid_end_unix"`
|
||
EffectType *int32 `json:"effect_type"`
|
||
RewardMultiplierX1000 *int32 `json:"reward_multiplier_x1000"`
|
||
BoostRateX1000 *int32 `json:"boost_rate_x1000"`
|
||
StackingStrategy *int32 `json:"stacking_strategy"`
|
||
MaxEffectValueX1000 *int32 `json:"max_effect_value_x1000"`
|
||
Remark *string `json:"remark"`
|
||
}
|
||
|
||
// ModifySystemItemCard 修改道具卡
|
||
// @Summary 修改道具卡
|
||
// @Description 管理员修改道具卡信息,支持修改名称、价格、有效期等属性
|
||
// @Tags 管理端.运营管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param item_card_id path integer true "道具卡ID"
|
||
// @Param RequestBody body modifyItemCardRequest true "修改道具卡请求参数"
|
||
// @Success 200 {object} simpleMessageResponse
|
||
// @Failure 400 {object} code.Failure "参数错误"
|
||
// @Failure 401 {object} code.Failure "未授权"
|
||
// @Failure 403 {object} code.Failure "无权限,仅超管可操作"
|
||
// @Failure 500 {object} code.Failure "服务器内部错误"
|
||
// @Router /api/admin/system_item_cards/{item_card_id} [put]
|
||
func (h *handler) ModifySystemItemCard() core.HandlerFunc {
|
||
return func(ctx core.Context) {
|
||
req := new(modifyItemCardRequest)
|
||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||
return
|
||
}
|
||
idStr := ctx.Param("item_card_id")
|
||
id, _ := strconv.ParseInt(idStr, 10, 64)
|
||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||
return
|
||
}
|
||
set := map[string]any{}
|
||
if req.Name != nil {
|
||
set["name"] = *req.Name
|
||
}
|
||
if req.Status != nil {
|
||
set["status"] = *req.Status
|
||
}
|
||
if req.CardType != nil {
|
||
set["card_type"] = *req.CardType
|
||
}
|
||
if req.ScopeType != nil {
|
||
set["scope_type"] = *req.ScopeType
|
||
}
|
||
if req.ActivityCategoryID != nil {
|
||
set["activity_category_id"] = *req.ActivityCategoryID
|
||
}
|
||
if req.ActivityID != nil {
|
||
set["activity_id"] = *req.ActivityID
|
||
}
|
||
if req.IssueID != nil {
|
||
set["issue_id"] = *req.IssueID
|
||
}
|
||
if req.Price != nil {
|
||
set["price"] = *req.Price
|
||
}
|
||
if req.EffectType != nil {
|
||
set["effect_type"] = *req.EffectType
|
||
}
|
||
if req.RewardMultiplierX1000 != nil {
|
||
set["reward_multiplier_x1000"] = *req.RewardMultiplierX1000
|
||
}
|
||
if req.BoostRateX1000 != nil {
|
||
set["boost_rate_x1000"] = *req.BoostRateX1000
|
||
}
|
||
if req.StackingStrategy != nil {
|
||
set["stacking_strategy"] = *req.StackingStrategy
|
||
}
|
||
if req.MaxEffectValueX1000 != nil {
|
||
set["max_effect_value_x1000"] = *req.MaxEffectValueX1000
|
||
}
|
||
if req.Remark != nil {
|
||
set["remark"] = *req.Remark
|
||
}
|
||
if req.ValidStartUnix != nil {
|
||
set["valid_start"] = time.Unix(*req.ValidStartUnix, 0)
|
||
}
|
||
if req.ValidEndUnix != nil {
|
||
set["valid_end"] = time.Unix(*req.ValidEndUnix, 0)
|
||
}
|
||
if len(set) == 0 {
|
||
ctx.Payload(simpleMessageResponse{Message: "操作成功"})
|
||
return
|
||
}
|
||
if _, err := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemItemCards.ID.Eq(id)).Updates(set); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
|
||
return
|
||
}
|
||
ctx.Payload(simpleMessageResponse{Message: "操作成功"})
|
||
}
|
||
}
|
||
|
||
// DeleteSystemItemCard 删除道具卡
|
||
// @Summary 删除道具卡
|
||
// @Description 管理员删除指定的道具卡
|
||
// @Tags 管理端.运营管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param item_card_id path integer true "道具卡ID"
|
||
// @Success 200 {object} simpleMessageResponse
|
||
// @Failure 400 {object} code.Failure "参数错误"
|
||
// @Failure 401 {object} code.Failure "未授权"
|
||
// @Failure 403 {object} code.Failure "无权限,仅超管可操作"
|
||
// @Failure 500 {object} code.Failure "服务器内部错误"
|
||
// @Router /api/admin/system_item_cards/{item_card_id} [delete]
|
||
func (h *handler) DeleteSystemItemCard() core.HandlerFunc {
|
||
return func(ctx core.Context) {
|
||
idStr := ctx.Param("item_card_id")
|
||
id, _ := strconv.ParseInt(idStr, 10, 64)
|
||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||
return
|
||
}
|
||
if _, err := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemItemCards.ID.Eq(id)).Delete(); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
|
||
return
|
||
}
|
||
ctx.Payload(simpleMessageResponse{Message: "操作成功"})
|
||
}
|
||
}
|
||
|
||
type listItemCardsRequest struct {
|
||
Name string `form:"name"`
|
||
Status int32 `form:"status"`
|
||
CardType int32 `form:"card_type"`
|
||
ScopeType int32 `form:"scope_type"`
|
||
Page int `form:"page"`
|
||
PageSize int `form:"page_size"`
|
||
}
|
||
|
||
type itemCardListItem struct {
|
||
*model.SystemItemCards
|
||
}
|
||
|
||
type listItemCardsResponse struct {
|
||
Page int `json:"page"`
|
||
PageSize int `json:"page_size"`
|
||
Total int64 `json:"total"`
|
||
List []itemCardListItem `json:"list"`
|
||
}
|
||
|
||
// ListSystemItemCards 获取道具卡列表
|
||
// @Summary 获取道具卡列表
|
||
// @Description 管理员获取道具卡列表,支持按名称、状态、类型等条件筛选
|
||
// @Tags 管理端.运营管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param name query string false "道具卡名称"
|
||
// @Param status query integer false "状态:1启用 2禁用"
|
||
// @Param card_type query integer false "道具卡类型:1抽奖卡 2加成卡 3保底卡"
|
||
// @Param scope_type query integer false "适用范围:1全局 2活动分类 3活动 4期次"
|
||
// @Param page query integer false "页码,默认1"
|
||
// @Param page_size query integer false "每页条数,默认10"
|
||
// @Success 200 {object} listItemCardsResponse
|
||
// @Failure 400 {object} code.Failure "参数错误"
|
||
// @Failure 401 {object} code.Failure "未授权"
|
||
// @Failure 500 {object} code.Failure "服务器内部错误"
|
||
// @Router /api/admin/system_item_cards [get]
|
||
func (h *handler) ListSystemItemCards() core.HandlerFunc {
|
||
return func(ctx core.Context) {
|
||
req := new(listItemCardsRequest)
|
||
res := new(listItemCardsResponse)
|
||
if err := ctx.ShouldBindForm(req); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||
return
|
||
}
|
||
q := h.readDB.SystemItemCards.WithContext(ctx.RequestContext()).ReadDB()
|
||
if req.Name != "" {
|
||
q = q.Where(h.readDB.SystemItemCards.Name.Like("%" + req.Name + "%"))
|
||
}
|
||
if req.Status != 0 {
|
||
q = q.Where(h.readDB.SystemItemCards.Status.Eq(req.Status))
|
||
}
|
||
if req.CardType != 0 {
|
||
q = q.Where(h.readDB.SystemItemCards.CardType.Eq(req.CardType))
|
||
}
|
||
if req.ScopeType != 0 {
|
||
q = q.Where(h.readDB.SystemItemCards.ScopeType.Eq(req.ScopeType))
|
||
}
|
||
total, err := q.Count()
|
||
if err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error()))
|
||
return
|
||
}
|
||
if req.Page <= 0 {
|
||
req.Page = 1
|
||
}
|
||
if req.PageSize <= 0 {
|
||
req.PageSize = 20
|
||
}
|
||
if req.PageSize > 100 {
|
||
req.PageSize = 100
|
||
}
|
||
rows, err := q.Order(h.readDB.SystemItemCards.ID.Desc()).Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Find()
|
||
if err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error()))
|
||
return
|
||
}
|
||
res.Page = req.Page
|
||
res.PageSize = req.PageSize
|
||
res.Total = total
|
||
res.List = make([]itemCardListItem, len(rows))
|
||
for i, r := range rows {
|
||
res.List[i] = itemCardListItem{SystemItemCards: r}
|
||
}
|
||
ctx.Payload(res)
|
||
}
|
||
}
|
||
|
||
type assignItemCardRequest struct {
|
||
CardID int64 `json:"card_id" binding:"required"`
|
||
Quantity int `json:"quantity"`
|
||
}
|
||
|
||
// AssignUserItemCard 给用户分配道具卡
|
||
// @Summary 给用户分配道具卡
|
||
// @Description 管理员给指定用户分配道具卡,可指定数量
|
||
// @Tags 管理端.运营管理
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param user_id path integer true "用户ID"
|
||
// @Param RequestBody body assignItemCardRequest true "分配道具卡请求参数"
|
||
// @Success 200 {object} simpleMessageResponse
|
||
// @Failure 400 {object} code.Failure "参数错误"
|
||
// @Failure 401 {object} code.Failure "未授权"
|
||
// @Failure 403 {object} code.Failure "无权限,仅超管可操作"
|
||
// @Failure 500 {object} code.Failure "服务器内部错误"
|
||
// @Router /api/admin/users/{user_id}/item_cards [post]
|
||
func (h *handler) AssignUserItemCard() core.HandlerFunc {
|
||
return func(ctx core.Context) {
|
||
req := new(assignItemCardRequest)
|
||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||
return
|
||
}
|
||
userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64)
|
||
if err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID"))
|
||
return
|
||
}
|
||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||
return
|
||
}
|
||
if err := h.user.AddItemCard(ctx.RequestContext(), userID, req.CardID, req.Quantity); err != nil {
|
||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
|
||
return
|
||
}
|
||
ctx.Payload(simpleMessageResponse{Message: "操作成功"})
|
||
}
|
||
}
|