⚡ feat: Add speed test functionality to API info display
- Add speed test tag with gauge icon for each API route - Integrate tcptest.cn service for API endpoint performance testing - Implement handleSpeedTest callback to open speed test in new tab - Add Tag component import from @douyinfe/semi-ui - Use Gauge icon with white circular tag styling - Position speed test tag before API route for better visibility - URL encoding handles special characters for proper test URL generation - Remove unused IconTestScoreStroked import and clean up comments The speed test feature allows users to quickly test API endpoint performance by clicking a small circular tag that opens the tcptest.cn speed testing service with the encoded API URL.
This commit is contained in:
@@ -1585,5 +1585,6 @@
|
|||||||
"请输入说明": "Please enter the description",
|
"请输入说明": "Please enter the description",
|
||||||
"如:香港线路": "e.g. Hong Kong line",
|
"如:香港线路": "e.g. Hong Kong line",
|
||||||
"请联系管理员在系统设置中配置API信息": "Please contact the administrator to configure API information in the system settings.",
|
"请联系管理员在系统设置中配置API信息": "Please contact the administrator to configure API information in the system settings.",
|
||||||
"确定要删除此API信息吗?": "Are you sure you want to delete this API information?"
|
"确定要删除此API信息吗?": "Are you sure you want to delete this API information?",
|
||||||
|
"测速": "Speed Test"
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
Tabs,
|
Tabs,
|
||||||
TabPane,
|
TabPane,
|
||||||
Empty,
|
Empty,
|
||||||
|
Tag
|
||||||
} from '@douyinfe/semi-ui';
|
} from '@douyinfe/semi-ui';
|
||||||
import {
|
import {
|
||||||
IconRefresh,
|
IconRefresh,
|
||||||
@@ -25,7 +26,7 @@ import {
|
|||||||
IconPulse,
|
IconPulse,
|
||||||
IconStopwatchStroked,
|
IconStopwatchStroked,
|
||||||
IconTypograph,
|
IconTypograph,
|
||||||
IconPieChart2Stroked,
|
IconPieChart2Stroked
|
||||||
} from '@douyinfe/semi-icons';
|
} from '@douyinfe/semi-icons';
|
||||||
import { IllustrationConstruction, IllustrationConstructionDark } from '@douyinfe/semi-illustrations';
|
import { IllustrationConstruction, IllustrationConstructionDark } from '@douyinfe/semi-illustrations';
|
||||||
import { VChart } from '@visactor/react-vchart';
|
import { VChart } from '@visactor/react-vchart';
|
||||||
@@ -495,6 +496,12 @@ const Detail = (props) => {
|
|||||||
}
|
}
|
||||||
}, [t]);
|
}, [t]);
|
||||||
|
|
||||||
|
const handleSpeedTest = useCallback((apiUrl) => {
|
||||||
|
const encodedUrl = encodeURIComponent(apiUrl);
|
||||||
|
const speedTestUrl = `https://www.tcptest.cn/http/${encodedUrl}`;
|
||||||
|
window.open(speedTestUrl, '_blank');
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleInputChange = useCallback((value, name) => {
|
const handleInputChange = useCallback((value, name) => {
|
||||||
if (name === 'data_export_default_time') {
|
if (name === 'data_export_default_time') {
|
||||||
setDataExportDefaultTime(value);
|
setDataExportDefaultTime(value);
|
||||||
@@ -698,22 +705,17 @@ const Detail = (props) => {
|
|||||||
}, [dataExportDefaultTime, getTimeInterval]);
|
}, [dataExportDefaultTime, getTimeInterval]);
|
||||||
|
|
||||||
const updateChartData = useCallback((data) => {
|
const updateChartData = useCallback((data) => {
|
||||||
// 处理原始数据
|
|
||||||
const processedData = processRawData(data);
|
const processedData = processRawData(data);
|
||||||
const { totalQuota, totalTimes, totalTokens, uniqueModels, timePoints, timeQuotaMap, timeTokensMap, timeCountMap } = processedData;
|
const { totalQuota, totalTimes, totalTokens, uniqueModels, timePoints, timeQuotaMap, timeTokensMap, timeCountMap } = processedData;
|
||||||
|
|
||||||
// 计算趋势数据
|
|
||||||
const trendDataResult = calculateTrendData(timePoints, timeQuotaMap, timeTokensMap, timeCountMap);
|
const trendDataResult = calculateTrendData(timePoints, timeQuotaMap, timeTokensMap, timeCountMap);
|
||||||
setTrendData(trendDataResult);
|
setTrendData(trendDataResult);
|
||||||
|
|
||||||
// 生成模型颜色映射
|
|
||||||
const newModelColors = generateModelColors(uniqueModels);
|
const newModelColors = generateModelColors(uniqueModels);
|
||||||
setModelColors(newModelColors);
|
setModelColors(newModelColors);
|
||||||
|
|
||||||
// 聚合数据
|
|
||||||
const aggregatedData = aggregateDataByTimeAndModel(data);
|
const aggregatedData = aggregateDataByTimeAndModel(data);
|
||||||
|
|
||||||
// 生成饼图数据
|
|
||||||
const modelTotals = new Map();
|
const modelTotals = new Map();
|
||||||
for (let [_, value] of aggregatedData) {
|
for (let [_, value] of aggregatedData) {
|
||||||
updateMapValue(modelTotals, value.model, value.count);
|
updateMapValue(modelTotals, value.model, value.count);
|
||||||
@@ -724,7 +726,6 @@ const Detail = (props) => {
|
|||||||
value: count,
|
value: count,
|
||||||
})).sort((a, b) => b.value - a.value);
|
})).sort((a, b) => b.value - a.value);
|
||||||
|
|
||||||
// 生成线图数据
|
|
||||||
const chartTimePoints = generateChartTimePoints(aggregatedData, data);
|
const chartTimePoints = generateChartTimePoints(aggregatedData, data);
|
||||||
let newLineData = [];
|
let newLineData = [];
|
||||||
|
|
||||||
@@ -748,7 +749,6 @@ const Detail = (props) => {
|
|||||||
|
|
||||||
newLineData.sort((a, b) => a.Time.localeCompare(b.Time));
|
newLineData.sort((a, b) => a.Time.localeCompare(b.Time));
|
||||||
|
|
||||||
// 更新图表配置
|
|
||||||
updateChartSpec(
|
updateChartSpec(
|
||||||
setSpecPie,
|
setSpecPie,
|
||||||
newPieData,
|
newPieData,
|
||||||
@@ -765,7 +765,6 @@ const Detail = (props) => {
|
|||||||
'barData'
|
'barData'
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新状态
|
|
||||||
setPieData(newPieData);
|
setPieData(newPieData);
|
||||||
setLineData(newLineData);
|
setLineData(newLineData);
|
||||||
setConsumeQuota(totalQuota);
|
setConsumeQuota(totalQuota);
|
||||||
@@ -994,7 +993,17 @@ const Detail = (props) => {
|
|||||||
</Avatar>
|
</Avatar>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="text-sm font-medium text-gray-900 mb-1">
|
<div className="text-sm font-medium text-gray-900 mb-1 !font-bold flex items-center gap-2">
|
||||||
|
<Tag
|
||||||
|
prefixIcon={<Gauge size={12} />}
|
||||||
|
size="small"
|
||||||
|
color="white"
|
||||||
|
shape='circle'
|
||||||
|
onClick={() => handleSpeedTest(api.url)}
|
||||||
|
className="cursor-pointer hover:opacity-80 text-xs"
|
||||||
|
>
|
||||||
|
{t('测速')}
|
||||||
|
</Tag>
|
||||||
{api.route}
|
{api.route}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|||||||
Reference in New Issue
Block a user