fix: 三端联调测试 2 P1 + 2 P2 + 4 P3 修复

P1-07: billing get_or_create_usage 同步 max_* 列到当前计划限额
P1-08: relay handler 增加直接配额检查 (relay_requests/input/output_tokens)
P2-09: relay failover 成功后记录 tokens 并标记 completed
P2-10: Tauri agentStore saas-relay 模式下从 SaaS API 获取真实用量
P2-14: super_admin 合成 subscription + check_quota 放行
P3-19: 新建 ApiKeys.tsx 页面替代 ModelServices 路由
P3-15: antd destroyOnClose → destroyOnHidden (3处)
P3-16: ProTable onSearch → onSubmit (2处)
This commit is contained in:
iven
2026-04-14 17:48:22 +08:00
parent 45fd9fee7b
commit dd854479eb
11 changed files with 259 additions and 12 deletions

View File

@@ -114,7 +114,26 @@ pub async fn get_or_create_usage(pool: &PgPool, account_id: &str) -> SaasResult<
.await?;
if let Some(usage) = existing {
return Ok(usage);
// P1-07 修复: 同步当前计划限额到 max_* 列(防止计划变更后数据不一致)
let plan = get_account_plan(pool, account_id).await?;
let limits: PlanLimits = serde_json::from_value(plan.limits.clone())
.unwrap_or_else(|_| PlanLimits::free());
sqlx::query(
"UPDATE billing_usage_quotas SET max_input_tokens=$2, max_output_tokens=$3, \
max_relay_requests=$4, max_hand_executions=$5, max_pipeline_runs=$6, updated_at=NOW() \
WHERE id=$1"
)
.bind(&usage.id)
.bind(limits.max_input_tokens_monthly)
.bind(limits.max_output_tokens_monthly)
.bind(limits.max_relay_requests_monthly)
.bind(limits.max_hand_executions_monthly)
.bind(limits.max_pipeline_runs_monthly)
.execute(pool).await?;
let updated = sqlx::query_as::<_, UsageQuota>(
"SELECT * FROM billing_usage_quotas WHERE id = $1"
).bind(&usage.id).fetch_one(pool).await?;
return Ok(updated);
}
// 获取当前计划限额
@@ -288,8 +307,13 @@ pub async fn increment_dimension_by(
pub async fn check_quota(
pool: &PgPool,
account_id: &str,
role: &str,
quota_type: &str,
) -> SaasResult<QuotaCheck> {
// P2-14 修复: super_admin 不受配额限制
if role == "super_admin" {
return Ok(QuotaCheck { allowed: true, reason: None, current: 0, limit: None, remaining: None });
}
let usage = get_or_create_usage(pool, account_id).await?;
// 从当前 Plan 读取真实限额,而非 usage 表的 stale 冗余列
let plan = get_account_plan(pool, account_id).await?;