feat(admin): 计费 & 用量合成一页 —— 顶部配规则、下方看结果(闭环)

按"配置和观测放一个页面"收口:删掉重复的「计价 & 预算」页(其预算区块是 mock),
把真·计价配置并入「计费 & 用量」,形成 规则→扣费→观测 一页闭环。
- 新组件 BillingRules:全局 token→积分汇率 + 每模型 单价/币种/积分权重(读写
  /admin/pricing + /admin/billing-config),改完对后续任务实时生效。
- UsagePage:顶部「计费规则」(配置端) + 下方「用量观测」(按规则折算后的实际消耗)。
- 删 PricingPage + /pricing 路由;api 加 credit_weight / getBillingConfig / saveBillingConfig。

live 验证(preview):改汇率保存→持久化→新任务按新汇率扣→用量观测反映;
tsc + 41 vitest 全过;无 PricingPage 残引。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-07 13:26:33 +08:00
parent e2fc2d366c
commit 11d321f218
5 changed files with 228 additions and 291 deletions
+13 -2
View File
@@ -1,8 +1,10 @@
import { useEffect, useMemo, useState, type ReactNode } from "react";
import { adminUsage, type UsageReport, type UsageTenantSum, type UsageDay } from "../api";
import { BillingRules } from "../components/BillingRules";
// 管理端「用量 & 计费」= SaaS P2 计量的观测面:全平台 / 单租户的 token · 积分 · 成本口径
// 数据来自 /api/v1/admin/usage系统级跨租户)。金额/积分均为微单位(×10⁻⁶),展示时 ÷1e6
// 管理端「用量 & 计费」= 计费闭环一页:顶部配「规则」(单价/积分权重/汇率),下方看「结果」(用量观测)
// 规则→扣费→观测:改规则即对后续任务生效,用量观测(读 /admin/usage系统级跨租户)即其结果
// 金额/积分均为微单位(×10⁻⁶),展示时 ÷1e6。
const MICRO = 1_000_000;
const credits = (micro: number) => (micro / MICRO).toLocaleString("zh-CN", { maximumFractionDigits: 2 });
@@ -75,6 +77,15 @@ export function UsagePage() {
return (
<div className="space-y-6">
{/* 配置端:计费规则(改规则即对后续任务生效) */}
<BillingRules onSaved={() => void load()} />
{/* 观测端:用量结果 */}
<div className="flex items-center gap-2 pt-1">
<h3 className="text-sm font-semibold text-gray-700"></h3>
<span className="text-[11px] text-gray-400"></span>
</div>
{/* 顶栏:租户筛选 + 区间 + 刷新 */}
<div className="flex flex-wrap items-center justify-between gap-3">
<div className="flex items-center gap-2">