🚀 feat(detail): enhance API Info list with jump button & responsive layout

* Added an “Jump” (`ExternalLink`) tag to each API entry that opens the URL in a new tab
* Placed “Speed Test” and “Jump” tags on the same line as the route
  * Route is left-aligned; tags are right-aligned and wrap to next line when space is insufficient
* Inserted `<Divider />` between API items to improve visual separation
* Tweaked flex gaps and utility classes for consistent spacing and readability
This commit is contained in:
t0ng7u
2025-07-14 20:22:09 +08:00
parent 5f011502d1
commit 232ba46b16

View File

@@ -1,14 +1,14 @@
import React, { useContext, useEffect, useRef, useState, useMemo, useCallback } from 'react';
import { initVChartSemiTheme } from '@visactor/vchart-semi-theme';
import { useNavigate } from 'react-router-dom';
import { Wallet, Activity, Zap, Gauge, PieChart, Server, Bell, HelpCircle } from 'lucide-react';
import { Wallet, Activity, Zap, Gauge, PieChart, Server, Bell, HelpCircle, ExternalLink } from 'lucide-react';
import { marked } from 'marked';
import {
Card,
Form,
Spin,
IconButton,
Button,
Modal,
Avatar,
Tabs,
@@ -614,7 +614,7 @@ const Detail = (props) => {
const handleSpeedTest = useCallback((apiUrl) => {
const encodedUrl = encodeURIComponent(apiUrl);
const speedTestUrl = `https://www.tcptest.cn/http/${encodedUrl}`;
window.open(speedTestUrl, '_blank');
window.open(speedTestUrl, '_blank', 'noopener,noreferrer');
}, []);
const handleInputChange = useCallback((value, name) => {
@@ -1108,12 +1108,14 @@ const Detail = (props) => {
<div className="flex items-center justify-between mb-4">
<h2 className="text-2xl font-semibold text-gray-800">{getGreeting}</h2>
<div className="flex gap-3">
<IconButton
<Button
type='tertiary'
icon={<IconSearch />}
onClick={showSearchModal}
className={`bg-green-500 hover:bg-green-600 ${ICON_BUTTON_CLASS}`}
/>
<IconButton
<Button
type='tertiary'
icon={<IconRefresh />}
onClick={refresh}
loading={loading}
@@ -1311,6 +1313,7 @@ const Detail = (props) => {
>
{apiInfoData.length > 0 ? (
apiInfoData.map((api) => (
<>
<div key={api.id} className="flex p-2 hover:bg-white rounded-lg transition-colors cursor-pointer">
<div className="flex-shrink-0 mr-3">
<Avatar
@@ -1321,7 +1324,11 @@ const Detail = (props) => {
</Avatar>
</div>
<div className="flex-1">
<div className="text-sm font-medium text-gray-900 mb-1 !font-bold flex items-center gap-2">
<div className="flex flex-wrap items-center justify-between mb-1 w-full gap-2">
<span className="text-sm font-medium text-gray-900 !font-bold break-all">
{api.route}
</span>
<div className="flex items-center gap-1 mt-1 lg:mt-0">
<Tag
prefixIcon={<Gauge size={12} />}
size="small"
@@ -1332,7 +1339,17 @@ const Detail = (props) => {
>
{t('测速')}
</Tag>
{api.route}
<Tag
prefixIcon={<ExternalLink size={12} />}
size="small"
color="white"
shape='circle'
onClick={() => window.open(api.url, '_blank', 'noopener,noreferrer')}
className="cursor-pointer hover:opacity-80 text-xs"
>
{t('跳转')}
</Tag>
</div>
</div>
<div
className="!text-semi-color-primary break-all cursor-pointer hover:underline mb-1"
@@ -1345,6 +1362,8 @@ const Detail = (props) => {
</div>
</div>
</div>
<Divider />
</>
))
) : (
<div className="flex justify-center items-center py-8">
@@ -1368,7 +1387,8 @@ const Detail = (props) => {
</div>
{/* 系统公告和常见问答卡片 */}
{hasInfoPanels && (
{
hasInfoPanels && (
<div className="mb-4">
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4">
{/* 公告卡片 */}
@@ -1520,12 +1540,13 @@ const Detail = (props) => {
<Gauge size={16} />
{t('服务可用性')}
</div>
<IconButton
<Button
icon={<IconRefresh />}
onClick={loadUptimeData}
loading={uptimeLoading}
size="small"
theme="borderless"
type='tertiary'
className="text-gray-500 hover:text-blue-500 hover:bg-blue-50 !rounded-full"
/>
</div>
@@ -1633,9 +1654,10 @@ const Detail = (props) => {
)}
</div>
</div>
)}
</Spin>
</div>
)
}
</Spin >
</div >
);
};