|
@@ -34,8 +34,14 @@ import {
|
|
|
updateChartSpec,
|
|
updateChartSpec,
|
|
|
updateMapValue,
|
|
updateMapValue,
|
|
|
initializeMaps,
|
|
initializeMaps,
|
|
|
|
|
+ processUserData,
|
|
|
} from '../../helpers/dashboard';
|
|
} from '../../helpers/dashboard';
|
|
|
|
|
|
|
|
|
|
+const USER_COLORS = [
|
|
|
|
|
+ '#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6',
|
|
|
|
|
+ '#ec4899', '#06b6d4', '#f97316', '#6366f1', '#14b8a6',
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
export const useDashboardCharts = (
|
|
export const useDashboardCharts = (
|
|
|
dataExportDefaultTime,
|
|
dataExportDefaultTime,
|
|
|
setTrendData,
|
|
setTrendData,
|
|
@@ -179,7 +185,6 @@ export const useDashboardCharts = (
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // 模型消耗趋势折线图
|
|
|
|
|
const [spec_model_line, setSpecModelLine] = useState({
|
|
const [spec_model_line, setSpecModelLine] = useState({
|
|
|
type: 'line',
|
|
type: 'line',
|
|
|
data: [
|
|
data: [
|
|
@@ -197,7 +202,7 @@ export const useDashboardCharts = (
|
|
|
},
|
|
},
|
|
|
title: {
|
|
title: {
|
|
|
visible: true,
|
|
visible: true,
|
|
|
- text: t('模型消耗趋势'),
|
|
|
|
|
|
|
+ text: t('调用趋势'),
|
|
|
subtext: '',
|
|
subtext: '',
|
|
|
},
|
|
},
|
|
|
tooltip: {
|
|
tooltip: {
|
|
@@ -215,7 +220,6 @@ export const useDashboardCharts = (
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // 模型调用次数排行柱状图
|
|
|
|
|
const [spec_rank_bar, setSpecRankBar] = useState({
|
|
const [spec_rank_bar, setSpecRankBar] = useState({
|
|
|
type: 'bar',
|
|
type: 'bar',
|
|
|
data: [
|
|
data: [
|
|
@@ -259,6 +263,76 @@ export const useDashboardCharts = (
|
|
|
},
|
|
},
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ // ========== Admin: 用户消耗排行 ==========
|
|
|
|
|
+ const [spec_user_rank, setSpecUserRank] = useState({
|
|
|
|
|
+ type: 'bar',
|
|
|
|
|
+ data: [{ id: 'userRankData', values: [] }],
|
|
|
|
|
+ xField: 'rawQuota',
|
|
|
|
|
+ yField: 'User',
|
|
|
|
|
+ seriesField: 'User',
|
|
|
|
|
+ direction: 'horizontal',
|
|
|
|
|
+ legends: { visible: false },
|
|
|
|
|
+ title: {
|
|
|
|
|
+ visible: true,
|
|
|
|
|
+ text: t('用户消耗排行'),
|
|
|
|
|
+ subtext: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ bar: {
|
|
|
|
|
+ state: { hover: { stroke: '#000', lineWidth: 1 } },
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ visible: true,
|
|
|
|
|
+ position: 'outside',
|
|
|
|
|
+ formatMethod: (value, datum) => renderQuota(datum['rawQuota'] || 0, 2),
|
|
|
|
|
+ },
|
|
|
|
|
+ axes: [{
|
|
|
|
|
+ orient: 'left',
|
|
|
|
|
+ type: 'band',
|
|
|
|
|
+ label: { visible: true },
|
|
|
|
|
+ }, {
|
|
|
|
|
+ orient: 'bottom',
|
|
|
|
|
+ type: 'linear',
|
|
|
|
|
+ visible: false,
|
|
|
|
|
+ }],
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ mark: {
|
|
|
|
|
+ content: [{
|
|
|
|
|
+ key: (datum) => datum['User'],
|
|
|
|
|
+ value: (datum) => renderQuota(datum['rawQuota'] || 0, 4),
|
|
|
|
|
+ }],
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ color: { type: 'ordinal', range: USER_COLORS },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ========== Admin: 用户消耗趋势 ==========
|
|
|
|
|
+ const [spec_user_trend, setSpecUserTrend] = useState({
|
|
|
|
|
+ type: 'area',
|
|
|
|
|
+ data: [{ id: 'userTrendData', values: [] }],
|
|
|
|
|
+ xField: 'Time',
|
|
|
|
|
+ yField: 'rawQuota',
|
|
|
|
|
+ seriesField: 'User',
|
|
|
|
|
+ stack: false,
|
|
|
|
|
+ legends: { visible: true, selectMode: 'single' },
|
|
|
|
|
+ title: {
|
|
|
|
|
+ visible: true,
|
|
|
|
|
+ text: t('用户消耗趋势'),
|
|
|
|
|
+ subtext: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ area: { style: { fillOpacity: 0.15 } },
|
|
|
|
|
+ line: { style: { lineWidth: 2 } },
|
|
|
|
|
+ point: { visible: false },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ mark: {
|
|
|
|
|
+ content: [{
|
|
|
|
|
+ key: (datum) => datum['User'],
|
|
|
|
|
+ value: (datum) => renderQuota(datum['rawQuota'] || 0, 4),
|
|
|
|
|
+ }],
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ color: { type: 'ordinal', range: USER_COLORS },
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
// ========== 数据处理函数 ==========
|
|
// ========== 数据处理函数 ==========
|
|
|
const generateModelColors = useCallback((uniqueModels, modelColors) => {
|
|
const generateModelColors = useCallback((uniqueModels, modelColors) => {
|
|
|
const newModelColors = {};
|
|
const newModelColors = {};
|
|
@@ -426,6 +500,51 @@ export const useDashboardCharts = (
|
|
|
],
|
|
],
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
|
|
+ // ========== 用户维度图表数据处理 ==========
|
|
|
|
|
+ const updateUserChartData = useCallback(
|
|
|
|
|
+ (data) => {
|
|
|
|
|
+ const { rankingData, trendData: userTrend } = processUserData(
|
|
|
|
|
+ data,
|
|
|
|
|
+ dataExportDefaultTime,
|
|
|
|
|
+ 10,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ const userRankValues = rankingData.map((item) => ({
|
|
|
|
|
+ User: item.User,
|
|
|
|
|
+ rawQuota: item.Quota,
|
|
|
|
|
+ Quota: getQuotaWithUnit(item.Quota, 4),
|
|
|
|
|
+ })).sort((a, b) => a.rawQuota - b.rawQuota);
|
|
|
|
|
+
|
|
|
|
|
+ const totalUserQuota = rankingData.reduce((s, i) => s + i.Quota, 0);
|
|
|
|
|
+
|
|
|
|
|
+ setSpecUserRank((prev) => ({
|
|
|
|
|
+ ...prev,
|
|
|
|
|
+ data: [{ id: 'userRankData', values: userRankValues }],
|
|
|
|
|
+ title: {
|
|
|
|
|
+ ...prev.title,
|
|
|
|
|
+ subtext: `${t('总计')}:${renderQuota(totalUserQuota, 2)}`,
|
|
|
|
|
+ },
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ const userTrendValues = userTrend.map((item) => ({
|
|
|
|
|
+ Time: item.Time,
|
|
|
|
|
+ User: item.User,
|
|
|
|
|
+ rawQuota: item.Quota,
|
|
|
|
|
+ Usage: item.Quota ? getQuotaWithUnit(item.Quota, 4) : 0,
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ setSpecUserTrend((prev) => ({
|
|
|
|
|
+ ...prev,
|
|
|
|
|
+ data: [{ id: 'userTrendData', values: userTrendValues }],
|
|
|
|
|
+ title: {
|
|
|
|
|
+ ...prev.title,
|
|
|
|
|
+ subtext: `${t('总计')}:${renderQuota(totalUserQuota, 2)}`,
|
|
|
|
|
+ },
|
|
|
|
|
+ }));
|
|
|
|
|
+ },
|
|
|
|
|
+ [dataExportDefaultTime, t],
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
// ========== 初始化图表主题 ==========
|
|
// ========== 初始化图表主题 ==========
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
|
initVChartSemiTheme({
|
|
initVChartSemiTheme({
|
|
@@ -434,14 +553,14 @@ export const useDashboardCharts = (
|
|
|
}, []);
|
|
}, []);
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
- // 图表规格
|
|
|
|
|
spec_pie,
|
|
spec_pie,
|
|
|
spec_line,
|
|
spec_line,
|
|
|
spec_model_line,
|
|
spec_model_line,
|
|
|
spec_rank_bar,
|
|
spec_rank_bar,
|
|
|
-
|
|
|
|
|
- // 函数
|
|
|
|
|
|
|
+ spec_user_rank,
|
|
|
|
|
+ spec_user_trend,
|
|
|
updateChartData,
|
|
updateChartData,
|
|
|
|
|
+ updateUserChartData,
|
|
|
generateModelColors,
|
|
generateModelColors,
|
|
|
};
|
|
};
|
|
|
};
|
|
};
|