light-sentry-sdk/docs/05-admin-dashboard.md

917 lines
43 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 管理后台与可视化设计文档
## 一、设计原则
### 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 Bar64px
│ ┌──────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ 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: <MainLayout />,
children: [
{ index: true, element: <Navigate to="/overview" replace /> },
{ 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: <Navigate to="rules" replace /> },
{ 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: <ProjectList /> },
{ path: '*', element: <NotFound /> },
];
```
### 7.3 状态管理Zustand
**为什么用 Zustand 而不是 Redux**
- 比 Redux 简单太多,没有 reducer、action、dispatch 那些概念
- 体积小(~1KB性能好
- TypeScript 支持好
- 支持 middlewarepersist、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<AppState>((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 (
<ConfigProvider
theme={{
algorithm: theme === 'dark'
? antdTheme.darkAlgorithm
: antdTheme.defaultAlgorithm,
token: {
colorPrimary: '#0090f9',
borderRadius: 6,
},
}}
>
<Router />
</ConfigProvider>
);
}
```
**自定义暗色主题色板**(贴合 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<HTMLDivElement>(null);
const chartInstance = useRef<echarts.ECharts | null>(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 <div ref={chartRef} style={{ height }} className={className} />;
}
```
### 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 操作反馈
- 重要操作(删除、标记已解决)有确认弹窗
- 成功操作顶部弹 toast3 秒自动消失
- 操作失败显示错误原因,可重试
---
## 九、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**
- 完整的错误管理工作流
- 性能深入分析(瀑布图、资源时序)
- 用户会话追踪