one-api/web/src/views/Dashboard/index.js
2024-02-01 18:45:53 +08:00

230 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from 'react';
import { Grid, Typography } from '@mui/material';
import { gridSpacing } from 'store/constant';
import StatisticalLineChartCard from './component/StatisticalLineChartCard';
import ApexCharts from 'ui-component/chart/ApexCharts';
import SupportModels from './component/SupportModels';
import { generateLineChartOptions, getLastSevenDays, generateBarChartOptions, renderChartNumber } from 'utils/chart';
import { API } from 'utils/api';
import { showError, calculateQuota, renderNumber } from 'utils/common';
import UserCard from 'ui-component/cards/UserCard';
const Dashboard = () => {
const [isLoading, setLoading] = useState(true);
const [statisticalData, setStatisticalData] = useState([]);
const [requestChart, setRequestChart] = useState(null);
const [quotaChart, setQuotaChart] = useState(null);
const [tokenChart, setTokenChart] = useState(null);
const [users, setUsers] = useState([]);
const userDashboard = async () => {
try {
const res = await API.get('/api/user/dashboard');
const { success, message, data } = res.data;
if (success) {
if (data) {
let lineData = getLineDataGroup(data);
setRequestChart(getLineCardOption(lineData, 'RequestCount'));
setQuotaChart(getLineCardOption(lineData, 'Quota'));
setTokenChart(getLineCardOption(lineData, 'PromptTokens'));
setStatisticalData(getBarDataGroup(data));
}
} else {
showError(message);
}
setLoading(false);
} catch (error) {
return;
}
};
const loadUser = async () => {
try {
let res = await API.get(`/api/user/self`);
const { success, message, data } = res.data;
if (success) {
setUsers(data);
} else {
showError(message);
}
} catch (error) {
return;
}
};
useEffect(() => {
userDashboard();
loadUser();
}, []);
return (
<Grid container spacing={gridSpacing}>
<Grid item xs={12}>
<SupportModels />
</Grid>
<Grid item xs={12}>
<Grid container spacing={gridSpacing}>
<Grid item lg={4} xs={12}>
<StatisticalLineChartCard
isLoading={isLoading}
title="今日请求量"
chartData={requestChart?.chartData}
todayValue={requestChart?.todayValue}
/>
</Grid>
<Grid item lg={4} xs={12}>
<StatisticalLineChartCard
isLoading={isLoading}
title="今日消费"
chartData={quotaChart?.chartData}
todayValue={quotaChart?.todayValue}
/>
</Grid>
<Grid item lg={4} xs={12}>
<StatisticalLineChartCard
isLoading={isLoading}
title="今日Token"
chartData={tokenChart?.chartData}
todayValue={tokenChart?.todayValue}
/>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<Grid container spacing={gridSpacing}>
<Grid item lg={8} xs={12}>
<ApexCharts isLoading={isLoading} chartDatas={statisticalData} />
</Grid>
<Grid item lg={4} xs={12}>
<UserCard>
<Grid container spacing={gridSpacing} justifyContent="center" alignItems="center" paddingTop={'20px'}>
<Grid item xs={4}>
<Typography variant="h4"> :</Typography>
</Grid>
<Grid item xs={8}>
<Typography variant="h3"> {users?.quota ? '$' + calculateQuota(users.quota) : '未知'}</Typography>
</Grid>
<Grid item xs={4}>
<Typography variant="h4">已使用:</Typography>
</Grid>
<Grid item xs={8}>
<Typography variant="h3"> {users?.used_quota ? '$' + calculateQuota(users.used_quota) : '未知'}</Typography>
</Grid>
<Grid item xs={4}>
<Typography variant="h4">调用次数:</Typography>
</Grid>
<Grid item xs={8}>
<Typography variant="h3"> {users?.request_count || '未知'}</Typography>
</Grid>
</Grid>
</UserCard>
</Grid>
</Grid>
</Grid>
</Grid>
);
};
export default Dashboard;
function getLineDataGroup(statisticalData) {
let groupedData = statisticalData.reduce((acc, cur) => {
if (!acc[cur.Date]) {
acc[cur.Date] = {
date: cur.Date,
RequestCount: 0,
Quota: 0,
PromptTokens: 0,
CompletionTokens: 0
};
}
acc[cur.Date].RequestCount += cur.RequestCount;
acc[cur.Date].Quota += cur.Quota;
acc[cur.Date].PromptTokens += cur.PromptTokens;
acc[cur.Date].CompletionTokens += cur.CompletionTokens;
return acc;
}, {});
let lastSevenDays = getLastSevenDays();
return lastSevenDays.map((Date) => {
if (!groupedData[Date]) {
return {
date: Date,
RequestCount: 0,
Quota: 0,
PromptTokens: 0,
CompletionTokens: 0
};
} else {
return groupedData[Date];
}
});
}
function getBarDataGroup(data) {
const lastSevenDays = getLastSevenDays();
const result = [];
const map = new Map();
let totalCosts = 0;
for (const item of data) {
if (!map.has(item.ModelName)) {
const newData = { name: item.ModelName, data: new Array(7).fill(0) };
map.set(item.ModelName, newData);
result.push(newData);
}
const index = lastSevenDays.indexOf(item.Date);
if (index !== -1) {
let costs = Number(calculateQuota(item.Quota, 3));
map.get(item.ModelName).data[index] = costs;
totalCosts += parseFloat(costs.toFixed(3));
}
}
let chartData = generateBarChartOptions(lastSevenDays, result, '美元', 3);
chartData.options.title.text = '7日总消费$' + renderChartNumber(totalCosts, 3);
return chartData;
}
function getLineCardOption(lineDataGroup, field) {
let todayValue = 0;
let chartData = null;
const lastItem = lineDataGroup.length - 1;
let lineData = lineDataGroup.map((item, index) => {
let tmp = {
date: item.date,
value: item[field]
};
switch (field) {
case 'Quota':
tmp.value = calculateQuota(item.Quota, 3);
break;
case 'PromptTokens':
tmp.value += item.CompletionTokens;
break;
}
if (index == lastItem) {
todayValue = tmp.value;
}
return tmp;
});
switch (field) {
case 'RequestCount':
chartData = generateLineChartOptions(lineData, '次');
todayValue = renderNumber(todayValue);
break;
case 'Quota':
chartData = generateLineChartOptions(lineData, '美元');
todayValue = '$' + renderNumber(todayValue);
break;
case 'PromptTokens':
chartData = generateLineChartOptions(lineData, '');
todayValue = renderNumber(todayValue);
break;
}
return { chartData: chartData, todayValue: todayValue };
}