docs: 重构文档体系
This commit is contained in:
117
docs/development/frontend.md
Normal file
117
docs/development/frontend.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# 前端开发
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 层面 | 技术 | 用途 |
|
||||
| ------ | ------------------------------------- | ---------------------------------------------- |
|
||||
| 框架 | React 19 | UI 组件开发 |
|
||||
| 构建 | Bun HTML import + Vite dev server | 开发服务与生产构建 |
|
||||
| 语言 | TypeScript 6 | 类型安全 |
|
||||
| UI 库 | TDesign React + tdesign-icons-react | UI 组件与图标 |
|
||||
| 数据层 | TanStack Query + React Query Devtools | 服务端状态管理与自动轮询 |
|
||||
| 图表 | Recharts | 拨测趋势图 |
|
||||
| 动画 | @number-flow/react | 倒计时数字滚动过渡 |
|
||||
| 路由 | 无 | 单页面 Dashboard,通过 Drawer/Tab 做页面内导航 |
|
||||
|
||||
不引入 React Router 或额外状态管理库。TanStack Query 承担服务端状态,组件内状态使用 `useState`。
|
||||
|
||||
## 组件树与数据流
|
||||
|
||||
```text
|
||||
main.tsx
|
||||
└── StrictMode
|
||||
└── ErrorBoundary
|
||||
└── QueryClientProvider
|
||||
├── App
|
||||
│ ├── useThemePreference()
|
||||
│ ├── useDashboard(refreshInterval)
|
||||
│ ├── SummaryCards
|
||||
│ └── TargetBoard
|
||||
│ └── TargetGroup[]
|
||||
│ └── PrimaryTable
|
||||
│ └── TargetDetailDrawer
|
||||
│ └── useTargetDetail()
|
||||
│ ├── OverviewTab
|
||||
│ └── HistoryTab
|
||||
└── ReactQueryDevtools
|
||||
```
|
||||
|
||||
## TanStack Query 规范
|
||||
|
||||
Query key 使用 structured array,排序为 scope -> id -> 参数。
|
||||
|
||||
```typescript
|
||||
const queryKeys = {
|
||||
dashboard: () => ["dashboard", "24h", 30] as const,
|
||||
meta: () => ["meta"] as const,
|
||||
metrics: (targetId: number, from: string, to: string, bucket: "auto" | MetricsBucket) =>
|
||||
["metrics", targetId, from, to, bucket] as const,
|
||||
history: (targetId: number, from: string, to: string, page: number) => ["history", targetId, from, to, page] as const,
|
||||
};
|
||||
```
|
||||
|
||||
全局面板级查询可持续刷新,详情级查询必须按 Drawer 状态和 Tab 状态条件启用。
|
||||
|
||||
## fetch 封装
|
||||
|
||||
统一使用 `fetch`,不引入 axios。错误抛异常,由 TanStack Query 的 `error` 状态承接。
|
||||
|
||||
```typescript
|
||||
async function fetchJson<T>(url: string): Promise<T> {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
```
|
||||
|
||||
## 组件开发规范
|
||||
|
||||
- 每个 React 组件一个 `.tsx` 文件,文件名使用 PascalCase。
|
||||
- 组件 props 定义为 `interface XxxProps`,紧邻组件函数声明。
|
||||
- 类型从 `../../shared/api` 导入,使用 `import type`。
|
||||
- 展示组件放在 `components/`,通过 props 接收数据,通过回调返回事件。
|
||||
- 容器逻辑放在 hooks 中,组件只做数据消费。
|
||||
- 列定义、排序器、筛选器、颜色阈值等常量放在 `constants/`。
|
||||
- 时间处理等纯函数放在 `utils/`。
|
||||
|
||||
## 现有组件
|
||||
|
||||
| 组件 | 用途 |
|
||||
| -------------------- | ----------------------------------------------------------------- |
|
||||
| `App` | 根组件,Layout + HeadMenu 骨架、主题模式、刷新控制、Skeleton 加载 |
|
||||
| `ErrorBoundary` | React 错误边界 |
|
||||
| `SummaryCards` | 总览统计卡片 |
|
||||
| `TargetBoard` | 按分组渲染目标表格列表 |
|
||||
| `TargetGroup` | 单个分组 Card + PrimaryTable |
|
||||
| `TargetDetailDrawer` | 目标详情抽屉 |
|
||||
| `OverviewTab` | 目标详情概览 |
|
||||
| `HistoryTab` | 目标历史记录表格和分页 |
|
||||
| `TrendChart` | 趋势折线图 |
|
||||
| `StatusDot` | 圆形状态指示点 |
|
||||
| `StatusBar` | 最近采样状态条 |
|
||||
| `RefreshCountdown` | Header 刷新倒计时和手动刷新按钮 |
|
||||
|
||||
## 样式规范
|
||||
|
||||
前端基于 TDesign React 构建 UI,样式开发优先级:
|
||||
|
||||
1. TDesign 组件
|
||||
2. TDesign 组件 props
|
||||
3. TDesign CSS tokens(`--td-*`)
|
||||
4. `styles.css` CSS 类
|
||||
5. 自行开发组件
|
||||
|
||||
红线:
|
||||
|
||||
- 严禁在组件中使用 `style` 属性内联调整样式。
|
||||
- 严禁通过 CSS 覆盖 TDesign 组件内部类名。
|
||||
- 严禁使用 `!important`。
|
||||
- 颜色统一使用 TDesign CSS tokens,不使用硬编码色值。
|
||||
|
||||
## 前端测试
|
||||
|
||||
- 测试目录为 `tests/web/`,结构对应 `src/web/`。
|
||||
- 重点测试 `constants/` 中的纯函数。
|
||||
- 组件测试使用 jsdom 和 `@testing-library/react`。
|
||||
- 测试用户行为而非实现细节。
|
||||
- 只 mock 系统边界,例如 `fetch`。
|
||||
Reference in New Issue
Block a user