🥳 feat(detail): unify uptime status handling & enhance availability card UI

Summary
• Centralized uptime status definition via `uptimeStatusMap`, containing color / label / text for each status.
• Generated `uptimeLegendData`, `getUptimeStatusColor`, `getUptimeStatusText` directly from the map, removing multiple switch-case blocks.

UI Improvements
1. Added statuses 2 (High Latency) & 3 (Maintenance) with dedicated colors.
2. Relocated status legend to a styled footer wrapped in a borderless sub-Card; header now only shows title + refresh button.
3. Footer (and its negative margin) renders only when `uptimeData` is present, preventing empty legend display.
4. Applied rounded, blurred badge style and always-on shadow to legend container for clearer separation.

Maintenance
• Simplified code paths, reduced duplication, and improved readability without breaking existing functionality.
This commit is contained in:
Apple\Apple
2025-06-11 03:12:34 +08:00
parent 4baaf456a7
commit 48817648c3
2 changed files with 50 additions and 47 deletions

View File

@@ -881,7 +881,6 @@
"你好,": "Hello,", "你好,": "Hello,",
"线路监控": "line monitoring", "线路监控": "line monitoring",
"查看全部": "View all", "查看全部": "View all",
"高延迟": "high latency",
"异常": "Abnormal", "异常": "Abnormal",
"的未命名令牌": "unnamed token", "的未命名令牌": "unnamed token",
"令牌更新成功!": "Token updated successfully!", "令牌更新成功!": "Token updated successfully!",
@@ -1644,6 +1643,8 @@
"服务可用性": "Service Status", "服务可用性": "Service Status",
"可用率": "Availability", "可用率": "Availability",
"有异常": "Abnormal", "有异常": "Abnormal",
"高延迟": "High latency",
"维护中": "Maintenance",
"暂无监控数据": "No monitoring data", "暂无监控数据": "No monitoring data",
"请联系管理员在系统设置中配置Uptime": "Please contact the administrator to configure Uptime in the system settings." "请联系管理员在系统设置中配置Uptime": "Please contact the administrator to configure Uptime in the system settings."
} }

View File

@@ -846,28 +846,27 @@ const Detail = (props) => {
{ color: 'red', label: t('异常'), type: 'error' } { color: 'red', label: t('异常'), type: 'error' }
], [t]); ], [t]);
const uptimeLegendData = useMemo(() => [ const uptimeStatusMap = useMemo(() => ({
{ color: 'green', label: t('正常'), status: 1 }, 1: { color: '#10b981', label: t('正常'), text: t('可用率') }, // UP
{ color: 'red', label: t('异常'), status: 0 } 0: { color: '#ef4444', label: t('异常'), text: t('有异常') }, // DOWN
], [t]); 2: { color: '#f59e0b', label: t('高延迟'), text: t('高延迟') }, // PENDING
3: { color: '#3b82f6', label: t('维护中'), text: t('维护中') } // MAINTENANCE
}), [t]);
const getUptimeStatusColor = useCallback((status) => { const uptimeLegendData = useMemo(() =>
switch (status) { Object.entries(uptimeStatusMap).map(([status, info]) => ({
case 1: status: Number(status),
return '#10b981'; // 绿色 - 正常 color: info.color,
default: label: info.label
return '#ef4444'; // 红色 - 异常 })), [uptimeStatusMap]);
}
}, []);
const getUptimeStatusText = useCallback((status) => { const getUptimeStatusColor = useCallback((status) =>
switch (status) { uptimeStatusMap[status]?.color || '#8b9aa7',
case 1: [uptimeStatusMap]);
return t('可用率');
default: const getUptimeStatusText = useCallback((status) =>
return t('有异常'); uptimeStatusMap[status]?.text || t('未知'),
} [uptimeStatusMap, t]);
}, [t]);
const apiInfoData = useMemo(() => { const apiInfoData = useMemo(() => {
return statusState?.status?.api_info || []; return statusState?.status?.api_info || [];
@@ -1263,38 +1262,41 @@ const Detail = (props) => {
{...CARD_PROPS} {...CARD_PROPS}
className="shadow-sm !rounded-2xl lg:col-span-1" className="shadow-sm !rounded-2xl lg:col-span-1"
title={ title={
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-2 w-full"> <div className="flex items-center justify-between w-full gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Gauge size={16} /> <Gauge size={16} />
{t('服务可用性')} {t('服务可用性')}
</div> </div>
<div className="flex items-center gap-3"> <IconButton
{/* 图例 */} icon={<IconRefresh />}
<div className="flex flex-wrap gap-3 text-xs"> onClick={loadUptimeData}
{uptimeLegendData.map((legend, index) => ( loading={uptimeLoading}
<div key={index} className="flex items-center gap-1"> size="small"
<div theme="borderless"
className="w-2 h-2 rounded-full" className="text-gray-500 hover:text-blue-500 hover:bg-blue-50 !rounded-full"
style={{ />
backgroundColor: legend.color === 'green' ? '#10b981' :
legend.color === 'red' ? '#ef4444' : '#8b9aa7'
}}
/>
<span className="text-gray-600">{legend.label}</span>
</div>
))}
</div>
<IconButton
icon={<IconRefresh />}
onClick={loadUptimeData}
loading={uptimeLoading}
size="small"
theme="borderless"
className="text-gray-500 hover:text-blue-500 hover:bg-blue-50 !rounded-full"
/>
</div>
</div> </div>
} }
footer={uptimeData.length > 0 ? (
<Card
shadows="always"
bordered={false}
className="!rounded-full backdrop-blur"
>
<div className="flex flex-wrap gap-3 text-xs justify-center">
{uptimeLegendData.map((legend, index) => (
<div key={index} className="flex items-center gap-1">
<div
className="w-2 h-2 rounded-full"
style={{ backgroundColor: legend.color }}
/>
<span className="text-gray-600">{legend.label}</span>
</div>
))}
</div>
</Card>
) : null}
footerStyle={uptimeData.length > 0 ? { marginTop: '-100px' } : undefined}
> >
<div className="card-content-container"> <div className="card-content-container">
<Spin spinning={uptimeLoading}> <Spin spinning={uptimeLoading}>