1
0

refactor: 前端架构重构 — hook拆分、组件拆分、类型筛选器动态化、Meta API

- 后端新增 GET /api/meta 端点(checkerRegistry.supportedTypes)及 MetaResponse 类型
- 前端 hook 拆分为 use-queries.ts(全局查询+useMeta)和 use-target-detail.ts(Drawer状态)
- TargetDetailDrawer 拆分为 OverviewTab + HistoryTab + history-table-columns + stats.ts
- 类型筛选器由 meta API 动态驱动,删除 target-type-display 静态映射
- 列定义改为工厂函数 createTargetTableColumns(checkerTypes),TargetGroup 新增 columns prop
- 修复 StatusDonut key、StatusBar maxSlots prop、TrendChart 移除 loading prop
- 补充 utils/time、utils/stats、动态列工厂测试,删除旧 mapping 测试
- 同步 delta specs 到主 specs,归档 frontend-architecture-refactor change
This commit is contained in:
2026-05-13 20:55:42 +08:00
parent a62007083d
commit 31aeee6d60
41 changed files with 713 additions and 902 deletions

View File

@@ -3,7 +3,13 @@ import { mkdir } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import type { HealthResponse, HistoryResponse, SummaryResponse, TargetStatus } from "../../src/shared/api";
import type {
HealthResponse,
HistoryResponse,
MetaResponse,
SummaryResponse,
TargetStatus,
} from "../../src/shared/api";
import { createFetchHandler, type StaticAssets } from "../../src/server/app";
import { checkerRegistry } from "../../src/server/checker/runner";
@@ -151,6 +157,32 @@ describe("API 路由", () => {
expect(tB.latestCheck).toBeNull();
});
test("/api/meta 返回 checker 类型列表", async () => {
const response = fetchHandler(new Request("http://localhost/api/meta"));
const body = (await response.json()) as MetaResponse;
expect(response.status).toBe(200);
expect(body.checkerTypes).toEqual(checkerRegistry.supportedTypes);
expect(body.checkerTypes).toContain("http");
expect(body.checkerTypes).toContain("command");
});
test("/api/meta HEAD 请求返回 headers 无 body", async () => {
const response = fetchHandler(new Request("http://localhost/api/meta", { method: "HEAD" }));
const body = await response.text();
expect(response.status).toBe(200);
expect(response.headers.get("content-type")).toContain("application/json");
expect(body).toBe("");
});
test("/api/meta 不支持的 method 返回 405", () => {
const response = fetchHandler(new Request("http://localhost/api/meta", { method: "POST" }));
expect(response.status).toBe(405);
expect(response.headers.get("allow")).toBe("GET, HEAD");
});
test("/api/targets/:id/history 返回历史记录", async () => {
const targets = store.getTargets();
const from = "2024-01-01T00:00:00.000Z";