mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-19 03:00:49 +08:00
fix(usage): update chart labels when locale changes
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
|||||||
buildHourlyCostSeries,
|
buildHourlyCostSeries,
|
||||||
buildDailyCostSeries,
|
buildDailyCostSeries,
|
||||||
formatUsd,
|
formatUsd,
|
||||||
type ModelPrice,
|
type ModelPrice
|
||||||
} from '@/utils/usage';
|
} from '@/utils/usage';
|
||||||
import { buildChartOptions, getHourChartMinWidth } from '@/utils/usage/chartConfig';
|
import { buildChartOptions, getHourChartMinWidth } from '@/utils/usage/chartConfig';
|
||||||
import type { UsagePayload } from './hooks/useUsageData';
|
import type { UsagePayload } from './hooks/useUsageData';
|
||||||
@@ -43,7 +43,7 @@ export function CostTrendChart({
|
|||||||
isDark,
|
isDark,
|
||||||
isMobile,
|
isMobile,
|
||||||
modelPrices,
|
modelPrices,
|
||||||
hourWindowHours,
|
hourWindowHours
|
||||||
}: CostTrendChartProps) {
|
}: CostTrendChartProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [period, setPeriod] = useState<'hour' | 'day'>('hour');
|
const [period, setPeriod] = useState<'hour' | 'day'>('hour');
|
||||||
@@ -70,9 +70,9 @@ export function CostTrendChart({
|
|||||||
pointBackgroundColor: COST_COLOR,
|
pointBackgroundColor: COST_COLOR,
|
||||||
pointBorderColor: COST_COLOR,
|
pointBorderColor: COST_COLOR,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.35,
|
tension: 0.35
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseOptions = buildChartOptions({ period, labels: series.labels, isDark, isMobile });
|
const baseOptions = buildChartOptions({ period, labels: series.labels, isDark, isMobile });
|
||||||
@@ -84,15 +84,14 @@ export function CostTrendChart({
|
|||||||
...baseOptions.scales?.y,
|
...baseOptions.scales?.y,
|
||||||
ticks: {
|
ticks: {
|
||||||
...(baseOptions.scales?.y && 'ticks' in baseOptions.scales.y ? baseOptions.scales.y.ticks : {}),
|
...(baseOptions.scales?.y && 'ticks' in baseOptions.scales.y ? baseOptions.scales.y.ticks : {}),
|
||||||
callback: (value: string | number) => formatUsd(Number(value)),
|
callback: (value: string | number) => formatUsd(Number(value))
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return { chartData: data, chartOptions: options, hasData: series.hasData };
|
return { chartData: data, chartOptions: options, hasData: series.hasData };
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}, [usage, period, isDark, isMobile, modelPrices, hasPrices, hourWindowHours, t]);
|
||||||
}, [usage, period, isDark, isMobile, modelPrices, hasPrices, hourWindowHours]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
|||||||
@@ -6,17 +6,17 @@ import { Button } from '@/components/ui/Button';
|
|||||||
import {
|
import {
|
||||||
buildHourlyTokenBreakdown,
|
buildHourlyTokenBreakdown,
|
||||||
buildDailyTokenBreakdown,
|
buildDailyTokenBreakdown,
|
||||||
type TokenCategory,
|
type TokenCategory
|
||||||
} from '@/utils/usage';
|
} from '@/utils/usage';
|
||||||
import { buildChartOptions, getHourChartMinWidth } from '@/utils/usage/chartConfig';
|
import { buildChartOptions, getHourChartMinWidth } from '@/utils/usage/chartConfig';
|
||||||
import type { UsagePayload } from './hooks/useUsageData';
|
import type { UsagePayload } from './hooks/useUsageData';
|
||||||
import styles from '@/pages/UsagePage.module.scss';
|
import styles from '@/pages/UsagePage.module.scss';
|
||||||
|
|
||||||
const TOKEN_COLORS: Record<TokenCategory, { border: string; bg: string }> = {
|
const TOKEN_COLORS: Record<TokenCategory, { border: string; bg: string }> = {
|
||||||
input: { border: '#3b82f6', bg: 'rgba(59, 130, 246, 0.25)' },
|
input: { border: '#3b82f6', bg: 'rgba(59, 130, 246, 0.25)' },
|
||||||
output: { border: '#22c55e', bg: 'rgba(34, 197, 94, 0.25)' },
|
output: { border: '#22c55e', bg: 'rgba(34, 197, 94, 0.25)' },
|
||||||
cached: { border: '#f59e0b', bg: 'rgba(245, 158, 11, 0.25)' },
|
cached: { border: '#f59e0b', bg: 'rgba(245, 158, 11, 0.25)' },
|
||||||
reasoning: { border: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.25)' },
|
reasoning: { border: '#8b5cf6', bg: 'rgba(139, 92, 246, 0.25)' }
|
||||||
};
|
};
|
||||||
|
|
||||||
const CATEGORIES: TokenCategory[] = ['input', 'output', 'cached', 'reasoning'];
|
const CATEGORIES: TokenCategory[] = ['input', 'output', 'cached', 'reasoning'];
|
||||||
@@ -34,56 +34,55 @@ export function TokenBreakdownChart({
|
|||||||
loading,
|
loading,
|
||||||
isDark,
|
isDark,
|
||||||
isMobile,
|
isMobile,
|
||||||
hourWindowHours,
|
hourWindowHours
|
||||||
}: TokenBreakdownChartProps) {
|
}: TokenBreakdownChartProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [period, setPeriod] = useState<'hour' | 'day'>('hour');
|
const [period, setPeriod] = useState<'hour' | 'day'>('hour');
|
||||||
|
|
||||||
const CATEGORY_LABELS: Record<TokenCategory, string> = {
|
|
||||||
input: t('usage_stats.input_tokens'),
|
|
||||||
output: t('usage_stats.output_tokens'),
|
|
||||||
cached: t('usage_stats.cached_tokens'),
|
|
||||||
reasoning: t('usage_stats.reasoning_tokens'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const { chartData, chartOptions } = useMemo(() => {
|
const { chartData, chartOptions } = useMemo(() => {
|
||||||
const series =
|
const series =
|
||||||
period === 'hour'
|
period === 'hour'
|
||||||
? buildHourlyTokenBreakdown(usage, hourWindowHours)
|
? buildHourlyTokenBreakdown(usage, hourWindowHours)
|
||||||
: buildDailyTokenBreakdown(usage);
|
: buildDailyTokenBreakdown(usage);
|
||||||
|
const categoryLabels: Record<TokenCategory, string> = {
|
||||||
|
input: t('usage_stats.input_tokens'),
|
||||||
|
output: t('usage_stats.output_tokens'),
|
||||||
|
cached: t('usage_stats.cached_tokens'),
|
||||||
|
reasoning: t('usage_stats.reasoning_tokens')
|
||||||
|
};
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
labels: series.labels,
|
labels: series.labels,
|
||||||
datasets: CATEGORIES.map((cat) => ({
|
datasets: CATEGORIES.map((cat) => ({
|
||||||
label: CATEGORY_LABELS[cat],
|
label: categoryLabels[cat],
|
||||||
data: series.dataByCategory[cat],
|
data: series.dataByCategory[cat],
|
||||||
borderColor: TOKEN_COLORS[cat].border,
|
borderColor: TOKEN_COLORS[cat].border,
|
||||||
backgroundColor: TOKEN_COLORS[cat].bg,
|
backgroundColor: TOKEN_COLORS[cat].bg,
|
||||||
pointBackgroundColor: TOKEN_COLORS[cat].border,
|
pointBackgroundColor: TOKEN_COLORS[cat].border,
|
||||||
pointBorderColor: TOKEN_COLORS[cat].border,
|
pointBorderColor: TOKEN_COLORS[cat].border,
|
||||||
fill: true,
|
fill: true,
|
||||||
tension: 0.35,
|
tension: 0.35
|
||||||
})),
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const baseOptions = buildChartOptions({ period, labels: series.labels, isDark, isMobile });
|
||||||
const options = {
|
const options = {
|
||||||
...buildChartOptions({ period, labels: series.labels, isDark, isMobile }),
|
...baseOptions,
|
||||||
scales: {
|
scales: {
|
||||||
...buildChartOptions({ period, labels: series.labels, isDark, isMobile }).scales,
|
...baseOptions.scales,
|
||||||
y: {
|
y: {
|
||||||
...buildChartOptions({ period, labels: series.labels, isDark, isMobile }).scales?.y,
|
...baseOptions.scales?.y,
|
||||||
stacked: true,
|
stacked: true
|
||||||
},
|
},
|
||||||
x: {
|
x: {
|
||||||
...buildChartOptions({ period, labels: series.labels, isDark, isMobile }).scales?.x,
|
...baseOptions.scales?.x,
|
||||||
stacked: true,
|
stacked: true
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return { chartData: data, chartOptions: options, hasData: series.hasData };
|
return { chartData: data, chartOptions: options };
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
}, [usage, period, isDark, isMobile, hourWindowHours, t]);
|
||||||
}, [usage, period, isDark, isMobile, hourWindowHours]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
|
|||||||
Reference in New Issue
Block a user