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 }