refactor(dashboard): collapse usage section into a single row

Merge the two "by Model" pies (Token Usage + API Requests) into one
dual-pie card with a shared right-side vertical legend and per-donut
center totals, drop the standalone API-Key Top 10 chart, and put the
combined chart side-by-side with the User Top 10 ranking in one row
with the same 16/8 column ratio used by the System Load section above.

* New component usage-charts/usage-by-model.tsx owns both metric queries
  (group_by=['date','route']), aggregates a shared route→color map so
  the legend toggles both donuts together, and renders two pies at
  centers ('20%','50%') and ('60%','50%') with radius ['50%','70%'].
* new-usage.tsx no longer mounts ApiRequestsByModel / TokenUsageByModel
  / TopTokenUsageByApiKey; layout collapses to two columns sized
  (lg=24 xl=16) and (lg=24 xl=8).
* Delete unused token-usage-by-model.tsx, api-requests-by-model.tsx,
  top-token-usage-by-api-key.tsx, and the use-top-token-usage-by-api-key
  hook.
* Strip the now-unreferenced dashboard.tokenUsageByModel /
  apiRequestsByModel / topTokenUsageByApiKey locale keys across 5
  locales, add the new dashboard.usageByModel title; locale parity
  check passes.
This commit is contained in:
Yuxing Deng
2026-05-20 11:29:43 +08:00
committed by jialin
parent 44e5b78d29
commit c38fcc494a
11 changed files with 317 additions and 280 deletions
@@ -1,52 +0,0 @@
import useQueryTimeSeriesData from '@/pages/usage/services/use-query-timeseries-data';
import { useIntl } from '@umijs/max';
import { useEffect, useMemo } from 'react';
import {
baseColorMap,
DashboardUsageCommonParams,
toUsageRankData
} from '../config';
export default function useTopTokenUsageByApiKey(
commonParams: DashboardUsageCommonParams
) {
const intl = useIntl();
const query = useQueryTimeSeriesData({
key: 'topTokenUsageByApiKeyData'
});
const tokenUsageText = intl.formatMessage({ id: 'dashboard.tokens' });
useEffect(() => {
query
.fetchData({
...commonParams,
metric: 'total_tokens',
group_by: ['date', 'api_key'],
page: 1,
perPage: 10,
sort_by: '-total_tokens'
})
.catch(() => {});
}, [commonParams]);
const rankData = useMemo(() => {
const data = toUsageRankData(
query.detailData,
'api_key',
tokenUsageText,
baseColorMap.baseR3
);
return {
names: data.names.filter((name) => name !== '-'),
series: data.series.map((item) => ({
...item,
data: item.data.filter((point) => point.name !== '-')
}))
};
}, [query.detailData, tokenUsageText]);
return {
rankData,
loading: query.loading
};
}