/*
Copyright (C) 2025 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
import React, { useMemo } from 'react';
import { TrendingUp } from 'lucide-react';
import Sparkline from './Sparkline';
import { renderQuota } from '../../helpers';
const formatMD = (d) => {
const m = d.getMonth() + 1;
const day = d.getDate();
return `${m}/${day}`;
};
const BentoTrend = ({
dailyStats = [],
topModels = [],
className = '',
}) => {
const counts = useMemo(() => dailyStats.map((d) => d.count), [dailyStats]);
const costs = useMemo(() => dailyStats.map((d) => d.cost), [dailyStats]);
const totalCalls = counts.reduce((s, v) => s + v, 0);
const totalCost = costs.reduce((s, v) => s + v, 0);
const avg = totalCalls > 0 ? (totalCalls / Math.max(counts.length, 1)).toFixed(1) : '0.0';
const peak = counts.length > 0 ? Math.max(...counts) : 0;
const topMax = topModels[0]?.count || 0;
return (
Token 使用趋势
近 7 天
{totalCalls} 次
· 日均{' '}
{avg}
花费
{totalCost > 0 ? renderQuota(totalCost) : '—'}
{dailyStats.map((d, i) => (
0
? 'font-semibold text-slate-900 dark:text-white'
: 'text-slate-300 dark:text-white/30'
}`}
title={`${d.date.getMonth() + 1}月${d.date.getDate()}日 ${d.count} 次`}
>
{formatMD(d.date)}
))}
峰值{' '}
{peak} 次
{topModels.length > 0 && (
Top 5 模型
近 30 日
{topModels.map((m, i) => {
const pct = topMax > 0 ? (m.count / topMax) * 100 : 0;
return (
-
{i + 1}
{m.name}
{m.count}
);
})}
)}
);
};
export default BentoTrend;