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

@@ -67,15 +67,17 @@ src/
styles.css 全局样式与自定义 CSS 变量
components/ UI 组件(见下方组件清单)
constants/ 常量与纯函数
target-type-display.ts 类型名称映射
target-table-columns.tsx 表格列定义
history-table-columns.tsx 历史记录表格列定义
target-table-columns.tsx 目标表格列定义工厂
target-table-filters.ts 表格筛选器
target-table-sorters.ts 表格排序器
color-threshold.ts 可用率颜色阈值函数
hooks/ TanStack Query 数据层
useTargetDetail.ts 集成轮询/条件查询的组合 hook
use-queries.ts 全局面板查询 hooksummary/targets/meta
use-target-detail.ts 目标详情 Drawer 状态与条件查询 hook
utils/ 前端工具函数
time.ts 时间处理subtractHours
stats.ts 趋势统计计算computeTrendStats
scripts/ 开发、构建、schema 生成和 smoke test 脚本
tests/ Bun test 测试(结构镜像 src 目录)
openspec/ OpenSpec 变更与规格文档
@@ -358,14 +360,11 @@ TcpChecker implements Checker
| `engine.ts` | 按 `target.type` 从 registry 取对应 checker 执行 `execute()` |
| `store.ts` | 按 `target.type` 从 registry 取对应 checker 执行 `serialize()` |
注意:自动适配指上述中间层不需要新增 `switch/case` 或类型分支;开发者仍需按后续步骤更新前端展示常量、配置示例、文档和测试。
注意:自动适配指上述中间层不需要新增 `switch/case` 或类型分支;开发者仍需按后续步骤更新配置示例、文档和测试。
#### 1.7.7 步骤六:更新前端展示
#### 1.7.7 步骤六:确认前端类型展示
| 文件 | 修改内容 |
| ------------------------------------------- | ------------------------------------------------------------ |
| `src/web/constants/target-type-display.ts` | 在 `TARGET_TYPE_DISPLAY` 中添加 `"tcp": "TCP"` |
| `src/web/constants/target-table-filters.ts` | 在 `typeFilter.list` 中添加 `{ label: "TCP", value: "tcp" }` |
前端通过 `/api/meta` 获取 `checkerRegistry.supportedTypes` 并动态生成类型筛选器,类型列和详情标题直接显示 `target.type` 原始文本。新增 checker 注册后无需更新前端类型映射或筛选常量。
#### 1.7.8 步骤七:编写测试
@@ -400,8 +399,6 @@ TcpChecker implements Checker
□ src/server/checker/runner/tcp/expect.ts — 专用断言(如需要)
□ src/server/checker/runner/tcp/index.ts — 模块入口re-export
□ src/server/checker/runner/index.ts — 注册(一行导入 + 一个数组元素)
□ src/web/constants/target-type-display.ts — 前端类型标签
□ src/web/constants/target-table-filters.ts — 前端类型筛选
□ tests/ — 契约 + 校验 + resolve + execute + 注册 测试
□ probes.example.yaml — 配置示例
□ bun run schema + bun run schema:check — Schema 导出同步
@@ -544,26 +541,29 @@ main.tsx
│ │ └── useSummary() ─── GET /api/summary8s 轮询)
│ └── TargetBoard目标列表
│ ├── useTargets() ─── GET /api/targets8s 轮询)
│ ├── useMeta() ────── GET /api/meta应用生命周期内缓存
│ └── TargetGroup[](按 group 字段分组)
│ └── PrimaryTable ← TARGET_TABLE_COLUMNS列定义排序/筛选/渲染)
│ └── PrimaryTable ← createTargetTableColumns(checkerTypes)
│ └── TargetDetailDrawer目标详情抽屉
│ └── useTargetDetail() ── 按需发起 trend + history 查询
│ ├── Tab: 概览 → Statistic + TrendChart + StatusDonut + Descriptions
│ └── Tab: 记录 → PrimaryTable分页历史记录
│ ├── OverviewTab → Statistic + TrendChart + StatusDonut + Descriptions
│ └── HistoryTab → PrimaryTable分页历史记录
└── ReactQueryDevtools开发工具仅开发环境
```
**数据层架构**
```
hooks/useTargetDetail.ts唯一的数据层入口
├── queryKeys结构化 query key,确保缓存粒度精确
hooks/use-queries.ts全局面板级查询
├── queryKeyssummary/targets/meta 结构化 query key
├── useSummary() → /api/summary8s 自动轮询)
├── useTargets() → /api/targets8s 自动轮询)
└── useTargetDetail()(组合 hook管理 Drawer 全部状态
├── 内部复用 useTargets() 的缓存来查找 selectedTarget
├── useQuery(/api/targets/:id/trend)条件查询enabled 仅当 Drawer 打开且时间范围有效
└── useQuery(/api/targets/:id/history)(条件查询:含分页)
└── useMeta() → /api/metastaleTime: Infinity
hooks/use-target-detail.tsDrawer 状态与详情级条件查询
├── 内部复用 useTargets() 的缓存来查找 selectedTarget
├── useQuery(/api/targets/:id/trend)条件查询enabled 仅当 Drawer 打开且时间范围有效)
└── useQuery(/api/targets/:id/history)(条件查询:含分页)
```
### 2.3 TanStack Query 数据层
@@ -574,6 +574,7 @@ hooks/useTargetDetail.ts唯一的数据层入口
const queryKeys = {
summary: () => ["summary"] as const,
targets: () => ["targets"] as const,
meta: () => ["meta"] as const,
trend: (targetId: number, from: string, to: string) => ["trend", targetId, from, to] as const,
history: (targetId: number, from: string, to: string, page: number) => ["history", targetId, from, to, page] as const,
};
@@ -668,7 +669,9 @@ export function TargetGroup({ name, targets, onTargetClick }: TargetGroupProps)
| `SummaryCards` | `components/SummaryCards.tsx` | 总览统计卡片(全部/正常/异常) |
| `TargetBoard` | `components/TargetBoard.tsx` | 按分组渲染目标表格列表 |
| `TargetGroup` | `components/TargetGroup.tsx` | 单个分组标题 + PrimaryTable |
| `TargetDetailDrawer` | `components/TargetDetailDrawer.tsx` | 目标详情抽屉(概览/记录 Tab |
| `TargetDetailDrawer` | `components/TargetDetailDrawer.tsx` | 目标详情抽屉壳、时间选择和 Tab 切换 |
| `OverviewTab` | `components/OverviewTab.tsx` | 目标详情概览(统计/趋势/状态分布/信息) |
| `HistoryTab` | `components/HistoryTab.tsx` | 目标历史记录表格和分页 |
| `TrendChart` | `components/TrendChart.tsx` | Recharts 双轴折线图(耗时/可用率) |
| `StatusDonut` | `components/StatusDonut.tsx` | Recharts 环状图UP/DOWN 分布) |
| `StatusDot` | `components/StatusDot.tsx` | 圆形状态指示点(绿/红) |
@@ -682,7 +685,7 @@ export function TargetGroup({ name, targets, onTargetClick }: TargetGroupProps)
1. **确认数据需求**:是已有 API 数据还是需要新端点?
- 如有新端点,先在 `src/server/routes/` 添加,参考 [1.3 新增路由步骤](#13-api-路由开发)
- 如有新字段,更新 `src/shared/api.ts` 类型定义
2. **实现 hooks**:在 `src/web/hooks/useTargetDetail.ts` 中新增 `useQuery`(写好 `queryKey``enabled` 条件)
2. **实现 hooks**全局查询放`src/web/hooks/use-queries.ts`;目标详情条件查询放在 `src/web/hooks/use-target-detail.ts`(写好 `queryKey``enabled` 条件)
3. **编写组件**:在 `src/web/components/` 创建组件文件
-`TargetDetailDrawer.tsx` 中新增 `<Tabs.TabPanel>` 引用
4. **编写常量**:如有列定义/排序器/筛选器,放在 `src/web/constants/`