diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 9b340149..d48df20e 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -1406,5 +1406,9 @@ "New API项目仓库地址:": "New API project repository address: ", "NewAPI © {{currentYear}} QuantumNous | 基于 One API v0.5.4 © 2023 JustSong。": "NewAPI © {{currentYear}} QuantumNous | Based on One API v0.5.4 © 2023 JustSong.", "本项目根据MIT许可证授权,需在遵守Apache-2.0协议的前提下使用。": "This project is licensed under the MIT License and must be used in compliance with the Apache-2.0 License.", - "管理员暂时未设置任何关于内容": "The administrator has not set any custom About content yet" + "管理员暂时未设置任何关于内容": "The administrator has not set any custom About content yet", + "早上好": "Good morning", + "中午好": "Good afternoon", + "下午好": "Good afternoon", + "晚上好": "Good evening" } \ No newline at end of file diff --git a/web/src/pages/Detail/index.js b/web/src/pages/Detail/index.js index e999daf7..dd240682 100644 --- a/web/src/pages/Detail/index.js +++ b/web/src/pages/Detail/index.js @@ -2,16 +2,14 @@ import React, { useContext, useEffect, useRef, useState } from 'react'; import { initVChartSemiTheme } from '@visactor/vchart-semi-theme'; import { - Button, Card, - Col, - Descriptions, Form, - Layout, - Row, Spin, - Tabs, + Typography, + IconButton, + Modal, } from '@douyinfe/semi-ui'; +import { IconRefresh, IconSearch } from '@douyinfe/semi-icons'; import { VChart } from '@visactor/react-vchart'; import { API, @@ -25,8 +23,6 @@ import { modelColorMap, renderNumber, renderQuota, - renderQuotaNumberWithDigit, - stringToColor, modelToColor, } from '../../helpers/render'; import { UserContext } from '../../context/User/index.js'; @@ -35,6 +31,7 @@ import { useTranslation } from 'react-i18next'; const Detail = (props) => { const { t } = useTranslation(); + const { Text } = Typography; const formRef = useRef(); let now = new Date(); const [userState, userDispatch] = useContext(UserContext); @@ -67,6 +64,8 @@ const Detail = (props) => { ); const [pieData, setPieData] = useState([{ type: 'null', value: '0' }]); const [lineData, setLineData] = useState([]); + const [searchModalVisible, setSearchModalVisible] = useState(false); + const [spec_pie, setSpecPie] = useState({ type: 'pie', data: [ @@ -200,6 +199,22 @@ const Detail = (props) => { // 添加一个新的状态来存储模型-颜色映射 const [modelColors, setModelColors] = useState({}); + // 显示搜索Modal + const showSearchModal = () => { + setSearchModalVisible(true); + }; + + // 关闭搜索Modal + const handleCloseModal = () => { + setSearchModalVisible(false); + }; + + // 搜索Modal确认按钮 + const handleSearchConfirm = () => { + refresh(); + setSearchModalVisible(false); + }; + const handleInputChange = (value, name) => { if (name === 'data_export_default_time') { setDataExportDefaultTime(value); @@ -416,165 +431,207 @@ const Detail = (props) => { } }, []); + // 数据卡片信息 + const statsData = [ + { + title: t('当前余额'), + value: renderQuota(userState?.user?.quota), + icon: '💰', + color: 'bg-blue-50', + }, + { + title: t('历史消耗'), + value: renderQuota(userState?.user?.used_quota), + icon: '📊', + color: 'bg-purple-50', + }, + { + title: t('请求次数'), + value: userState.user?.request_count, + icon: '🔄', + color: 'bg-green-50', + }, + { + title: t('统计额度'), + value: renderQuota(consumeQuota), + icon: '💲', + color: 'bg-yellow-50', + }, + { + title: t('统计Tokens'), + value: isNaN(consumeTokens) ? 0 : consumeTokens, + icon: '🔤', + color: 'bg-pink-50', + }, + { + title: t('统计次数'), + value: times, + icon: '📈', + color: 'bg-teal-50', + }, + { + title: t('平均RPM'), + value: ( + times / + ((Date.parse(end_timestamp) - Date.parse(start_timestamp)) / 60000) + ).toFixed(3), + icon: '⏱️', + color: 'bg-indigo-50', + }, + { + title: t('平均TPM'), + value: (() => { + const tpm = consumeTokens / + ((Date.parse(end_timestamp) - Date.parse(start_timestamp)) / 60000); + return isNaN(tpm) ? '0' : tpm.toFixed(3); + })(), + icon: '📝', + color: 'bg-orange-50', + }, + ]; + + // 获取问候语 + const getGreeting = () => { + const hours = new Date().getHours(); + let greeting = ''; + + if (hours >= 5 && hours < 12) { + greeting = t('早上好'); + } else if (hours >= 12 && hours < 14) { + greeting = t('中午好'); + } else if (hours >= 14 && hours < 18) { + greeting = t('下午好'); + } else { + greeting = t('晚上好'); + } + + const username = userState?.user?.username || ''; + return `👋${greeting},${username}`; + }; + return ( - <> - - -

{t('数据看板')}

-
- -
- <> - - handleInputChange(value, 'start_timestamp') - } - /> - handleInputChange(value, 'end_timestamp')} - /> - - handleInputChange(value, 'data_export_default_time') - } - > - {isAdminUser && ( - <> - handleInputChange(value, 'username')} - /> - - )} - - - - - - - - - - - {renderQuota(userState?.user?.quota)} - - - {renderQuota(userState?.user?.used_quota)} - - - {userState.user?.request_count} - - - - - - - - - {renderQuota(consumeQuota)} - - - {consumeTokens} - - - {times} - - - - - - - - - {( - times / - ((Date.parse(end_timestamp) - - Date.parse(start_timestamp)) / - 60000) - ).toFixed(3)} - - - {( - consumeTokens / - ((Date.parse(end_timestamp) - - Date.parse(start_timestamp)) / - 60000) - ).toFixed(3)} - - - - - - - - -
- +
+
{stat.icon}
+
+
{stat.title}
+
{stat.value}
- - -
- -
-
- - - - - - +
+ + ))} +
+ + +
+ +
+ +
+
+ + +
+ +
+
+
+
+ ); };