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,13 +1,30 @@
import { Alert, Loading, Typography } from "tdesign-react";
import type { SkeletonProps } from "tdesign-react";
import { useEffect, useState } from "react";
import { Alert, Layout, Menu, Skeleton, Typography } from "tdesign-react";
import { SummaryCards } from "./components/SummaryCards";
import { TargetBoard } from "./components/TargetBoard";
import { TargetDetailDrawer } from "./components/TargetDetailDrawer";
import { useDashboard } from "./hooks/use-queries";
import { DASHBOARD_REFRESH_INTERVAL_MS, useDashboard } from "./hooks/use-queries";
import { useTargetDetail } from "./hooks/use-target-detail";
const { Content, Header } = Layout;
const DASHBOARD_SKELETON_ROW_COL: SkeletonProps["rowCol"] = [
[{ height: "112px", type: "rect", width: "100%" }],
[{ height: "56px", type: "rect", width: "100%" }],
[{ height: "320px", type: "rect", width: "100%" }],
];
export function App() {
const { data: dashboard, error: dashboardError, isLoading: dashboardLoading } = useDashboard();
const [now, setNow] = useState(() => new Date());
const {
data: dashboard,
dataUpdatedAt: dashboardUpdatedAt,
error: dashboardError,
isFetching: dashboardFetching,
isLoading: dashboardLoading,
} = useDashboard();
const {
closeDrawer,
handlePageChange,
@@ -21,25 +38,55 @@ export function App() {
timeFrom,
timeTo,
} = useTargetDetail();
const nextRefreshSeconds =
dashboardUpdatedAt > 0
? Math.max(0, Math.ceil((dashboardUpdatedAt + DASHBOARD_REFRESH_INTERVAL_MS - now.getTime()) / 1000))
: null;
const refreshText =
dashboardUpdatedAt > 0
? dashboardFetching && !dashboardLoading
? "刷新中..."
: `下一次刷新:${nextRefreshSeconds}`
: "等待首次刷新";
useEffect(() => {
const timer = window.setInterval(() => setNow(new Date()), 1000);
return () => window.clearInterval(timer);
}, []);
return (
<main className="dashboard">
<header className="dashboard-header">
<Typography.Title level="h1">DiAL</Typography.Title>
<Typography.Text theme="secondary"></Typography.Text>
</header>
{dashboardError && <Alert closeBtn message={`请求失败: ${dashboardError.message}`} theme="error" />}
{dashboardLoading ? (
<Loading />
) : (
<>
<SummaryCards summary={dashboard?.summary ?? null} />
<TargetBoard onTargetClick={openDrawer} targets={dashboard?.targets ?? []} />
</>
)}
<Layout className="dashboard">
<Header>
<Menu.HeadMenu
logo={
<span className="dashboard-brand">
<span className="dashboard-logo">DiAL</span>
<span className="dashboard-subtitle"></span>
</span>
}
operations={
<span className="dashboard-refresh-status">
<Typography.Text className="dashboard-refresh-text" theme="secondary">
{refreshText}
</Typography.Text>
</span>
}
/>
</Header>
<Content>
<div className="dashboard-content">
{dashboardError && <Alert closeBtn message={`请求失败: ${dashboardError.message}`} theme="error" />}
{dashboardLoading ? (
<Skeleton animation="gradient" rowCol={DASHBOARD_SKELETON_ROW_COL} />
) : (
<>
<SummaryCards summary={dashboard?.summary ?? null} />
<TargetBoard onTargetClick={openDrawer} targets={dashboard?.targets ?? []} />
</>
)}
</div>
</Content>
<TargetDetailDrawer
historyData={historyData}
historyLoading={historyLoading}
@@ -53,6 +100,6 @@ export function App() {
timeFrom={timeFrom}
timeTo={timeTo}
/>
</main>
</Layout>
);
}