mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 16:26:16 +08:00
87b80c66b2
* style: format code and apply clippy lint fixes * feat(usage): enhance dashboard with auto-refresh control and robust formatting - Add configurable auto-refresh interval toggle (off/5s/10s/30s/60s) to usage dashboard - Extract shared format utilities (fmtUsd, fmtInt, parseFiniteNumber, getLocaleFromLanguage) - Refactor request log time filtering to rolling vs fixed mode with validation - Use stable serializable query keys instead of filter objects - Handle NaN/Infinity safely in number formatting across all usage components - Use RFC 3339 date format in backend trend data
83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/ui/table";
|
|
import { useModelStats } from "@/lib/query/usage";
|
|
import { fmtUsd } from "./format";
|
|
|
|
interface ModelStatsTableProps {
|
|
refreshIntervalMs: number;
|
|
}
|
|
|
|
export function ModelStatsTable({ refreshIntervalMs }: ModelStatsTableProps) {
|
|
const { t } = useTranslation();
|
|
const { data: stats, isLoading } = useModelStats({
|
|
refetchInterval: refreshIntervalMs > 0 ? refreshIntervalMs : false,
|
|
});
|
|
|
|
if (isLoading) {
|
|
return <div className="h-[400px] animate-pulse rounded bg-gray-100" />;
|
|
}
|
|
|
|
return (
|
|
<div className="rounded-lg border border-border/50 bg-card/40 backdrop-blur-sm overflow-hidden">
|
|
<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>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{stats?.length === 0 ? (
|
|
<TableRow>
|
|
<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">
|
|
{fmtUsd(stat.totalCost, 4)}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
{fmtUsd(stat.avgCostPerRequest, 6)}
|
|
</TableCell>
|
|
</TableRow>
|
|
))
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
);
|
|
}
|