feat(ui): add usage dashboard components

Add UsageDashboard with summary cards, trend chart, and data tables.
Implement model pricing configuration panel.
Add request log viewer with filtering and detail panel.
This commit is contained in:
YoVinchen
2025-12-03 00:25:41 +08:00
parent 38e8949152
commit 434ffd559d
9 changed files with 863 additions and 290 deletions
+44 -16
View File
@@ -1,6 +1,13 @@
import { useTranslation } from 'react-i18next';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { useModelStats } from '@/lib/query/usage';
import { useTranslation } from "react-i18next";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useModelStats } from "@/lib/query/usage";
export function ModelStatsTable() {
const { t } = useTranslation();
@@ -11,32 +18,53 @@ export function ModelStatsTable() {
}
return (
<div className="rounded-md border">
<div className="rounded-md bg-card/60 shadow-sm">
<Table>
<TableHeader>
<TableRow>
<TableHead>{t('usage.model', '模型')}</TableHead>
<TableHead className="text-right">{t('usage.requests', '请求数')}</TableHead>
<TableHead className="text-right">{t('usage.tokens', 'Tokens')}</TableHead>
<TableHead className="text-right">{t('usage.totalCost', '总成本')}</TableHead>
<TableHead className="text-right">{t('usage.avgCost', '平均成本')}</TableHead>
<TableHead>{t("usage.model", "模型")}</TableHead>
<TableHead className="text-right">
{t("usage.requests", "请求数")}
</TableHead>
<TableHead className="text-right">
{t("usage.tokens", "Tokens")}
</TableHead>
<TableHead className="text-right">
{t("usage.totalCost", "总成本")}
</TableHead>
<TableHead className="text-right">
{t("usage.avgCost", "平均成本")}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{stats?.length === 0 ? (
<TableRow>
<TableCell colSpan={5} className="text-center text-muted-foreground">
{t('usage.noData', '暂无数据')}
<TableCell
colSpan={5}
className="text-center text-muted-foreground"
>
{t("usage.noData", "暂无数据")}
</TableCell>
</TableRow>
) : (
stats?.map((stat) => (
<TableRow key={stat.model}>
<TableCell className="font-mono text-sm">{stat.model}</TableCell>
<TableCell className="text-right">{stat.requestCount.toLocaleString()}</TableCell>
<TableCell className="text-right">{stat.totalTokens.toLocaleString()}</TableCell>
<TableCell className="text-right">${parseFloat(stat.totalCost).toFixed(4)}</TableCell>
<TableCell className="text-right">${parseFloat(stat.avgCostPerRequest).toFixed(6)}</TableCell>
<TableCell className="font-mono text-sm">
{stat.model}
</TableCell>
<TableCell className="text-right">
{stat.requestCount.toLocaleString()}
</TableCell>
<TableCell className="text-right">
{stat.totalTokens.toLocaleString()}
</TableCell>
<TableCell className="text-right">
${parseFloat(stat.totalCost).toFixed(4)}
</TableCell>
<TableCell className="text-right">
${parseFloat(stat.avgCostPerRequest).toFixed(6)}
</TableCell>
</TableRow>
))
)}