实现批次检查接口 & 修复白银接口 url 二次编码问题

This commit is contained in:
2025-12-19 10:59:04 +08:00
parent 8f2e71849f
commit 2b190bd4e5
8 changed files with 124 additions and 48 deletions

View File

@@ -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
}

View File

@@ -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:

57
web/handlers/batch.go Normal file
View File

@@ -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"`
}

View File

@@ -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"`
}

View File

@@ -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
}

View File

@@ -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")

View File

@@ -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),