bindbox-game/internal/api/admin/scheduled_config_admin.go
邹方成 45815bfb7d chore: 清理无用文件与优化代码结构
refactor(utils): 修复密码哈希比较逻辑错误
feat(user): 新增按状态筛选优惠券接口
docs: 添加虚拟发货与任务中心相关文档
fix(wechat): 修正Code2Session上下文传递问题
test: 补充订单折扣与积分转换测试用例
build: 更新配置文件与构建脚本
style: 清理多余的空行与注释
2025-12-18 17:35:55 +08:00

158 lines
7.2 KiB
Go

package admin
import (
"net/http"
"time"
"errors"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/validation"
"bindbox-game/internal/code"
activitysvc "bindbox-game/internal/service/activity"
)
type setScheduledConfigRequest struct {
PlayType string `json:"play_type"`
DrawMode string `json:"draw_mode"`
MinParticipants int64 `json:"min_participants"`
ScheduledTime string `json:"scheduled_time"`
ScheduledDelayMinutes int64 `json:"scheduled_delay_minutes"`
IntervalMinutes int64 `json:"interval_minutes"`
RefundCouponType string `json:"refund_coupon_type"`
RefundCouponAmount float64 `json:"refund_coupon_amount"`
RefundCouponID int64 `json:"refund_coupon_id"`
}
type scheduledConfigResponse struct {
ActivityID int64 `json:"activity_id"`
PlayType string `json:"play_type"`
DrawMode string `json:"draw_mode"`
MinParticipants int64 `json:"min_participants"`
ScheduledTime string `json:"scheduled_time"`
ScheduledDelayMinutes int64 `json:"scheduled_delay_minutes"`
IntervalMinutes int64 `json:"interval_minutes"`
RefundCouponType string `json:"refund_coupon_type"`
RefundCouponAmount float64 `json:"refund_coupon_amount"`
RefundCouponID int64 `json:"refund_coupon_id"`
}
func (h *handler) SetScheduledConfig() core.HandlerFunc {
return func(ctx core.Context) {
if ctx.SessionUserInfo().IsSuper != 1 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "禁止操作"))
return
}
activityID, err := parsePathID(ctx, "activity_id")
if err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID"))
return
}
req := new(setScheduledConfigRequest)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
if req.DrawMode != "scheduled" && req.DrawMode != "instant" {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "draw_mode错误"))
return
}
if req.DrawMode == "scheduled" {
if req.MinParticipants <= 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "min_participants必须>0"))
return
}
var st time.Time
if req.ScheduledDelayMinutes > 0 {
st = time.Now().Add(time.Duration(req.ScheduledDelayMinutes) * time.Minute)
} else if req.IntervalMinutes > 0 {
st = time.Now().Add(time.Duration(req.IntervalMinutes) * time.Minute)
} else {
if req.ScheduledTime == "" {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "scheduled_time或scheduled_delay_minutes必填"))
return
}
var ok bool
if t, e := time.Parse(time.RFC3339, req.ScheduledTime); e == nil { st = t; ok = true }
if !ok {
if t2, e2 := time.ParseInLocation("2006-01-02 15:04:05", req.ScheduledTime, time.Local); e2 == nil { st = t2; ok = true }
}
if !ok {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "scheduled_time格式错误"))
return
}
}
if st.Before(time.Now().Add(1 * time.Minute)) {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "scheduled_time需晚于当前时间1分钟"))
return
}
req.ScheduledTime = st.UTC().Format(time.RFC3339)
}
var stPtr *time.Time
if req.ScheduledTime != "" { t := parseTimeFlexible(req.ScheduledTime); if !t.IsZero() { stPtr = &t } }
if req.ScheduledDelayMinutes > 0 && stPtr == nil { t := time.Now().Add(time.Duration(req.ScheduledDelayMinutes)*time.Minute); stPtr = &t }
if req.IntervalMinutes > 0 && stPtr == nil { t := time.Now().Add(time.Duration(req.IntervalMinutes)*time.Minute); stPtr = &t }
if err := h.activity.SaveActivityDrawConfig(ctx.RequestContext(), activityID, activitysvc.DrawConfig{ PlayType: req.PlayType, DrawMode: req.DrawMode, MinParticipants: req.MinParticipants, IntervalMinutes: req.IntervalMinutes, ScheduledTime: stPtr, RefundCouponID: req.RefundCouponID }); err != nil {
ctx.AbortWithError(core.Error(http.StatusInternalServerError, 160010, err.Error()))
return
}
resp := &scheduledConfigResponse{
ActivityID: activityID,
PlayType: req.PlayType,
DrawMode: req.DrawMode,
MinParticipants: req.MinParticipants,
ScheduledTime: req.ScheduledTime,
ScheduledDelayMinutes: req.ScheduledDelayMinutes,
IntervalMinutes: req.IntervalMinutes,
RefundCouponType: req.RefundCouponType,
RefundCouponAmount: req.RefundCouponAmount,
RefundCouponID: req.RefundCouponID,
}
ctx.Payload(resp)
}
}
func (h *handler) GetScheduledConfig() core.HandlerFunc {
return func(ctx core.Context) {
if ctx.SessionUserInfo().IsSuper != 1 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "禁止操作"))
return
}
activityID, err := parsePathID(ctx, "activity_id")
if err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID"))
return
}
dc, err := h.activity.GetActivityDrawConfig(ctx.RequestContext(), activityID)
if err != nil || dc == nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, 160011, "配置不存在"))
return
}
resp := &scheduledConfigResponse{ ActivityID: activityID, PlayType: dc.PlayType, DrawMode: dc.DrawMode, MinParticipants: dc.MinParticipants, ScheduledTime: func() string { if dc.ScheduledTime!=nil { return dc.ScheduledTime.UTC().Format(time.RFC3339) }; return "" }(), ScheduledDelayMinutes: 0, IntervalMinutes: dc.IntervalMinutes, RefundCouponType: "", RefundCouponAmount: 0, RefundCouponID: dc.RefundCouponID }
ctx.Payload(resp)
}
}
func parsePathID(ctx core.Context, name string) (int64, error) {
v := ctx.Param(name)
if v == "" { return 0, errors.New("missing id") }
id, err := strconvParseInt(v)
if err != nil { return 0, err }
return id, nil
}
func parseTimeFlexible(s string) time.Time {
if s == "" { return time.Time{} }
if t, err := time.Parse(time.RFC3339, s); err == nil { return t }
if t2, err2 := time.ParseInLocation("2006-01-02 15:04:05", s, time.Local); err2 == nil { return t2 }
return time.Time{}
}
func strconvParseInt(s string) (int64, error) {
var n int64
for i := 0; i < len(s); i++ {
c := s[i]
if c < '0' || c > '9' { return 0, errors.New("invalid id") }
n = n*10 + int64(c-'0')
}
return n, nil
}