# 管理后台与可视化设计文档
## 一、设计原则
### 1.1 核心理念
**克制、高效、数据为先**
- 不做花哨的动效,所有设计都服务于「快速定位问题」
- 深色主题为主,长时间盯着不累眼
- 信息分层明确,重要的信息一眼看到,次要的信息收起来
- 操作路径短:3 次点击以内能到达任何核心页面
### 1.2 技术选型
| 层级 | 技术 | 说明 |
|------|------|------|
| 框架 | React 18 | 生态成熟,社区活跃 |
| 构建 | Vite 5 | 快,开发体验好 |
| 语言 | TypeScript | 类型安全,减少 bug |
| UI 库 | Ant Design 5 | 后台管理组件最全,深色主题好 |
| 路由 | React Router v6 | 官方推荐,功能完整 |
| 状态管理 | Zustand | 轻量,比 Redux 简单太多 |
| 数据请求 | TanStack Query (React Query) | 缓存、重发、分页都有了 |
| 图表 | ECharts 5 | 功能强大,国内用得多 |
| HTTP 客户端 | Axios | 拦截器、取消请求都方便 |
| 样式 | CSS Modules + Less | 按需定制主题 |
| 代码规范 | ESLint + Prettier | 统一代码风格 |
### 1.3 为什么选 Ant Design
- **组件最丰富**:表格、表单、弹窗、树形...后台需要的都有
- **深色主题好**:AntD 5 原生支持 ConfigProvider 切换主题
- **ProComponents**:ProTable、ProForm 等高级组件,开发效率翻倍
- **生态成熟**:遇到问题搜一下就有答案
- **设计语言统一**:有自己的设计规范,不用从零定
### 1.3 页面清单
| 页面 | 路径 | 优先级 | 说明 |
|------|------|--------|------|
| 项目列表 | `/manage/` | P0 | 项目管理(已有) |
| 项目概览 | `#/overview` | P0 | 项目总览、关键指标 |
| 错误列表 | `#/errors` | P0 | 错误 Issue 列表、详情 |
| 错误详情 | `#/errors/:id` | P0 | 单个错误的详细分析 |
| 性能分析 | `#/performance` | P1 | Web Vitals、性能趋势 |
| 网络分析 | `#/network` | P2 | 接口请求统计 |
| 行为分析 | `#/behavior` | P2 | PV、用户行为 |
| 告警中心 | `#/alerts` | P1 | 告警规则、告警历史 |
| 日志查询 | `#/logs` | P1 | Loki 原始日志查询 |
| 接入指南 | `#/integration` | P0 | SDK 接入文档(已有) |
| 项目设置 | `#/settings` | P1 | 项目配置、成员、采样率 |
---
## 二、设计系统
### 2.1 配色系统
**主色调**:蓝色系(专业、可信赖)
| 用途 | 颜色 | 色值 |
|------|------|------|
| 品牌主色 | 亮蓝 | `#0090f9` |
| 品牌主色(悬停) | 蓝 | `#1da1f2` |
| 成功 | 绿 | `#26a641` |
| 警告 | 黄 | `#e9c46a` |
| 错误 | 红 | `#e63946` |
| 信息 | 紫 | `#a855f7` |
**中性色(深色主题)**:
| 用途 | 色值 | 说明 |
|------|------|------|
| 背景(最深) | `#0d1117` | 页面底色 |
| 背景(卡片) | `#161b22` | 卡片、弹窗 |
| 背景(悬浮) | `#21262d` | hover、选中 |
| 边框 | `#30363d` | 分割线、边框 |
| 文字(主) | `#e6edf3` | 标题、正文 |
| 文字(次) | `#8b949e` | 辅助说明、时间 |
| 文字(弱) | `#6e7681` | 占位符、disabled |
### 2.2 字体与间距
**字体栈**:
```css
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
```
**字号阶梯**:
| 用途 | 大小 | 字重 |
|------|------|------|
| 页面大标题 | 24px | 600 |
| 区块标题 | 18px | 600 |
| 卡片标题 | 16px | 600 |
| 正文 | 14px | 400 |
| 辅助文字 | 12px | 400 |
**间距阶梯**(4px 基准):
`4px / 8px / 12px / 16px / 20px / 24px / 32px / 48px`
### 2.3 圆角与阴影
| 元素 | 圆角 | 阴影 |
|------|------|------|
| 按钮 | 6px | 无 |
| 输入框 | 6px | 无 |
| 卡片 | 8px | 无(用边框区分) |
| 弹窗 | 12px | `0 8px 24px rgba(0,0,0,0.4)` |
| 下拉菜单 | 8px | `0 4px 12px rgba(0,0,0,0.3)` |
---
## 三、整体布局
### 3.1 布局结构
```
┌─────────────────────────────────────────────────────────────────┐
│ Top Bar(64px) │
│ ┌──────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Logo │ │ 项目选择器 ▼ │ │ 🔔 👤 设置 │ │
│ └──────┘ └──────────────┘ └─────────────┘ │
├────────┬────────────────────────────────────────────────────────┤
│ │ │
│ Side │ Content Area │
│ Nav │ ┌──────────────────────────────────────────────────┐ │
│(64px │ │ Page Header(标题 + 操作 + 筛选) │ │
│ 展开 │ └──────────────────────────────────────────────────┘ │
│ 220px)│ ┌──────────────────────────────────────────────────┐ │
│ │ │ Metric Cards(指标卡片行) │ │
│ │ └──────────────────────────────────────────────────┘ │
│ │ ┌──────────────────────────────────────────────────┐ │
│ │ │ Charts / Tables(主内容区) │ │
│ │ │ │ │
│ │ │ │ │
│ │ └──────────────────────────────────────────────────┘ │
│ │ │
└────────┴────────────────────────────────────────────────────────┘
```
### 3.2 侧边栏(可折叠)
**收起态(64px)**:只显示图标
```
📊 ← 概览
🐛 ← 错误
⚡ ← 性能
🌐 ← 网络
📈 ← 看板
🔔 ← 告警
⚙️ ← 设置
```
**展开态(220px)**:图标 + 文字 + 角标
```
📊 概览
🐛 错误 12 ← 未解决错误数
⚡ 性能 3 ← 有性能告警
🌐 网络
📈 看板
🔔 告警 5 ← 未读告警
⚙️ 设置
```
### 3.3 顶部栏
```
┌─────────────────────────────────────────────────────────────┐
│ ◀▶ 🪲 Light-Sentry [▼ 前端项目 - my-app ] 🔔 ⚙️ │
└─────────────────────────────────────────────────────────────┘
```
- 左侧:折叠按钮 + Logo + 产品名
- 中间:项目选择器(下拉,可搜索)
- 右侧:告警铃(有未读红点) + 设置
### 3.4 页面头(每个页面都有)
```
┌─────────────────────────────────────────────────────────────┐
│ 错误 Issues [时间范围: 24h ▼] [搜索] │
│ 12 个未解决 · 3 个今日新增 [导出] [刷新] │
└─────────────────────────────────────────────────────────────┘
```
---
## 四、核心页面详细设计
### 4.1 概览页(Overview)
**定位**:一屏看完项目健康状况,有问题快速跳转到对应页面
```
┌─────────────────────────────────────────────────────────────────┐
│ 概览 [24h ▼] [环境: 全部 ▼] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 错误数 │ │ 错误率 │ │ 影响用户│ │ LCP P95 │ │ CLS P95 │ │
│ │ 128 │ │ 2.3% │ │ 1,234 │ │ 3.2s │ │ 0.15 │ │
│ │ ↑15% │ │ ↑0.8% │ │ ↑12% │ │ 🔴 差 │ │ 🟡 中 │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ ┌──────────────────────────┐ ┌───────────────────────────────┐ │
│ │ 错误趋势(24h) │ │ Top 5 错误 │ │
│ │ ╱╲ │ │ 1. TypeError: Cannot read... │ │
│ │ ╱ ╲ ╱╲ │ │ 2. AxiosError: 500 Inter... │ │
│ │ ╱╲╱ ╲╱ ╲ │ │ 3. ReferenceError: x is ... │ │
│ │ │ │ 4. ChunkLoadError: Loadin... │ │
│ │ │ │ 5. TypeError: Cannot set... │ │
│ └──────────────────────────┘ └───────────────────────────────┘ │
│ │
│ ┌──────────────────────────┐ ┌───────────────────────────────┐ │
│ │ 性能趋势(LCP/FID/CLS) │ │ 新错误(今日新增) │ │
│ │ 🟢 LCP 2.5s │ │ • TypeError: Cannot read... │ │
│ │ 🟡 FID 120ms │ │ • AxiosError: Network Er... │ │
│ │ 🟢 CLS 0.08 │ │ • ReferenceError: foo i... │ │
│ │ │ │ │ │
│ └──────────────────────────┘ └───────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 实时错误流(最近 5 分钟) │ │
│ │ 14:32:15 TypeError: Cannot read property 'foo' │ │
│ │ 14:32:10 AxiosError: Request failed with 500 │ │
│ │ 14:32:05 ReferenceError: x is not defined │ │
│ │ ... │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**设计要点**:
- 5 个核心指标卡片放在最上面,一眼看完
- 指标卡片底部的小数字是「同比昨日」,红涨绿跌
- 左图右表,趋势 + Top 排行
- 底部实时流,让你感知系统状态
### 4.2 错误列表页(Errors)
**定位**:浏览和管理错误 Issue,找到要处理的问题
```
┌─────────────────────────────────────────────────────────────────┐
│ 错误 Issues [24h ▼] [🔍 搜索错误消息] │
│ 128 个错误 · 12 个未解决 · 3 个今日新增 [状态: 全部 ▼] [级别: ▼] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───┬─────────────────────┬──────┬───────┬───────┬──────────┐ │
│ │ ✓ │ 错误消息 │ 级别 │ 次数 │ 用户 │ 最后出现 │ │
│ ├───┼─────────────────────┼──────┼───────┼───────┼──────────┤ │
│ │ 🔴│Cannot read property│error │ 456 │ 123 │ 2 分钟前 │ │
│ │ │ 'foo' of undefined│ │ │ │ │ │
│ ├───┼─────────────────────┼──────┼───────┼───────┼──────────┤ │
│ │ 🔴│AxiosError: Request │error │ 234 │ 89 │ 5 分钟前 │ │
│ │ │ failed with 500 │ │ │ │ │ │
│ ├───┼─────────────────────┼──────┼───────┼───────┼──────────┤ │
│ │ 🟡│ReferenceError: x is│warning│ 123 │ 45 │ 12 分钟前 │ │
│ │ │ not defined │ │ │ │ │ │
│ └───┴─────────────────────┴──────┴───────┴───────┴──────────┘ │
│ │
│ ◀ 1 2 3 4 ... 12 ▶ 每页 20 条 ▼ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**筛选器**:
- 时间范围(15m / 1h / 6h / 24h / 7d / 30d / 自定义)
- 状态(全部 / 未解决 / 已解决 / 已忽略)
- 级别(全部 / fatal / error / warning / info)
- 搜索(错误消息、指纹、文件路径)
- 环境
- 版本(release)
**列表交互**:
- 点击行 → 进入错误详情
- 行前 checkbox → 批量操作(标记已解决、忽略)
- hover 行 → 显示快捷操作(查看、已解决、忽略)
### 4.3 错误详情页
**定位**:深入分析单个错误,定位根因
```
┌─────────────────────────────────────────────────────────────────┐
│ ← 返回列表 [标记已解决] [忽略] [分配给 ▼] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 🔴 TypeError: Cannot read property 'foo' of undefined │
│ Uncaught exception · active · 来自浏览器 JS │
│ │
│ 📊 概览 📝 堆栈 📋 Breadcrumbs 👥 用户 🌐 分布 ⏱️ 趋势 │
│ ───── │
│ │
│ ┌──────────────┬──────────────┬──────────────┬──────────────┐ │
│ │ 总次数 │ 影响用户 │ 首次出现 │ 最后出现 │ │
│ │ 456 │ 123 │ 3 天前 │ 2 分钟前 │ │
│ └──────────────┴──────────────┴──────────────┴──────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 发生趋势(7 天) │ │
│ │ ╱╲ │ │
│ │ ╱ ╲ ╱╲ │ │
│ │ ╱╲╱ ╲╱ ╲ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 堆栈跟踪 │ │
│ │ 📄 app.js:123 onClick │ │
│ │ 📄 utils.js:45 handleClick │ │
│ │ 📄 index.js:8 main │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 最近出现(最新 5 条) │ │
│ │ 14:32:15 user_123 Chrome 120 macOS 点击按钮时 │ │
│ │ 14:31:45 user_456 Safari 17 iOS 加载页面时 │ │
│ │ ... │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**Tab 内容**:
- **概览**:核心数据 + 趋势图 + 最近出现
- **堆栈**:完整堆栈跟踪,可折叠,点击跳源码(如果配置了 sourcemap)
- **Breadcrumbs**:用户操作路径,时间线展示
- **用户**:受影响的用户列表
- **分布**:浏览器、OS、设备、地区分布
- **趋势**:更长时间的趋势图
### 4.4 性能分析页
**定位**:看页面性能好不好,哪里慢
```
┌─────────────────────────────────────────────────────────────────┐
│ 性能分析 [24h ▼] [页面: 全部 ▼] │
│ Web Vitals 指标 [浏览器: 全部 ▼] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│ │ LCP │ │ FID │ │ CLS │ │ FCP │ │
│ │ 3.2s 🔴 │ │ 120ms 🟡 │ │ 0.15 🟢 │ │ 1.8s 🟡 │ │
│ │ P95: 4.5s │ │ P95: 200ms │ │ P95: 0.25 │ │ P95: 2.5s│ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 性能趋势(P50 / P75 / P95 / P99) │ │
│ │ ╭────────────────────────────────────────────────────╮ │ │
│ │ │ ▲ P99 ── P95 ─ ─ P75 ┄ ┄ P50 │ │ │
│ │ │ │╲ │ │ │
│ │ │ │ ╲──────╮ │ │ │
│ │ │ │ ╲╱╲ │ │ │
│ │ │ │ │ │ │
│ │ │ ╰───────────────────────────────────────────────╯ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 页面性能排行 [按 LCP 排序 ▼] │ │
│ ├─────────────────────┬──────┬──────┬──────┬──────┬───────┤ │
│ │ 页面 │ LCP │ FID │ CLS │ 样本 │ 评级 │ │
│ ├─────────────────────┼──────┼──────┼──────┼──────┼───────┤ │
│ │ /home │ 2.8s │ 80ms │ 0.10 │ 1.2k │ 🟢 良 │ │
│ │ /product/:id │ 4.2s │ 150ms│ 0.20 │ 800 │ 🔴 差 │ │
│ │ /checkout │ 3.5s │ 120ms│ 0.15 │ 500 │ 🟡 中 │ │
│ │ ... │ │ │ │ │ │ │
│ └─────────────────────┴──────┴──────┴──────┴──────┴───────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 4.5 告警中心
**定位**:配置告警规则,查看告警历史
```
┌─────────────────────────────────────────────────────────────────┐
│ 告警中心 │
│ ┌─────────┐ │
│ │ 告警规则 │ 告警历史 │
│ └─────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [+ 新建告警规则] │
│ │
│ ┌───┬─────────────────────┬──────────┬───────┬────────┬─────┐ │
│ │ ✓ │ 规则名称 │ 类型 │ 级别 │ 状态 │ 操作 │ │
│ ├───┼─────────────────────┼──────────┼───────┼────────┼─────┤ │
│ │ 🔔│ 错误数量突增 │ 突增告警 │ 严重 │ ✅ 启用 │ ... │ │
│ ├───┼─────────────────────┼──────────┼───────┼────────┼─────┤ │
│ │ 🔔│ 新错误出现 │ 新错误 │ 警告 │ ✅ 启用 │ ... │ │
│ ├───┼─────────────────────┼──────────┼───────┼────────┼─────┤ │
│ │ 🔔│ LCP 超过 4s │ 阈值告警 │ 警告 │ ✅ 启用 │ ... │ │
│ └───┴─────────────────────┴──────────┴───────┴────────┴─────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## 五、组件设计
### 5.1 指标卡片
```
┌─────────────────┐
│ 错误总数 │ ← 标题(小字、灰色)
│ 128 │ ← 数值(大字、粗体)
│ ↑ 15% vs 昨日 │ ← 趋势(红涨绿跌)
│ ╱╲ │ ← 迷你趋势图(可选)
│ ╱ ╲ │
└─────────────────┘
```
**变体**:
- 标准:数字 + 趋势
- 带评级:数字 + 颜色评级(性能指标用)
- 极简:只有数字
### 5.2 状态标签
| 状态 | 颜色 | 示例 |
|------|------|------|
| Active(未解决) | 红底白字 | `active` |
| Resolved(已解决) | 绿底白字 | `resolved` |
| Ignored(已忽略) | 灰底灰字 | `ignored` |
| Firing(告警中) | 红底白字 | `FIRING` |
| Resolved(已恢复) | 绿底白字 | `RESOLVED` |
### 5.3 错误级别标记
| 级别 | 颜色 |
|------|------|
| Fatal | 🔴 深红 |
| Error | 🔴 红 |
| Warning | 🟡 黄 |
| Info | 🔵 蓝 |
| Debug | ⚪ 灰 |
### 5.4 性能评级
| 评级 | 颜色 | LCP | FID | CLS |
|------|------|-----|-----|-----|
| Good 🟢 | 绿 | < 2.5s | < 100ms | < 0.1 |
| Needs Improvement 🟡 | 黄 | 2.5-4s | 100-300ms | 0.1-0.25 |
| Poor 🔴 | 红 | > 4s | > 300ms | > 0.25 |
---
## 六、图表设计
### 6.1 图表库选型
| 库 | 体积 | 功能 | 适合场景 |
|----|------|------|----------|
| Chart.js | ~60KB gzip | 基础图表够用 | 轻量、简单 |
| ECharts | ~150KB gzip | 功能强大 | 复杂图表、交互多 |
| uPlot | ~15KB gzip | 时序图表 | 极致轻量、性能好 |
**推荐方案**:
- 默认用 Chart.js(够用、轻量、生态好)
- 性能监控页面用 ECharts(需要更复杂的交互)
- 可按需加载,首屏只加载必要的
### 6.2 图表类型
| 图表 | 用途 | 页面 |
|------|------|------|
| 折线图 | 错误趋势、性能趋势 | 概览、错误、性能 |
| 柱状图 | Top N 排行、分布 | 错误、性能 |
| 饼图 / 环形图 | 占比、分布 | 概览、错误 |
| 面积图 | 堆叠趋势 | 性能 |
| 热力图 | 时间段分布 | 错误 |
### 6.3 与 Grafana 的关系
**管理后台解决的问题**:
- 错误 Issue 管理(状态、分配、标记)
- 项目配置和管理
- 告警规则配置
- 更友好的错误详情展示
**Grafana 解决的问题**:
- 灵活的自定义仪表盘
- 复杂的数据探索
- 多种数据源联合查询
- 告警(可复用 Grafana Alerting)
**分工原则**:
- 常用功能做进管理后台(开箱即用)
- 高级分析用 Grafana(灵活强大)
- 管理后台提供一键跳转到 Grafana 的链接
---
## 七、前端架构
### 7.1 目录结构
```
frontend/ # 前端工程(独立目录)
├── public/
│ └── favicon.ico
├── src/
│ ├── assets/ # 静态资源
│ │ ├── images/
│ │ └── icons/
│ ├── components/ # 通用组件
│ │ ├── layout/ # 布局组件
│ │ │ ├── MainLayout.tsx # 主布局(侧边栏+顶栏+内容)
│ │ │ ├── Sidebar.tsx # 侧边栏
│ │ │ ├── Header.tsx # 顶部栏
│ │ │ └── PageHeader.tsx # 页面头
│ │ ├── chart/ # 图表组件
│ │ │ ├── LineChart.tsx # 折线图
│ │ │ ├── BarChart.tsx # 柱状图
│ │ │ └── PieChart.tsx # 饼图
│ │ ├── metrics/ # 指标组件
│ │ │ └── MetricCard.tsx # 指标卡片
│ │ └── common/ # 其他通用组件
│ │ ├── StatusTag.tsx # 状态标签
│ │ └── CopyButton.tsx # 复制按钮
│ ├── pages/ # 页面
│ │ ├── overview/ # 概览页
│ │ │ └── index.tsx
│ │ ├── errors/ # 错误管理
│ │ │ ├── List.tsx # 错误列表
│ │ │ └── Detail.tsx # 错误详情
│ │ ├── performance/ # 性能分析
│ │ │ └── index.tsx
│ │ ├── network/ # 网络分析
│ │ │ └── index.tsx
│ │ ├── alerts/ # 告警中心
│ │ │ ├── Rules.tsx # 告警规则
│ │ │ └── History.tsx # 告警历史
│ │ ├── logs/ # 日志查询
│ │ │ └── index.tsx
│ │ ├── settings/ # 项目设置
│ │ │ └── index.tsx
│ │ ├── projects/ # 项目管理
│ │ │ └── List.tsx
│ │ └── integration/ # 接入指南
│ │ └── index.tsx
│ ├── store/ # 状态管理 (Zustand)
│ │ ├── index.ts # 导出
│ │ ├── useAppStore.ts # 全局状态(主题、侧边栏等)
│ │ └── useProjectStore.ts # 当前项目状态
│ ├── services/ # API 服务
│ │ ├── request.ts # Axios 封装
│ │ ├── project.ts # 项目相关 API
│ │ ├── error.ts # 错误相关 API
│ │ ├── performance.ts # 性能相关 API
│ │ └── alert.ts # 告警相关 API
│ ├── hooks/ # 自定义 Hooks
│ │ ├── useProject.ts # 当前项目 hook
│ │ ├── useTimeRange.ts # 时间范围 hook
│ │ └── useChartTheme.ts # 图表主题 hook
│ ├── router/ # 路由配置
│ │ ├── index.tsx # 路由入口
│ │ └── routes.ts # 路由表
│ ├── utils/ # 工具函数
│ │ ├── format.ts # 格式化(时间、数字等)
│ │ ├── date.ts # 日期工具
│ │ └── storage.ts # 本地存储
│ ├── types/ # TypeScript 类型定义
│ │ ├── api.ts # API 类型
│ │ ├── error.ts # 错误相关类型
│ │ ├── performance.ts # 性能相关类型
│ │ └── common.ts # 通用类型
│ ├── styles/ # 全局样式
│ │ ├── global.less
│ │ └── variables.less
│ ├── App.tsx # 根组件
│ └── main.tsx # 入口文件
├── .eslintrc.js # ESLint 配置
├── .prettierrc # Prettier 配置
├── tsconfig.json # TypeScript 配置
├── vite.config.ts # Vite 配置
└── package.json
```
### 7.2 路由设计
使用 React Router v6,嵌套路由 + 懒加载:
```typescript
// router/routes.ts
const routes = [
{
path: '/',
element: ,
children: [
{ index: true, element: },
{ path: 'overview', lazy: () => import('@/pages/overview') },
{
path: 'errors',
children: [
{ index: true, lazy: () => import('@/pages/errors/List') },
{ path: ':id', lazy: () => import('@/pages/errors/Detail') },
],
},
{ path: 'performance', lazy: () => import('@/pages/performance') },
{ path: 'network', lazy: () => import('@/pages/network') },
{
path: 'alerts',
children: [
{ index: true, element: },
{ path: 'rules', lazy: () => import('@/pages/alerts/Rules') },
{ path: 'history', lazy: () => import('@/pages/alerts/History') },
],
},
{ path: 'logs', lazy: () => import('@/pages/logs') },
{ path: 'settings', lazy: () => import('@/pages/settings') },
{ path: 'integration', lazy: () => import('@/pages/integration') },
],
},
{ path: '/projects', element: },
{ path: '*', element: },
];
```
### 7.3 状态管理(Zustand)
**为什么用 Zustand 而不是 Redux?**
- 比 Redux 简单太多,没有 reducer、action、dispatch 那些概念
- 体积小(~1KB),性能好
- TypeScript 支持好
- 支持 middleware(persist、devtools 等)
```typescript
// store/useAppStore.ts
import { create } from 'zustand';
interface AppState {
theme: 'dark' | 'light';
sidebarCollapsed: boolean;
currentProject: Project | null;
toggleTheme: () => void;
toggleSidebar: () => void;
setCurrentProject: (project: Project) => void;
}
export const useAppStore = create((set) => ({
theme: 'dark',
sidebarCollapsed: false,
currentProject: null,
toggleTheme: () => set((s) => ({ theme: s.theme === 'dark' ? 'light' : 'dark' })),
toggleSidebar: () => set((s) => ({ sidebarCollapsed: !s.sidebarCollapsed })),
setCurrentProject: (project) => set({ currentProject: project }),
}));
```
### 7.4 数据请求(TanStack Query)
**为什么用 TanStack Query?**
- 自动缓存,相同请求不会重复发
- 后台自动刷新
- 分页、无限滚动都有封装
- 乐观更新、重试策略
- 和 Zustand 互补,不用把 API 数据放全局 store
```typescript
// hooks/useErrors.ts
import { useQuery } from '@tanstack/react-query';
import { getErrorList } from '@/services/error';
export function useErrorList(params: ErrorListParams) {
return useQuery({
queryKey: ['errors', params],
queryFn: () => getErrorList(params),
keepPreviousData: true,
staleTime: 30_000, // 30秒内认为是新鲜的
});
}
```
### 7.5 请求封装(Axios)
```typescript
// services/request.ts
import axios from 'axios';
import { message } from 'antd';
const request = axios.create({
baseURL: '/api',
timeout: 15000,
});
// 请求拦截器:加 token
request.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 响应拦截器:统一处理错误
request.interceptors.response.use(
(res) => res.data,
(err) => {
const status = err.response?.status;
const message = err.response?.data?.message || err.message;
if (status === 401) {
// 登录过期,跳登录页
} else {
message.error(message);
}
return Promise.reject(err);
}
);
export default request;
```
### 7.6 主题配置(Ant Design 5 深色主题)
Ant Design 5 用 CSS-in-JS,通过 ConfigProvider 配置主题:
```typescript
// App.tsx
import { ConfigProvider, theme as antdTheme } from 'antd';
import { useAppStore } from '@/store';
function App() {
const { theme } = useAppStore();
return (
);
}
```
**自定义暗色主题色板**(贴合 GitHub Dark 风格):
```typescript
{
colorBgLayout: '#0d1117', // 页面背景
colorBgContainer: '#161b22', // 卡片背景
colorBgElevated: '#21262d', // 悬浮背景
colorBorder: '#30363d', // 边框
colorText: '#e6edf3', // 主文字
colorTextSecondary: '#8b949e',// 次文字
colorTextTertiary: '#6e7681', // 弱文字
}
```
### 7.7 图表封装
基于 ECharts 封装通用图表组件,自动适配主题和容器大小:
```typescript
// components/chart/BaseChart.tsx
import { useEffect, useRef } from 'react';
import * as echarts from 'echarts';
import { useAppStore } from '@/store';
interface BaseChartProps {
option: echarts.EChartsOption;
height?: number | string;
className?: string;
}
export function BaseChart({ option, height = 300, className }: BaseChartProps) {
const chartRef = useRef(null);
const chartInstance = useRef(null);
const { theme } = useAppStore();
useEffect(() => {
if (!chartRef.current) return;
chartInstance.current = echarts.init(
chartRef.current,
theme === 'dark' ? 'dark' : null
);
const resizeObserver = new ResizeObserver(() => {
chartInstance.current?.resize();
});
resizeObserver.observe(chartRef.current);
return () => {
resizeObserver.disconnect();
chartInstance.current?.dispose();
};
}, [theme]);
useEffect(() => {
chartInstance.current?.setOption(option, true);
}, [option]);
return ;
}
```
### 7.8 构建与部署
**开发环境**:
```bash
pnpm dev # 启动开发服务器
pnpm build # 生产构建
pnpm preview # 预览构建结果
pnpm lint # ESLint 检查
pnpm type-check # TypeScript 类型检查
```
**部署方案**:
- 构建产物:`dist/` 目录
- Nginx 直接托管静态文件
- API 请求通过 Nginx 反向代理到后端
- 和现有 `public/manage/` 共存,新前端走 `/manage/` 路径
```nginx
location /manage/ {
try_files $uri $uri/ /manage/index.html;
root /path/to/frontend/dist;
}
```
---
## 八、交互设计原则
### 8.1 快速导航
- 全局搜索:`⌘K` 唤起,可搜项目、错误、页面
- 面包屑:永远知道自己在哪
- 相关跳转:错误详情里可跳转到对应页面的性能分析
### 8.2 数据加载
- 骨架屏:数据加载中显示骨架,不跳
- 增量加载:列表滚动加载
- 实时刷新:可开/关,默认 30 秒自动刷新
### 8.3 操作反馈
- 重要操作(删除、标记已解决)有确认弹窗
- 成功操作顶部弹 toast,3 秒自动消失
- 操作失败显示错误原因,可重试
---
## 九、API 设计
### 9.1 统计 API
```
# 概览数据
GET /api/projects/{id}/overview?time_range=24h
# 错误趋势
GET /api/projects/{id}/errors/trend?time_range=24h&interval=1h
# 错误列表
GET /api/projects/{id}/errors?page=1&page_size=20&level=error&status=active
# 错误详情
GET /api/projects/{id}/errors/{fingerprint}
# 性能指标
GET /api/projects/{id}/performance/metrics?time_range=24h&metric=lcp
# 告警规则
GET /api/projects/{id}/alerts/rules
POST /api/projects/{id}/alerts/rules
PUT /api/projects/{id}/alerts/rules/{rule_id}
DELETE /api/projects/{id}/alerts/rules/{rule_id}
# 告警历史
GET /api/projects/{id}/alerts/history?page=1&page_size=20
```
---
## 十、演进路线
### 10.1 当前状态
现有的 [index.html](file:///Users/weidingjian/Desktop/work/ai/light-sentry/public/manage/index.html) 是项目列表页,只有最基础的 CRUD 功能。
### 10.2 版本规划
**v1.1(下一个版本)**:
- 改造成侧边栏 + 内容区的布局
- 新增概览页(核心指标 + 错误趋势)
- 新增错误列表页(从聚合表读)
- 项目选择器移到顶部
**v1.2**:
- 错误详情页
- 性能分析页
- 告警规则管理
**v2.0**:
- 完整的错误管理工作流
- 性能深入分析(瀑布图、资源时序)
- 用户会话追踪