mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-04 10:13:53 +08:00
Merge remote-tracking branch 'origin/feature/1.8-cx' into feature/liujian-1.8
This commit is contained in:
@@ -9,6 +9,7 @@ type AreaChartInfo = {
|
||||
data: number[]
|
||||
max: string
|
||||
min: string
|
||||
originValue?: number
|
||||
showXAxis?: boolean
|
||||
}
|
||||
|
||||
@@ -17,9 +18,10 @@ type ServiceAreaCharProps = {
|
||||
dataInfo?: AreaChartInfo
|
||||
height?: number
|
||||
showAvgLine?: boolean
|
||||
customMarkLineValue?: number
|
||||
}
|
||||
|
||||
const ServiceAreaChart = ({ customClassNames, dataInfo, height, showAvgLine }: ServiceAreaCharProps) => {
|
||||
const ServiceAreaChart = ({ customClassNames, dataInfo, height, showAvgLine, customMarkLineValue }: ServiceAreaCharProps) => {
|
||||
const chartRef = useRef<ECharts>(null)
|
||||
const [option, setOption] = useState<EChartsOption | undefined>({})
|
||||
const [hasData, setHasData] = useState(true)
|
||||
@@ -186,7 +188,9 @@ const ServiceAreaChart = ({ customClassNames, dataInfo, height, showAvgLine }: S
|
||||
show: false // 悬停时不显示标签
|
||||
}
|
||||
},
|
||||
data: [{ type: 'average', name: 'Avg' }]
|
||||
data: dataInfo?.originValue !== undefined ?
|
||||
[{ yAxis: dataInfo?.originValue, name: '自定义值' }] :
|
||||
[{ type: 'average', name: 'Avg' }]
|
||||
} : undefined,
|
||||
areaStyle: {
|
||||
color: {
|
||||
|
||||
@@ -21,6 +21,8 @@ export type BarChartInfo = {
|
||||
traffic2xxTotal?: string
|
||||
traffic4xxTotal?: string
|
||||
traffic5xxTotal?: string
|
||||
max?: string | number
|
||||
min?: string | number
|
||||
}
|
||||
|
||||
type ServiceBarCharProps = {
|
||||
@@ -29,9 +31,17 @@ type ServiceBarCharProps = {
|
||||
height?: number
|
||||
showAvgLine?: boolean
|
||||
showLegendIndicator?: boolean
|
||||
hideIndicatorValue?: boolean
|
||||
}
|
||||
|
||||
const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showLegendIndicator }: ServiceBarCharProps) => {
|
||||
const ServiceBarChar = ({
|
||||
customClassNames,
|
||||
dataInfo,
|
||||
height,
|
||||
showAvgLine,
|
||||
showLegendIndicator,
|
||||
hideIndicatorValue
|
||||
}: ServiceBarCharProps) => {
|
||||
const chartRef = useRef<ECharts>(null)
|
||||
const [option, setOption] = useState<EChartsOption | undefined>({})
|
||||
// 使用从主题配置中导入的默认颜色,而不是硬编码的颜色值
|
||||
@@ -78,7 +88,10 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showL
|
||||
const option: EChartsOption = {
|
||||
title: [
|
||||
{
|
||||
text: '{titleStyle|' + $t(dataInfo.title) + '}\n\n{valueStyle|' + dataInfo.value + '}',
|
||||
text:
|
||||
'{titleStyle|' +
|
||||
$t(dataInfo.title) +
|
||||
`}${hideIndicatorValue ? '' : '\n\n{valueStyle|' + dataInfo.value + '}'}`,
|
||||
left: '2%',
|
||||
top: '0',
|
||||
textStyle: {
|
||||
@@ -125,23 +138,23 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showL
|
||||
show: !isNumberArray,
|
||||
data: legendData,
|
||||
right: '10px',
|
||||
top: '60px',
|
||||
top: hideIndicatorValue ? '10px' : '60px',
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
textStyle: {
|
||||
color: '#333'
|
||||
},
|
||||
icon: 'rect',
|
||||
formatter: function(name: string): string {
|
||||
formatter: function (name: string): string {
|
||||
// 这里可以映射或自定义图例文本
|
||||
const customNames: Record<string, string> = {
|
||||
'inputToken': `${$t('输入 Token')} ${showLegendIndicator ? `(${dataInfo.inputTokenTotal})` : ''}`,
|
||||
'outputToken': `${$t('输出 Token')} ${showLegendIndicator ? `(${dataInfo.outputTokenTotal})` : ''}`,
|
||||
inputToken: `${$t('输入 Token')} ${showLegendIndicator ? `(${dataInfo.inputTokenTotal})` : ''}`,
|
||||
outputToken: `${$t('输出 Token')} ${showLegendIndicator ? `(${dataInfo.outputTokenTotal})` : ''}`,
|
||||
'2xx': `${'2xx'} ${showLegendIndicator ? `(${dataInfo.request2xxTotal || dataInfo.traffic2xxTotal})` : ''}`,
|
||||
'4xx': `${'4xx'} ${showLegendIndicator ? `(${dataInfo.request4xxTotal || dataInfo.traffic4xxTotal})` : ''}`,
|
||||
'5xx': `${'5xx'} ${showLegendIndicator ? `(${dataInfo.request5xxTotal || dataInfo.traffic5xxTotal})` : ''}`
|
||||
};
|
||||
return customNames[name] || name;
|
||||
}
|
||||
return customNames[name] || name
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
@@ -161,7 +174,7 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showL
|
||||
type: 'value',
|
||||
name: '',
|
||||
min: 0,
|
||||
minInterval: 1,
|
||||
...(showAvgLine ? {} : { minInterval: 1 }),
|
||||
show: dataExists, // 没有数据时不显示Y轴
|
||||
splitLine: {
|
||||
show: dataExists, // 没有数据时不显示网格线
|
||||
@@ -252,10 +265,10 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showL
|
||||
},
|
||||
emphasis: {
|
||||
lineStyle: {
|
||||
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
|
||||
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
|
||||
},
|
||||
label: {
|
||||
show: false // 悬停时不显示标签
|
||||
show: false // 悬停时不显示标签
|
||||
}
|
||||
},
|
||||
data: [{ type: 'average', name: 'Avg' }]
|
||||
@@ -289,10 +302,10 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showL
|
||||
},
|
||||
emphasis: {
|
||||
lineStyle: {
|
||||
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
|
||||
width: 1 // 保持线条宽度不变,禁用默认的悬停加粗
|
||||
},
|
||||
label: {
|
||||
show: false // 悬停时不显示标签
|
||||
show: false // 悬停时不显示标签
|
||||
}
|
||||
},
|
||||
data: [{ type: 'average', name: 'Avg' }]
|
||||
@@ -348,6 +361,24 @@ const ServiceBarChar = ({ customClassNames, dataInfo, height, showAvgLine, showL
|
||||
}, [])
|
||||
return (
|
||||
<div className={`w-full ${customClassNames}`}>
|
||||
{
|
||||
hideIndicatorValue && (
|
||||
<div className="absolute top-[26px] left-[10px] w-full">
|
||||
<div className="relative top-[5px]">
|
||||
<div className="absolute top-[23px] right-[5%] grid grid-cols-[auto_auto] justify-items-end">
|
||||
<div className="flex justify-center items-center">
|
||||
<span className="text-[#FE564D] text-[9px]">▲</span>
|
||||
</div>
|
||||
<span className="ml-1 text-right">{dataInfo?.max}</span>
|
||||
<div className="flex justify-center items-center">
|
||||
<span className="text-[#27B148] text-[9px]">▼</span>
|
||||
</div>
|
||||
<span className="ml-1 text-right">{dataInfo?.min}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div style={!hasData ? { cursor: 'default', pointerEvents: 'none' } : {}}>
|
||||
<ECharts
|
||||
ref={chartRef}
|
||||
|
||||
@@ -12,7 +12,7 @@ import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const'
|
||||
import { App } from 'antd'
|
||||
import ServiceAreaChart from './charts/ServiceAreaChart'
|
||||
import RankingList from './rankingList/RankingList'
|
||||
import { getTime } from '@dashboard/utils/dashboard'
|
||||
import { abbreviateFloat, formatBytes, formatDuration, formatNumberWithUnit, getTime } from '@dashboard/utils/dashboard'
|
||||
import { setBarChartInfoData } from './utils'
|
||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext'
|
||||
|
||||
@@ -78,7 +78,11 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
'request_4xx_total',
|
||||
'request_5xx_total',
|
||||
'input_token_total',
|
||||
'output_token_total'
|
||||
'output_token_total',
|
||||
'max_token_per_subscriber',
|
||||
'min_token_per_subscriber',
|
||||
'max_request_per_subscriber',
|
||||
'min_request_per_subscriber'
|
||||
]
|
||||
}).then((response) => {
|
||||
const { code, data, msg } = response
|
||||
@@ -114,24 +118,24 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
...setBarChartInfoData({
|
||||
title: $t('请求次数'),
|
||||
data: serviceOverview.requestOverview,
|
||||
value: serviceOverview.requestTotal,
|
||||
value: formatNumberWithUnit(serviceOverview.requestTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
request2xxTotal: serviceOverview.request2xxTotal,
|
||||
request4xxTotal: serviceOverview.request4xxTotal,
|
||||
request5xxTotal: serviceOverview.request5xxTotal
|
||||
request2xxTotal: formatNumberWithUnit(serviceOverview.request2xxTotal),
|
||||
request4xxTotal: formatNumberWithUnit(serviceOverview.request4xxTotal),
|
||||
request5xxTotal: formatNumberWithUnit(serviceOverview.request5xxTotal)
|
||||
},
|
||||
// 流量消耗总数
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('网络流量'),
|
||||
data: serviceOverview.trafficOverview,
|
||||
value: serviceOverview.trafficTotal,
|
||||
value: formatBytes(serviceOverview.trafficTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
traffic2xxTotal: serviceOverview.traffic2xxTotal,
|
||||
traffic4xxTotal: serviceOverview.traffic4xxTotal,
|
||||
traffic5xxTotal: serviceOverview.traffic5xxTotal
|
||||
traffic2xxTotal: formatBytes(serviceOverview.traffic2xxTotal),
|
||||
traffic4xxTotal: formatBytes(serviceOverview.traffic4xxTotal),
|
||||
traffic5xxTotal: formatBytes(serviceOverview.traffic5xxTotal)
|
||||
}
|
||||
])
|
||||
// 设置平均值数据
|
||||
@@ -140,29 +144,36 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
{
|
||||
title: $t('平均响应时间'),
|
||||
data: serviceOverview.avgResponseTimeOverview,
|
||||
value: serviceOverview.avgResponseTime,
|
||||
value: formatDuration(serviceOverview.avgResponseTime),
|
||||
originValue: serviceOverview.avgResponseTime,
|
||||
date: serviceOverview.date,
|
||||
max: serviceOverview.maxResponseTime,
|
||||
min: serviceOverview.minResponseTime,
|
||||
max: formatDuration(serviceOverview.maxResponseTime),
|
||||
min: formatDuration(serviceOverview.minResponseTime),
|
||||
type: 'area',
|
||||
showXAxis: false
|
||||
},
|
||||
// 平均请求
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
value: serviceOverview.avgRequestPerSubscriber,
|
||||
date: serviceOverview.date,
|
||||
showXAxis: false
|
||||
}),
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
date: serviceOverview.date,
|
||||
showXAxis: false
|
||||
}),
|
||||
max: abbreviateFloat(serviceOverview.maxRequestPerSubscriber),
|
||||
min: abbreviateFloat(serviceOverview.minRequestPerSubscriber)
|
||||
},
|
||||
// 平均流量消耗
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的网络流量'),
|
||||
data: serviceOverview.avgTrafficPerSubscriberOverview,
|
||||
value: serviceOverview.avgTrafficPerSubscriber,
|
||||
date: serviceOverview.date,
|
||||
showXAxis: false
|
||||
})
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的网络流量'),
|
||||
data: serviceOverview.avgTrafficPerSubscriberOverview,
|
||||
date: serviceOverview.date,
|
||||
showXAxis: false
|
||||
}),
|
||||
max: formatBytes(serviceOverview.maxTrafficPerSubscriber),
|
||||
min: formatBytes(serviceOverview.minTrafficPerSubscriber)
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
@@ -186,12 +197,12 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
...setBarChartInfoData({
|
||||
title: $t('请求次数'),
|
||||
data: serviceOverview.requestOverview,
|
||||
value: serviceOverview.requestTotal,
|
||||
value: formatNumberWithUnit(serviceOverview.requestTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
request2xxTotal: serviceOverview.request2xxTotal,
|
||||
request4xxTotal: serviceOverview.request4xxTotal,
|
||||
request5xxTotal: serviceOverview.request5xxTotal
|
||||
request2xxTotal: formatNumberWithUnit(serviceOverview.request2xxTotal),
|
||||
request4xxTotal: formatNumberWithUnit(serviceOverview.request4xxTotal),
|
||||
request5xxTotal: formatNumberWithUnit(serviceOverview.request5xxTotal)
|
||||
},
|
||||
// token 消耗总数
|
||||
{
|
||||
@@ -201,11 +212,11 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
inputToken: item.inputToken,
|
||||
outputToken: item.outputToken
|
||||
})),
|
||||
value: serviceOverview.tokenTotal,
|
||||
value: formatNumberWithUnit(serviceOverview.tokenTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
inputTokenTotal: serviceOverview.inputTokenTotal,
|
||||
outputTokenTotal: serviceOverview.outputTokenTotal
|
||||
inputTokenTotal: formatNumberWithUnit(serviceOverview.inputTokenTotal),
|
||||
outputTokenTotal: formatNumberWithUnit(serviceOverview.outputTokenTotal)
|
||||
}
|
||||
])
|
||||
// 设置平均值数据
|
||||
@@ -214,29 +225,38 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
{
|
||||
title: $t('平均 Token 消耗'),
|
||||
data: serviceOverview.avgTokenOverview,
|
||||
value: serviceOverview.avgToken,
|
||||
value: formatNumberWithUnit(serviceOverview.avgToken) + ' Token/s',
|
||||
originValue: serviceOverview.avgToken,
|
||||
date: serviceOverview.date,
|
||||
min: serviceOverview.minToken,
|
||||
max: serviceOverview.maxToken,
|
||||
min: formatNumberWithUnit(serviceOverview.minToken) + ' Token/s',
|
||||
max: formatNumberWithUnit(serviceOverview.maxToken) + ' Token/s',
|
||||
type: 'area'
|
||||
},
|
||||
// 平均请求
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
value: serviceOverview.avgRequestPerSubscriber,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
{
|
||||
// 平均请求
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
max: abbreviateFloat(serviceOverview.maxRequestPerSubscriber),
|
||||
min: abbreviateFloat(serviceOverview.minRequestPerSubscriber)
|
||||
},
|
||||
// 评价 token 消耗
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的 Token 消耗'),
|
||||
data: serviceOverview.avgTokenPerSubscriberOverview.map((item: { inputToken: number; outputToken: number }) => ({
|
||||
inputToken: item.inputToken,
|
||||
outputToken: item.outputToken
|
||||
})),
|
||||
value: serviceOverview.avgTokenPerSubscriber,
|
||||
date: serviceOverview.date
|
||||
})
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的 Token 消耗'),
|
||||
data: serviceOverview.avgTokenPerSubscriberOverview.map(
|
||||
(item: { inputToken: number; outputToken: number }) => ({
|
||||
inputToken: item.inputToken,
|
||||
outputToken: item.outputToken
|
||||
})
|
||||
),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
max: abbreviateFloat(serviceOverview.maxTokenPerSubscriber),
|
||||
min: abbreviateFloat(serviceOverview.minTokenPerSubscriber)
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
@@ -268,7 +288,11 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
'request_5xx_total',
|
||||
'traffic_2xx_total',
|
||||
'traffic_4xx_total',
|
||||
'traffic_5xx_total'
|
||||
'traffic_5xx_total',
|
||||
'max_request_per_subscriber',
|
||||
'min_request_per_subscriber',
|
||||
'max_traffic_per_subscriber',
|
||||
'min_traffic_per_subscriber'
|
||||
]
|
||||
}).then((response) => {
|
||||
const { code, data, msg } = response
|
||||
@@ -354,7 +378,13 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
body: 'py-[15px] px-[0px]'
|
||||
}}
|
||||
>
|
||||
<ServiceBarChar showLegendIndicator={true} key={index} height={400} dataInfo={item} customClassNames="flex-1"></ServiceBarChar>
|
||||
<ServiceBarChar
|
||||
showLegendIndicator={true}
|
||||
key={index}
|
||||
height={400}
|
||||
dataInfo={item}
|
||||
customClassNames="flex-1"
|
||||
></ServiceBarChar>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
@@ -378,7 +408,13 @@ const ServiceOverview = ({ serviceType }: { serviceType: 'aiService' | 'restServ
|
||||
></ServiceAreaChart>
|
||||
</>
|
||||
) : (
|
||||
<ServiceBarChar key={index} height={270} dataInfo={item} showAvgLine={true} customClassNames="flex-1"></ServiceBarChar>
|
||||
<ServiceBarChar
|
||||
key={index}
|
||||
height={270}
|
||||
dataInfo={item}
|
||||
hideIndicatorValue={true}
|
||||
customClassNames="flex-1"
|
||||
></ServiceBarChar>
|
||||
)}
|
||||
</Card>
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export type BarData = {
|
||||
title: string
|
||||
value: string
|
||||
value?: string
|
||||
date: string[]
|
||||
data: any[]
|
||||
showXAxis?: boolean
|
||||
|
||||
@@ -4,7 +4,7 @@ import ScrollableSection from '@common/components/aoplatform/ScrollableSection'
|
||||
import { TimeRange } from '@common/components/aoplatform/TimeRangeSelector'
|
||||
import { useEffect, useState } from 'react'
|
||||
import DateSelectFilter, { TimeOption } from '@core/pages/serviceOverview/filter/DateSelectFilter'
|
||||
import { getTime } from '@dashboard/utils/dashboard'
|
||||
import { abbreviateFloat, formatBytes, formatDuration, formatNumberWithUnit, getTime } from '@dashboard/utils/dashboard'
|
||||
import { $t } from '@common/locales/index.ts'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { Card, Spin } from 'antd'
|
||||
@@ -71,7 +71,11 @@ export default function DashboardTotal() {
|
||||
'request_4xx_total',
|
||||
'request_5xx_total',
|
||||
'input_token_total',
|
||||
'output_token_total'
|
||||
'output_token_total',
|
||||
'max_request_per_subscriber',
|
||||
'min_request_per_subscriber',
|
||||
'max_token_per_subscriber',
|
||||
'min_token_per_subscriber'
|
||||
]
|
||||
}).then((response) => {
|
||||
const { code, data, msg } = response
|
||||
@@ -109,7 +113,11 @@ export default function DashboardTotal() {
|
||||
'request_5xx_total',
|
||||
'traffic_2xx_total',
|
||||
'traffic_4xx_total',
|
||||
'traffic_5xx_total'
|
||||
'traffic_5xx_total',
|
||||
'max_request_per_subscriber',
|
||||
'min_request_per_subscriber',
|
||||
'max_traffic_per_subscriber',
|
||||
'min_traffic_per_subscriber'
|
||||
]
|
||||
}).then((response) => {
|
||||
const { code, data, msg } = response
|
||||
@@ -135,24 +143,24 @@ export default function DashboardTotal() {
|
||||
...setBarChartInfoData({
|
||||
title: $t('请求次数'),
|
||||
data: serviceOverview.requestOverview,
|
||||
value: serviceOverview.requestTotal,
|
||||
value: formatNumberWithUnit(serviceOverview.requestTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
request2xxTotal: serviceOverview.request2xxTotal,
|
||||
request4xxTotal: serviceOverview.request4xxTotal,
|
||||
request5xxTotal: serviceOverview.request5xxTotal
|
||||
request2xxTotal: formatNumberWithUnit(serviceOverview.request2xxTotal),
|
||||
request4xxTotal: formatNumberWithUnit(serviceOverview.request4xxTotal),
|
||||
request5xxTotal: formatNumberWithUnit(serviceOverview.request5xxTotal)
|
||||
},
|
||||
// 流量消耗总数
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('网络流量'),
|
||||
data: serviceOverview.trafficOverview,
|
||||
value: serviceOverview.trafficTotal,
|
||||
value: formatBytes(serviceOverview.trafficTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
traffic2xxTotal: serviceOverview.traffic2xxTotal,
|
||||
traffic4xxTotal: serviceOverview.traffic4xxTotal,
|
||||
traffic5xxTotal: serviceOverview.traffic5xxTotal
|
||||
traffic2xxTotal: formatBytes(serviceOverview.traffic2xxTotal),
|
||||
traffic4xxTotal: formatBytes(serviceOverview.traffic4xxTotal),
|
||||
traffic5xxTotal: formatBytes(serviceOverview.traffic5xxTotal)
|
||||
}
|
||||
])
|
||||
// 设置平均值数据
|
||||
@@ -161,26 +169,33 @@ export default function DashboardTotal() {
|
||||
{
|
||||
title: $t('平均响应时间'),
|
||||
data: serviceOverview.avgResponseTimeOverview,
|
||||
value: serviceOverview.avgResponseTime,
|
||||
value: formatDuration(serviceOverview.avgResponseTime),
|
||||
originValue: serviceOverview.avgResponseTime,
|
||||
date: serviceOverview.date,
|
||||
min: serviceOverview.minResponseTime,
|
||||
max: serviceOverview.maxResponseTime,
|
||||
min: formatDuration(serviceOverview.minResponseTime),
|
||||
max: formatDuration(serviceOverview.maxResponseTime),
|
||||
type: 'area'
|
||||
},
|
||||
// 平均请求
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
value: serviceOverview.avgRequestPerSubscriber,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
max: abbreviateFloat(serviceOverview.maxRequestPerSubscriber),
|
||||
min: abbreviateFloat(serviceOverview.minRequestPerSubscriber)
|
||||
},
|
||||
// 平均流量消耗
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的网络流量'),
|
||||
data: serviceOverview.avgTrafficPerSubscriberOverview,
|
||||
value: serviceOverview.avgTrafficPerSubscriber,
|
||||
date: serviceOverview.date
|
||||
})
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的网络流量'),
|
||||
data: serviceOverview.avgTrafficPerSubscriberOverview,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
max: formatBytes(serviceOverview.maxTrafficPerSubscriber),
|
||||
min: formatBytes(serviceOverview.minTrafficPerSubscriber)
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
@@ -195,12 +210,12 @@ export default function DashboardTotal() {
|
||||
...setBarChartInfoData({
|
||||
title: $t('请求次数'),
|
||||
data: serviceOverview.requestOverview,
|
||||
value: serviceOverview.requestTotal,
|
||||
value: formatNumberWithUnit(serviceOverview.requestTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
request2xxTotal: serviceOverview.request2xxTotal,
|
||||
request4xxTotal: serviceOverview.request4xxTotal,
|
||||
request5xxTotal: serviceOverview.request5xxTotal
|
||||
request2xxTotal: formatNumberWithUnit(serviceOverview.request2xxTotal),
|
||||
request4xxTotal: formatNumberWithUnit(serviceOverview.request4xxTotal),
|
||||
request5xxTotal: formatNumberWithUnit(serviceOverview.request5xxTotal)
|
||||
},
|
||||
// token 消耗总数
|
||||
{
|
||||
@@ -210,11 +225,11 @@ export default function DashboardTotal() {
|
||||
inputToken: item.inputToken,
|
||||
outputToken: item.outputToken
|
||||
})),
|
||||
value: serviceOverview.tokenTotal,
|
||||
value: formatNumberWithUnit(serviceOverview.tokenTotal),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
inputTokenTotal: serviceOverview.inputTokenTotal,
|
||||
outputTokenTotal: serviceOverview.outputTokenTotal
|
||||
inputTokenTotal: formatNumberWithUnit(serviceOverview.inputTokenTotal),
|
||||
outputTokenTotal: formatNumberWithUnit(serviceOverview.outputTokenTotal)
|
||||
}
|
||||
])
|
||||
// 设置平均值数据
|
||||
@@ -223,31 +238,38 @@ export default function DashboardTotal() {
|
||||
{
|
||||
title: $t('平均 Token 消耗'),
|
||||
data: serviceOverview.avgTokenOverview,
|
||||
value: serviceOverview.avgToken,
|
||||
value: formatNumberWithUnit(serviceOverview.avgToken) + ' Token/s',
|
||||
originValue: serviceOverview.avgToken,
|
||||
date: serviceOverview.date,
|
||||
min: serviceOverview.minToken,
|
||||
max: serviceOverview.maxToken,
|
||||
min: formatNumberWithUnit(serviceOverview.minToken) + ' Token/s',
|
||||
max: formatNumberWithUnit(serviceOverview.maxToken) + ' Token/s',
|
||||
type: 'area'
|
||||
},
|
||||
// 平均请求
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
value: serviceOverview.avgRequestPerSubscriber,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的请求次数'),
|
||||
data: serviceOverview.avgRequestPerSubscriberOverview,
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
max: abbreviateFloat(serviceOverview.maxRequestPerSubscriber),
|
||||
min: abbreviateFloat(serviceOverview.minRequestPerSubscriber)
|
||||
},
|
||||
// 平均 token 消耗
|
||||
setBarChartInfoData({
|
||||
title: $t('平均每消费者的 Token 消耗'),
|
||||
data: serviceOverview.avgTokenPerSubscriberOverview.map(
|
||||
(item: { inputToken: number; outputToken: number }) => ({
|
||||
inputToken: item.inputToken,
|
||||
outputToken: item.outputToken
|
||||
})
|
||||
),
|
||||
value: serviceOverview.avgTokenPerSubscriber,
|
||||
date: serviceOverview.date
|
||||
})
|
||||
{
|
||||
...setBarChartInfoData({
|
||||
title: $t('平均每消费者的 Token 消耗'),
|
||||
data: serviceOverview.avgTokenPerSubscriberOverview.map(
|
||||
(item: { inputToken: number; outputToken: number }) => ({
|
||||
inputToken: item.inputToken,
|
||||
outputToken: item.outputToken
|
||||
})
|
||||
),
|
||||
date: serviceOverview.date
|
||||
}),
|
||||
max: abbreviateFloat(serviceOverview.maxTokenPerSubscriber),
|
||||
min: abbreviateFloat(serviceOverview.minTokenPerSubscriber)
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
@@ -394,7 +416,7 @@ export default function DashboardTotal() {
|
||||
<ServiceBarChar
|
||||
key={index}
|
||||
height={270}
|
||||
showAvgLine={true}
|
||||
hideIndicatorValue={true}
|
||||
dataInfo={item}
|
||||
customClassNames="flex-1"
|
||||
></ServiceBarChar>
|
||||
|
||||
@@ -89,3 +89,114 @@ export function yUnitFormatter(value: number): string {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数字并添加适当的单位后缀
|
||||
* 根据数字大小自动选择合适的单位:
|
||||
* - 小于1000:原始数字
|
||||
* - 千级别(K): 1,000 - 999,999
|
||||
* - 百万级别(M): 1,000,000 - 999,999,999
|
||||
* - 十亿级别(B): 1,000,000,000 - 999,999,999,999
|
||||
* - 万亿级别(T): 1,000,000,000,000及以上
|
||||
* @param count 需要格式化的数字
|
||||
* @returns 格式化后的字符串,包含单位
|
||||
*/
|
||||
export function formatNumberWithUnit(count: number) {
|
||||
if (count < 1000) {
|
||||
return count.toString() // 小于1000直接返回
|
||||
} else if (count < 1_000_000) {
|
||||
return (count / 1000).toFixed(1) + 'K' // 千级别,如1.5K
|
||||
} else if (count < 1_000_000_000) {
|
||||
return (count / 1_000_000).toFixed(1) + 'M' // 百万级别,如2.3M
|
||||
} else if (count < 1_000_000_000_000) {
|
||||
return (count / 1_000_000_000).toFixed(1) + 'B' // 十亿级别,如4.5B
|
||||
} else {
|
||||
return (count / 1_000_000_000_000).toFixed(1) + 'T' // 万亿级别,如7.8T
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化浮点数并缩写为带单位的形式
|
||||
* 与 formatNumberWithUnit 类似,但对小于1000的数字也进行保留1位小数的格式化
|
||||
* - 小于1000:保留1位小数
|
||||
* - 千级别(K): 1,000 - 999,999
|
||||
* - 百万级别(M): 1,000,000 - 999,999,999
|
||||
* - 十亿级别(B): 1,000,000,000 - 999,999,999,999
|
||||
* - 万亿级别(T): 1,000,000,000,000及以上
|
||||
* @param count 需要格式化的数字
|
||||
* @returns 格式化后的字符串,包含单位
|
||||
*/
|
||||
export function abbreviateFloat(count: number) {
|
||||
if (count < 1000) {
|
||||
return count.toFixed(1) // 小于1000的数字保留1位小数,如5.0
|
||||
} else if (count < 1_000_000) {
|
||||
return (count / 1000).toFixed(1) + 'K' // 千级别,如1.5K
|
||||
} else if (count < 1_000_000_000) {
|
||||
return (count / 1_000_000).toFixed(1) + 'M' // 百万级别,如2.3M
|
||||
} else if (count < 1_000_000_000_000) {
|
||||
return (count / 1_000_000_000).toFixed(1) + 'B' // 十亿级别,如4.5B
|
||||
} else {
|
||||
return (count / 1_000_000_000_000).toFixed(1) + 'T' // 万亿级别,如7.8T
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间持续时间,自动选择合适的时间单位
|
||||
* 根据持续时间的长度自动选择不同的单位:
|
||||
* - 毫秒(ms): < 1000
|
||||
* - 秒(s): 1,000 - 999,999
|
||||
* - 分钟(min): 1,000,000 - 999,999,999
|
||||
* - 小时(hour): 1,000,000,000 - 999,999,999,999
|
||||
* - 天(day): ≥ 1,000,000,000,000
|
||||
* @param durationNano 时间持续时间数值
|
||||
* @returns 格式化后的字符串,包含单位
|
||||
*/
|
||||
export function formatDuration(durationNano: number) {
|
||||
if (durationNano < 1000) {
|
||||
return `${durationNano}ms` // 小于1000,返回毫秒
|
||||
}
|
||||
if (durationNano < 1_000_000) {
|
||||
return (durationNano / 1000).toFixed(1) + 's' // 转换为秒
|
||||
}
|
||||
if (durationNano < 1_000_000_000) {
|
||||
return (durationNano / 1_000_000).toFixed(1) + 'min' // 转换为分钟
|
||||
}
|
||||
if (durationNano < 1_000_000_000_000) {
|
||||
return (durationNano / 1_000_000_000).toFixed(1) + 'hour' // 转换为小时
|
||||
}
|
||||
return (durationNano / 1_000_000_000_000).toFixed(1) + 'day' // 转换为天
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数据大小,自动选择合适的单位
|
||||
* 根据字节数自动选择适当的单位进行显示:
|
||||
* - 字节(B): < 1000
|
||||
* - 千字节(KB): 1,000 - 999,999
|
||||
* - 兆字节(MB): 1,000,000 - 999,999,999
|
||||
* - 吉字节(GB): 1,000,000,000 - 999,999,999,999
|
||||
* - 太字节(TB): 1,000,000,000,000 - 999,999,999,999,999
|
||||
* - 拉字节(PB): ≥ 1,000,000,000,000,000
|
||||
* @param bytes 字节数
|
||||
* @returns 格式化后的字符串,包含单位
|
||||
*/
|
||||
export function formatBytes(bytes: number) {
|
||||
const KB = 1000 // 千字节
|
||||
const MB = KB * 1000 // 兆字节
|
||||
const GB = MB * 1000 // 吉字节
|
||||
const TB = GB * 1000 // 太字节
|
||||
const PB = TB * 1000 // 拉字节
|
||||
|
||||
if (bytes < KB) {
|
||||
return `${bytes}B` // 直接显示字节
|
||||
} else if (bytes < MB) {
|
||||
return (bytes / KB).toFixed(1) + 'KB' // 转换为千字节
|
||||
} else if (bytes < GB) {
|
||||
return (bytes / MB).toFixed(1) + 'MB' // 转换为兆字节
|
||||
} else if (bytes < TB) {
|
||||
return (bytes / GB).toFixed(1) + 'GB' // 转换为吉字节
|
||||
} else if (bytes < PB) {
|
||||
return (bytes / TB).toFixed(1) + 'TB' // 转换为太字节
|
||||
} else {
|
||||
return (bytes / PB).toFixed(1) + 'PB' // 转换为拉字节
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user