mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-19 11:10:49 +08:00
feat(usage): add success rate column to model stats table
This commit is contained in:
@@ -19,9 +19,13 @@ export interface ModelStatsCardProps {
|
|||||||
hasPrices: boolean;
|
hasPrices: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type SortKey = 'model' | 'requests' | 'tokens' | 'cost';
|
type SortKey = 'model' | 'requests' | 'tokens' | 'cost' | 'successRate';
|
||||||
type SortDir = 'asc' | 'desc';
|
type SortDir = 'asc' | 'desc';
|
||||||
|
|
||||||
|
interface ModelStatWithRate extends ModelStat {
|
||||||
|
successRate: number;
|
||||||
|
}
|
||||||
|
|
||||||
export function ModelStatsCard({ modelStats, loading, hasPrices }: ModelStatsCardProps) {
|
export function ModelStatsCard({ modelStats, loading, hasPrices }: ModelStatsCardProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [sortKey, setSortKey] = useState<SortKey>('requests');
|
const [sortKey, setSortKey] = useState<SortKey>('requests');
|
||||||
@@ -36,8 +40,11 @@ export function ModelStatsCard({ modelStats, loading, hasPrices }: ModelStatsCar
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const sorted = useMemo(() => {
|
const sorted = useMemo((): ModelStatWithRate[] => {
|
||||||
const list = [...modelStats];
|
const list: ModelStatWithRate[] = modelStats.map((s) => ({
|
||||||
|
...s,
|
||||||
|
successRate: s.requests > 0 ? (s.successCount / s.requests) * 100 : 100,
|
||||||
|
}));
|
||||||
const dir = sortDir === 'asc' ? 1 : -1;
|
const dir = sortDir === 'asc' ? 1 : -1;
|
||||||
list.sort((a, b) => {
|
list.sort((a, b) => {
|
||||||
if (sortKey === 'model') return dir * a.model.localeCompare(b.model);
|
if (sortKey === 'model') return dir * a.model.localeCompare(b.model);
|
||||||
@@ -67,6 +74,9 @@ export function ModelStatsCard({ modelStats, loading, hasPrices }: ModelStatsCar
|
|||||||
<th className={styles.sortableHeader} onClick={() => handleSort('tokens')}>
|
<th className={styles.sortableHeader} onClick={() => handleSort('tokens')}>
|
||||||
{t('usage_stats.tokens_count')}{arrow('tokens')}
|
{t('usage_stats.tokens_count')}{arrow('tokens')}
|
||||||
</th>
|
</th>
|
||||||
|
<th className={styles.sortableHeader} onClick={() => handleSort('successRate')}>
|
||||||
|
{t('usage_stats.success_rate')}{arrow('successRate')}
|
||||||
|
</th>
|
||||||
{hasPrices && (
|
{hasPrices && (
|
||||||
<th className={styles.sortableHeader} onClick={() => handleSort('cost')}>
|
<th className={styles.sortableHeader} onClick={() => handleSort('cost')}>
|
||||||
{t('usage_stats.total_cost')}{arrow('cost')}
|
{t('usage_stats.total_cost')}{arrow('cost')}
|
||||||
@@ -88,6 +98,19 @@ export function ModelStatsCard({ modelStats, loading, hasPrices }: ModelStatsCar
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{formatTokensInMillions(stat.tokens)}</td>
|
<td>{formatTokensInMillions(stat.tokens)}</td>
|
||||||
|
<td>
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
stat.successRate >= 95
|
||||||
|
? styles.statSuccess
|
||||||
|
: stat.successRate >= 80
|
||||||
|
? styles.statNeutral
|
||||||
|
: styles.statFailure
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{stat.successRate.toFixed(1)}%
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
{hasPrices && <td>{stat.cost > 0 ? formatUsd(stat.cost) : '--'}</td>}
|
{hasPrices && <td>{stat.cost > 0 ? formatUsd(stat.cost) : '--'}</td>}
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user