1
0

refactor: 前端视觉重构 — Layout/HeadMenu 骨架、SummaryCards 合并、Card 分组、Drawer 概览重设计

This commit is contained in:
2026-05-14 15:51:39 +08:00
parent 1c5cfafda6
commit c61a4a6091
20 changed files with 530 additions and 427 deletions

View File

@@ -1,11 +1,19 @@
import { Col, Descriptions, Divider, Row, Skeleton, Space, Statistic } from "tdesign-react";
import type { ReactNode } from "react";
import { Card, Col, Descriptions, Divider, Row, Skeleton, Space, Statistic, Typography } from "tdesign-react";
import type { TargetMetricsResponse, TargetStatus } from "../../shared/api";
import { formatDurationUnit } from "../utils/time";
import { StatusDonut } from "./StatusDonut";
import { TrendChart } from "./TrendChart";
interface OverviewStatItemProps {
color?: string;
suffix?: ReactNode;
title: string;
value: number;
}
interface OverviewTabProps {
metricsData: null | TargetMetricsResponse;
metricsLoading: boolean;
@@ -20,70 +28,6 @@ export function OverviewTab({ metricsData, metricsLoading, target }: OverviewTab
return (
<Space className="full-width" direction="vertical" size={16}>
<Divider align="left"></Divider>
{metricsLoading ? (
<Skeleton animation="gradient" />
) : stats ? (
<Space className="full-width" direction="vertical" size={16}>
<Row gutter={16}>
<Col span={3}>
<Statistic color="green" suffix="%" title="可用率" value={stats.availability} />
</Col>
<Col span={3}>
<Statistic
suffix={stats.avgDurationMs === null ? "" : "ms"}
title="平均延迟"
value={stats.avgDurationMs ?? 0}
/>
</Col>
<Col span={3}>
<Statistic
suffix={stats.p95DurationMs === null ? "" : "ms"}
title="P95 延迟"
value={stats.p95DurationMs ?? 0}
/>
</Col>
<Col span={3}>
<Statistic color="blue" title="检查总数" value={stats.totalChecks} />
</Col>
</Row>
<Row gutter={16}>
<Col span={3}>
<Statistic suffix={mttr.suffix} title="MTTR" value={mttr.value} />
</Col>
<Col span={3}>
<Statistic suffix={longestOutage.suffix} title="最长故障" value={longestOutage.value} />
</Col>
<Col span={3}>
<Statistic color="red" suffix="次" title="故障次数" value={stats.incidentCount} />
</Col>
<Col span={3}>
<Statistic color="green" suffix="次" title="连续正常" value={currentUpStreak} />
</Col>
</Row>
</Space>
) : (
<div className="trend-empty"></div>
)}
<Divider align="left"></Divider>
{metricsLoading ? (
<Skeleton animation="gradient" />
) : metricsData ? (
<TrendChart data={metricsData.trend} />
) : (
<div className="trend-empty"></div>
)}
<Divider align="left"></Divider>
{metricsLoading ? (
<Skeleton animation="gradient" />
) : stats ? (
<StatusDonut down={stats.downChecks} up={stats.upChecks} />
) : (
<div className="trend-empty"></div>
)}
<Divider align="left"></Divider>
<Descriptions
items={[
@@ -96,6 +40,68 @@ export function OverviewTab({ metricsData, metricsLoading, target }: OverviewTab
{ content: target.latestCheck?.statusDetail ?? "-", label: "状态详情" },
]}
/>
<Divider align="left"></Divider>
{metricsLoading ? (
<Skeleton animation="gradient" />
) : stats ? (
<Row gutter={[16, 16]}>
<Col span={3}>
<OverviewStatItem color="green" suffix="%" title="可用率" value={stats.availability} />
</Col>
<Col span={3}>
<OverviewStatItem
suffix={stats.avgDurationMs === null ? "" : "ms"}
title="平均延迟"
value={stats.avgDurationMs ?? 0}
/>
</Col>
<Col span={3}>
<OverviewStatItem
suffix={stats.p95DurationMs === null ? "" : "ms"}
title="P95 延迟"
value={stats.p95DurationMs ?? 0}
/>
</Col>
<Col span={3}>
<OverviewStatItem color="blue" title="检查总数" value={stats.totalChecks} />
</Col>
<Col span={3}>
<OverviewStatItem suffix={mttr.suffix} title="MTTR" value={mttr.value} />
</Col>
<Col span={3}>
<OverviewStatItem suffix={longestOutage.suffix} title="最长故障" value={longestOutage.value} />
</Col>
<Col span={3}>
<OverviewStatItem color="red" suffix="次" title="故障次数" value={stats.incidentCount} />
</Col>
<Col span={3}>
<OverviewStatItem color="green" suffix="次" title="连续正常" value={currentUpStreak} />
</Col>
</Row>
) : (
<div className="trend-empty"></div>
)}
<Divider align="left"></Divider>
{metricsLoading ? (
<Skeleton animation="gradient" />
) : metricsData ? (
<TrendChart data={metricsData.trend} />
) : (
<div className="trend-empty"></div>
)}
</Space>
);
}
function OverviewStatItem({ color, suffix, title, value }: OverviewStatItemProps) {
return (
<Card bordered={false} className="overview-stat-card" size="small">
<div className="overview-stat-item">
<Typography.Text theme="secondary">{title}</Typography.Text>
<Statistic className="overview-stat-value" color={color} suffix={suffix} value={value} />
</div>
</Card>
);
}