mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-15 23:22:59 +08:00
feat(quota): 用户 × 平台 USD 配额
为用户在 anthropic/openai/gemini/antigravity 四个平台上提供日/周/月 三个窗口的 USD 配额管控。配额语义:未设置=不限制,0=禁用,>0=美元上限。 两层模型: - 配置层:系统默认配额,以及 email/linuxdo/oidc/wechat/github/google/ dingtalk 七个鉴权来源的默认配额,存于 settings,以嵌套 JSON 整体读写 (系统 1 个 key + 每个来源 1 个 key),整体替换语义。 - 运行时层:user_platform_quota 表按用户记录实际配额,与配置层解耦。 后端:新增 ent schema 与 140_user_platform_quotas.sql 迁移、repository 与 service 端口、计费链路集成、管理端与用户端读写接口。 前端:管理端设置页配额编辑、用户配额管理 Modal、用户 Dashboard 展示、 中英文案。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
QTom
co-authored by
Claude Opus 4.7
parent
2f70d965bf
commit
6b39b344d8
@@ -42,6 +42,7 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/ent/userallowedgroup"
|
||||
"github.com/Wei-Shaw/sub2api/ent/userattributedefinition"
|
||||
"github.com/Wei-Shaw/sub2api/ent/userattributevalue"
|
||||
"github.com/Wei-Shaw/sub2api/ent/userplatformquota"
|
||||
"github.com/Wei-Shaw/sub2api/ent/usersubscription"
|
||||
)
|
||||
|
||||
@@ -992,6 +993,33 @@ func (f TraverseUserAttributeValue) Traverse(ctx context.Context, q ent.Query) e
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.UserAttributeValueQuery", q)
|
||||
}
|
||||
|
||||
// The UserPlatformQuotaFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type UserPlatformQuotaFunc func(context.Context, *ent.UserPlatformQuotaQuery) (ent.Value, error)
|
||||
|
||||
// Query calls f(ctx, q).
|
||||
func (f UserPlatformQuotaFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) {
|
||||
if q, ok := q.(*ent.UserPlatformQuotaQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected query type %T. expect *ent.UserPlatformQuotaQuery", q)
|
||||
}
|
||||
|
||||
// The TraverseUserPlatformQuota type is an adapter to allow the use of ordinary function as Traverser.
|
||||
type TraverseUserPlatformQuota func(context.Context, *ent.UserPlatformQuotaQuery) error
|
||||
|
||||
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
|
||||
func (f TraverseUserPlatformQuota) Intercept(next ent.Querier) ent.Querier {
|
||||
return next
|
||||
}
|
||||
|
||||
// Traverse calls f(ctx, q).
|
||||
func (f TraverseUserPlatformQuota) Traverse(ctx context.Context, q ent.Query) error {
|
||||
if q, ok := q.(*ent.UserPlatformQuotaQuery); ok {
|
||||
return f(ctx, q)
|
||||
}
|
||||
return fmt.Errorf("unexpected query type %T. expect *ent.UserPlatformQuotaQuery", q)
|
||||
}
|
||||
|
||||
// The UserSubscriptionFunc type is an adapter to allow the use of ordinary function as a Querier.
|
||||
type UserSubscriptionFunc func(context.Context, *ent.UserSubscriptionQuery) (ent.Value, error)
|
||||
|
||||
@@ -1088,6 +1116,8 @@ func NewQuery(q ent.Query) (Query, error) {
|
||||
return &query[*ent.UserAttributeDefinitionQuery, predicate.UserAttributeDefinition, userattributedefinition.OrderOption]{typ: ent.TypeUserAttributeDefinition, tq: q}, nil
|
||||
case *ent.UserAttributeValueQuery:
|
||||
return &query[*ent.UserAttributeValueQuery, predicate.UserAttributeValue, userattributevalue.OrderOption]{typ: ent.TypeUserAttributeValue, tq: q}, nil
|
||||
case *ent.UserPlatformQuotaQuery:
|
||||
return &query[*ent.UserPlatformQuotaQuery, predicate.UserPlatformQuota, userplatformquota.OrderOption]{typ: ent.TypeUserPlatformQuota, tq: q}, nil
|
||||
case *ent.UserSubscriptionQuery:
|
||||
return &query[*ent.UserSubscriptionQuery, predicate.UserSubscription, usersubscription.OrderOption]{typ: ent.TypeUserSubscription, tq: q}, nil
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user