mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-26 06:24:32 +08:00
687ffc237d
Add dashboard-level app type filter to usage statistics, replacing the DataSourceBar with a more useful segmented control. All components (summary cards, trend chart, provider stats, model stats, request logs) now respond to the selected app filter. Backend: add optional app_type parameter to get_usage_summary, get_daily_trends, get_provider_stats, and get_model_stats queries. Frontend: new AppTypeFilter type, updated query keys with appType dimension for proper cache separation, and RequestLogTable local filter auto-locks when dashboard filter is active.
87 lines
2.6 KiB
TypeScript
87 lines
2.6 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 {
|
|
appType?: string;
|
|
refreshIntervalMs: number;
|
|
}
|
|
|
|
export function ModelStatsTable({
|
|
appType,
|
|
refreshIntervalMs,
|
|
}: ModelStatsTableProps) {
|
|
const { t } = useTranslation();
|
|
const { data: stats, isLoading } = useModelStats(appType, {
|
|
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>
|
|
);
|
|
}
|