- 合并 DEVELOPMENT.md 至 docs/development/README.md - 合并 CONTRIBUTING.md 至 docs/development/checker.md - 合并 build-release.md 至 release.md - 合并 testing-quality.md 内容至各专题文档 - 合并 status-model.md 至 expectations.md - 新增 docs/user/README.md 用户入口 - 简化 docs/README.md 文档路由 - 各专题文档新增适用场景和更新触发条件 - 更新 openspec/config.yaml 文档规则
131 lines
6.3 KiB
Markdown
131 lines
6.3 KiB
Markdown
# 前端开发
|
||
|
||
本文档说明 DiAL Dashboard 的 React、TDesign、TanStack Query、组件、样式和前端测试约定。
|
||
|
||
适用场景:修改 `src/web/`、前端共享类型使用方式、Dashboard 数据流、组件结构、样式规则或前端测试。
|
||
|
||
## 技术栈
|
||
|
||
| 层面 | 技术 | 用途 |
|
||
| ------ | ------------------------------------- | ---------------------------------------------- |
|
||
| 框架 | 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/`、`utils/` 和 hooks 中的纯逻辑。
|
||
- 组件测试使用 jsdom 和 `@testing-library/react`。
|
||
- 测试用户行为而非实现细节。
|
||
- 只 mock 系统边界,例如 `fetch`。
|
||
- 使用真实的 QueryClientProvider 包裹依赖 TanStack Query 的组件。
|
||
- 异步错误断言使用 helper 或显式 try/catch,避免依赖 Bun `expect(...).rejects` 与 `await-thenable` 规则的类型不匹配。
|
||
- 组件测试环境由 `tests/setup.ts` 和 `bunfig.toml` preload 提供,包含 ResizeObserver、IntersectionObserver、matchMedia、attachEvent 和 Recharts mock。
|
||
|
||
前端逻辑变更通常需要运行 `bun run check`。影响生产静态资源、前后端集成或构建流程时运行 `bun run verify`。
|
||
|
||
## 更新触发条件
|
||
|
||
修改前端技术栈、组件边界、数据流、样式规则、测试环境或前端验证方式时,必须更新本文档。
|