diff --git a/README.md b/README.md index 522a253..013f2a1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## TODO -价格与优惠 +前端需要 token 化改造,以避免每次 basic 认证流程中 bcrypt 对比导致的性能对比 优化中间件,配置通用限速 diff --git a/web/core/error.go b/web/core/error.go index c88ed97..b1c14d9 100644 --- a/web/core/error.go +++ b/web/core/error.go @@ -19,7 +19,6 @@ type Err struct { func (e *Err) Error() string { if e.err != nil { slog.Debug(fmt.Sprintf("%s: %s", e.msg, e.err.Error())) - return e.msg } return e.msg } diff --git a/web/core/http.go b/web/core/http.go index b26a174..a2acdf2 100644 --- a/web/core/http.go +++ b/web/core/http.go @@ -114,7 +114,7 @@ func Query(in any) url.Values { switch value := value.Interface().(type) { case string: - out.Add(name, url.QueryEscape(value)) + out.Add(name, value) case int: out.Add(name, strconv.Itoa(value)) case bool: diff --git a/web/handlers/batch.go b/web/handlers/batch.go new file mode 100644 index 0000000..49ec324 --- /dev/null +++ b/web/handlers/batch.go @@ -0,0 +1,57 @@ +package handlers + +import ( + "platform/web/auth" + "platform/web/core" + c "platform/web/core" + g "platform/web/globals" + q "platform/web/queries" + "time" + + "github.com/gofiber/fiber/v2" +) + +// PageResourceBatch 分页查询套餐提取记录 +func PageResourceBatch(ctx *fiber.Ctx) error { + // 检查权限 + authCtx, err := auth.GetAuthCtx(ctx).PermitUser() + if err != nil { + return err + } + + // 解析请求参数 + req := new(PageResourceBatchReq) + if err := g.Validator.ParseBody(ctx, req); err != nil { + return err + } + + // 查询批次 + conds := q.LogsUserUsage.Where(q.LogsUserUsage.UserID.Eq(authCtx.User.ID)) + if req.TimeStart != nil { + conds.Where(q.LogsUserUsage.Time.Gte(*req.TimeStart)) + } + if req.TimeEnd != nil { + conds.Where(q.LogsUserUsage.Time.Lte(*req.TimeEnd)) + } + + list, total, err := q.LogsUserUsage.Where(conds). + Order(q.LogsUserUsage.Time.Desc()). + FindByPage(req.GetOffset(), req.GetLimit()) + if err != nil { + return core.NewBizErr("获取数据失败", err) + } + + // 返回数据 + return ctx.JSON(c.PageResp{ + Total: int(total), + List: list, + Page: req.GetPage(), + Size: req.GetSize(), + }) +} + +type PageResourceBatchReq struct { + c.PageReq + TimeStart *time.Time `json:"time_start"` + TimeEnd *time.Time `json:"time_end"` +} diff --git a/web/handlers/resource.go b/web/handlers/resource.go index 5194f2c..092c248 100644 --- a/web/handlers/resource.go +++ b/web/handlers/resource.go @@ -15,17 +15,7 @@ import ( "github.com/gofiber/fiber/v2" ) -type ListResourceShortReq struct { - core.PageReq - ResourceNo *string `json:"resource_no"` - Active *bool `json:"active"` - Type *int `json:"type"` - CreateAfter *time.Time `json:"create_after"` - CreateBefore *time.Time `json:"create_before"` - ExpireAfter *time.Time `json:"expire_after"` - ExpireBefore *time.Time `json:"expire_before"` -} - +// ListResourceShort 分页短效套餐 func ListResourceShort(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -96,7 +86,7 @@ func ListResourceShort(c *fiber.Ctx) error { }) } -type ListResourceLongReq struct { +type ListResourceShortReq struct { core.PageReq ResourceNo *string `json:"resource_no"` Active *bool `json:"active"` @@ -107,6 +97,7 @@ type ListResourceLongReq struct { ExpireBefore *time.Time `json:"expire_before"` } +// ListResourceLong 分页长效套餐 func ListResourceLong(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -177,9 +168,18 @@ func ListResourceLong(c *fiber.Ctx) error { }) } -type AllResourceReq struct { +type ListResourceLongReq struct { + core.PageReq + ResourceNo *string `json:"resource_no"` + Active *bool `json:"active"` + Type *int `json:"type"` + CreateAfter *time.Time `json:"create_after"` + CreateBefore *time.Time `json:"create_before"` + ExpireAfter *time.Time `json:"expire_after"` + ExpireBefore *time.Time `json:"expire_before"` } +// AllActiveResource 所有可用套餐 func AllActiveResource(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -235,23 +235,10 @@ func AllActiveResource(c *fiber.Ctx) error { return c.JSON(resources) } -type StatisticPersonalResp struct { - Short StatisticShort `json:"short"` - Long StatisticLong `json:"long"` -} - -type StatisticShort struct { - ResourceCount int `json:"resource_count"` - ResourceQuotaSum int `json:"resource_quota_sum"` - ResourceDailyFreeSum int `json:"resource_daily_free_sum"` -} - -type StatisticLong struct { - ResourceCount int `json:"resource_count"` - ResourceQuotaSum int `json:"resource_quota_sum"` - ResourceDailyFreeSum int `json:"resource_daily_free_sum"` +type AllResourceReq struct { } +// StatisticResourceFree 统计每日可用 func StatisticResourceFree(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -334,17 +321,24 @@ func StatisticResourceFree(c *fiber.Ctx) error { }) } -type StatisticResourceUsageReq struct { - ResourceNo *string `json:"resource_no"` - TimeAfter *time.Time `json:"time_after"` - TimeBefore *time.Time `json:"time_before"` +type StatisticPersonalResp struct { + Short StatisticShort `json:"short"` + Long StatisticLong `json:"long"` } -type StatisticResourceUsageResp []struct { - Date time.Time `json:"date"` - Count int `json:"count"` +type StatisticShort struct { + ResourceCount int `json:"resource_count"` + ResourceQuotaSum int `json:"resource_quota_sum"` + ResourceDailyFreeSum int `json:"resource_daily_free_sum"` } +type StatisticLong struct { + ResourceCount int `json:"resource_count"` + ResourceQuotaSum int `json:"resource_quota_sum"` + ResourceDailyFreeSum int `json:"resource_daily_free_sum"` +} + +// StatisticResourceUsage 统计每日用量 func StatisticResourceUsage(c *fiber.Ctx) error { // 检查权限 authCtx, err := auth.GetAuthCtx(c).PermitUser() @@ -402,10 +396,18 @@ func StatisticResourceUsage(c *fiber.Ctx) error { return c.JSON(data) } -type CreateResourceReq struct { - *s.CreateResourceData +type StatisticResourceUsageReq struct { + ResourceNo *string `json:"resource_no"` + TimeAfter *time.Time `json:"time_after"` + TimeBefore *time.Time `json:"time_before"` } +type StatisticResourceUsageResp []struct { + Date time.Time `json:"date"` + Count int `json:"count"` +} + +// CreateResource 创建套餐 func CreateResource(c *fiber.Ctx) error { // 检查权限 @@ -429,6 +431,11 @@ func CreateResource(c *fiber.Ctx) error { return nil } +type CreateResourceReq struct { + *s.CreateResourceData +} + +// ResourcePrice 套餐价格 func ResourcePrice(c *fiber.Ctx) error { // 检查权限 _, err := auth.GetAuthCtx(c).PermitSecretClient() @@ -447,7 +454,17 @@ func ResourcePrice(c *fiber.Ctx) error { if err != nil { return err } - return c.JSON(fiber.Map{ - "price": amount.StringFixed(2), + + // 计算折扣 + return c.JSON(ResourcePriceResp{ + Price: amount.StringFixed(2), + Discounted: 1, + DiscountedPrice: amount.StringFixed(2), }) } + +type ResourcePriceResp struct { + Price string `json:"price"` + Discounted float32 `json:"discounted"` + DiscountedPrice string `json:"discounted_price"` +} diff --git a/web/handlers/trade.go b/web/handlers/trade.go index 9be38e7..1d3b0d7 100644 --- a/web/handlers/trade.go +++ b/web/handlers/trade.go @@ -10,7 +10,6 @@ import ( g "platform/web/globals" m "platform/web/models" s "platform/web/services" - "reflect" "time" "github.com/gofiber/fiber/v2" @@ -154,9 +153,9 @@ func TradeCheck(c *fiber.Ctx) error { slog.Error("写入订单状态失败", "trade_no", req.TradeNo, "error", err) return } + err = w.Flush() if err != nil { - slog.Error("刷新缓冲区失败", "trade_no", req.TradeNo, "error", err, "errType", reflect.TypeOf(err)) return } diff --git a/web/routes.go b/web/routes.go index ee8bed4..0b270e7 100644 --- a/web/routes.go +++ b/web/routes.go @@ -36,10 +36,14 @@ func ApplyRouters(app *fiber.App) { resource.Post("/all", handlers.AllActiveResource) resource.Post("/list/short", handlers.ListResourceShort) resource.Post("/list/long", handlers.ListResourceLong) - resource.Post("/statistics/free", handlers.StatisticResourceFree) - resource.Post("/statistics/usage", handlers.StatisticResourceUsage) resource.Post("/create", handlers.CreateResource) resource.Post("/price", handlers.ResourcePrice) + resource.Post("/statistics/free", handlers.StatisticResourceFree) + resource.Post("/statistics/usage", handlers.StatisticResourceUsage) + + // 批次 + batch := api.Group("/batch") + batch.Post("/page", handlers.PageResourceBatch) // 通道 channel := api.Group("/channel") diff --git a/web/services/channel_baiyin.go b/web/services/channel_baiyin.go index af5a67d..d812268 100644 --- a/web/services/channel_baiyin.go +++ b/web/services/channel_baiyin.go @@ -86,7 +86,7 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int return nil, core.NewBizErr("获取可用节点失败", err) } if edgesResp.Total != count && len(edgesResp.Edges) != count { - return nil, core.NewBizErr("无可用节点,请稍后再试") + return nil, core.NewBizErr("地区可用节点数量不足 [%s, %s] [%s]") } edges := edgesResp.Edges @@ -161,7 +161,7 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int switch { case isShortType: - rs, err = q.ResourceShort.Debug(). + rs, err = q.ResourceShort. Where( q.ResourceShort.ID.Eq(*resource.ShortId), q.ResourceShort.Used.Eq(resource.Used),