From 232ba46b16620c7e66c7ef3d65a919eba12831cb Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Mon, 14 Jul 2025 20:22:09 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20feat(detail):=20enhance=20API=20?= =?UTF-8?q?Info=20list=20with=20jump=20button=20&=20responsive=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 `` between API items to improve visual separation * Tweaked flex gaps and utility classes for consistent spacing and readability --- web/src/pages/Detail/index.js | 604 ++++++++++++++++++---------------- 1 file changed, 313 insertions(+), 291 deletions(-) diff --git a/web/src/pages/Detail/index.js b/web/src/pages/Detail/index.js index 584a0ab2..e8ed36fa 100644 --- a/web/src/pages/Detail/index.js +++ b/web/src/pages/Detail/index.js @@ -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) => {

{getGreeting}

- } onClick={showSearchModal} className={`bg-green-500 hover:bg-green-600 ${ICON_BUTTON_CLASS}`} /> - } onClick={refresh} loading={loading} @@ -1311,40 +1313,57 @@ const Detail = (props) => { > {apiInfoData.length > 0 ? ( apiInfoData.map((api) => ( -
-
- - {api.route.substring(0, 2)} - -
-
-
- } - size="small" - color="white" - shape='circle' - onClick={() => handleSpeedTest(api.url)} - className="cursor-pointer hover:opacity-80 text-xs" + <> +
+
+ - {t('测速')} - - {api.route} + {api.route.substring(0, 2)} +
-
handleCopyUrl(api.url)} - > - {api.url} -
-
- {api.description} +
+
+ + {api.route} + +
+ } + size="small" + color="white" + shape='circle' + onClick={() => handleSpeedTest(api.url)} + className="cursor-pointer hover:opacity-80 text-xs" + > + {t('测速')} + + } + size="small" + color="white" + shape='circle' + onClick={() => window.open(api.url, '_blank', 'noopener,noreferrer')} + className="cursor-pointer hover:opacity-80 text-xs" + > + {t('跳转')} + +
+
+
handleCopyUrl(api.url)} + > + {api.url} +
+
+ {api.description} +
-
+ + )) ) : (
@@ -1368,274 +1387,277 @@ const Detail = (props) => {
{/* 系统公告和常见问答卡片 */} - {hasInfoPanels && ( -
-
- {/* 公告卡片 */} - {announcementsEnabled && ( - -
- - {t('系统公告')} - - {t('显示最新20条')} - -
- {/* 图例 */} -
- {announcementLegendData.map((legend, index) => ( -
-
- {legend.label} -
- ))} -
-
- } - > -
-
handleCardScroll(announcementScrollRef, setShowAnnouncementScrollHint)} - > - {announcementData.length > 0 ? ( - - {announcementData.map((item, idx) => ( - -
-
- {item.extra && ( -
- )} -
- - ))} - - ) : ( -
- } - darkModeImage={} - title={t('暂无系统公告')} - description={t('请联系管理员在系统设置中配置公告信息')} - /> + { + hasInfoPanels && ( +
+
+ {/* 公告卡片 */} + {announcementsEnabled && ( + +
+ + {t('系统公告')} + + {t('显示最新20条')} +
- )} -
-
-
- - )} - - {/* 常见问答卡片 */} - {faqEnabled && ( - - - {t('常见问答')} -
- } - bodyStyle={{ padding: 0 }} - > -
-
handleCardScroll(faqScrollRef, setShowFaqScrollHint)} - > - {faqData.length > 0 ? ( - } - collapseIcon={} - > - {faqData.map((item, index) => ( - + {/* 图例 */} +
+ {announcementLegendData.map((legend, index) => ( +
- + {legend.label} +
))} - - ) : ( -
- } - darkModeImage={} - title={t('暂无常见问答')} - description={t('请联系管理员在系统设置中配置常见问答')} - />
- )} -
-
-
- - )} - - {/* 服务可用性卡片 */} - {uptimeEnabled && ( - -
- - {t('服务可用性')}
- } - onClick={loadUptimeData} - loading={uptimeLoading} - size="small" - theme="borderless" - className="text-gray-500 hover:text-blue-500 hover:bg-blue-50 !rounded-full" + } + > +
+
handleCardScroll(announcementScrollRef, setShowAnnouncementScrollHint)} + > + {announcementData.length > 0 ? ( + + {announcementData.map((item, idx) => ( + +
+
+ {item.extra && ( +
+ )} +
+ + ))} + + ) : ( +
+ } + darkModeImage={} + title={t('暂无系统公告')} + description={t('请联系管理员在系统设置中配置公告信息')} + /> +
+ )} +
+
- } - bodyStyle={{ padding: 0 }} - > - {/* 内容区域 */} -
- - {uptimeData.length > 0 ? ( - uptimeData.length === 1 ? ( -
-
handleCardScroll(uptimeScrollRef, setShowUptimeScrollHint)} - > - {renderMonitorList(uptimeData[0].monitors)} -
-
-
- ) : ( - - {uptimeData.map((group, groupIdx) => { - if (!uptimeTabScrollRefs.current[group.categoryName]) { - uptimeTabScrollRefs.current[group.categoryName] = React.createRef(); - } - const tabScrollRef = uptimeTabScrollRefs.current[group.categoryName]; + + )} - return ( - - - {group.categoryName} - - {group.monitors ? group.monitors.length : 0} - - - } - itemKey={group.categoryName} - key={groupIdx} - > -
-
handleCardScroll(tabScrollRef, setShowUptimeScrollHint)} - > - {renderMonitorList(group.monitors)} -
-
-
- - ); - })} - - ) - ) : ( -
- } - darkModeImage={} - title={t('暂无监控数据')} - description={t('请联系管理员在系统设置中配置Uptime')} - /> -
- )} - -
- - {/* 固定在底部的图例 */} - {uptimeData.length > 0 && ( -
-
- {uptimeLegendData.map((legend, index) => ( -
-
- {legend.label} -
- ))} + {/* 常见问答卡片 */} + {faqEnabled && ( + + + {t('常见问答')}
+ } + bodyStyle={{ padding: 0 }} + > +
+
handleCardScroll(faqScrollRef, setShowFaqScrollHint)} + > + {faqData.length > 0 ? ( + } + collapseIcon={} + > + {faqData.map((item, index) => ( + +
+ + ))} + + ) : ( +
+ } + darkModeImage={} + title={t('暂无常见问答')} + description={t('请联系管理员在系统设置中配置常见问答')} + /> +
+ )} +
+
- )} - - )} + + )} + + {/* 服务可用性卡片 */} + {uptimeEnabled && ( + +
+ + {t('服务可用性')} +
+
+ } + bodyStyle={{ padding: 0 }} + > + {/* 内容区域 */} +
+ + {uptimeData.length > 0 ? ( + uptimeData.length === 1 ? ( +
+
handleCardScroll(uptimeScrollRef, setShowUptimeScrollHint)} + > + {renderMonitorList(uptimeData[0].monitors)} +
+
+
+ ) : ( + + {uptimeData.map((group, groupIdx) => { + if (!uptimeTabScrollRefs.current[group.categoryName]) { + uptimeTabScrollRefs.current[group.categoryName] = React.createRef(); + } + const tabScrollRef = uptimeTabScrollRefs.current[group.categoryName]; + + return ( + + + {group.categoryName} + + {group.monitors ? group.monitors.length : 0} + + + } + itemKey={group.categoryName} + key={groupIdx} + > +
+
handleCardScroll(tabScrollRef, setShowUptimeScrollHint)} + > + {renderMonitorList(group.monitors)} +
+
+
+ + ); + })} + + ) + ) : ( +
+ } + darkModeImage={} + title={t('暂无监控数据')} + description={t('请联系管理员在系统设置中配置Uptime')} + /> +
+ )} + +
+ + {/* 固定在底部的图例 */} + {uptimeData.length > 0 && ( +
+
+ {uptimeLegendData.map((legend, index) => ( +
+
+ {legend.label} +
+ ))} +
+
+ )} + + )} +
-
- )} - -
+ ) + } + +
); };