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

43 KiB
Raw Permalink Blame History

管理后台与可视化设计文档

一、设计原则

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 切换主题
  • ProComponentsProTable、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 字体与间距

字体栈

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嵌套路由 + 懒加载:

// 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 等)
// 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
// 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

// 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 配置主题:

// 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 风格):

{
  colorBgLayout: '#0d1117',     // 页面背景
  colorBgContainer: '#161b22',  // 卡片背景
  colorBgElevated: '#21262d',   // 悬浮背景
  colorBorder: '#30363d',       // 边框
  colorText: '#e6edf3',         // 主文字
  colorTextSecondary: '#8b949e',// 次文字
  colorTextTertiary: '#6e7681', // 弱文字
}

7.7 图表封装

基于 ECharts 封装通用图表组件,自动适配主题和容器大小:

// 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 构建与部署

开发环境

pnpm dev          # 启动开发服务器
pnpm build        # 生产构建
pnpm preview      # 预览构建结果
pnpm lint         # ESLint 检查
pnpm type-check   # TypeScript 类型检查

部署方案

  • 构建产物:dist/ 目录
  • Nginx 直接托管静态文件
  • API 请求通过 Nginx 反向代理到后端
  • 和现有 public/manage/ 共存,新前端走 /manage/ 路径
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 是项目列表页,只有最基础的 CRUD 功能。

10.2 版本规划

v1.1(下一个版本)

  • 改造成侧边栏 + 内容区的布局
  • 新增概览页(核心指标 + 错误趋势)
  • 新增错误列表页(从聚合表读)
  • 项目选择器移到顶部

v1.2

  • 错误详情页
  • 性能分析页
  • 告警规则管理

v2.0

  • 完整的错误管理工作流
  • 性能深入分析(瀑布图、资源时序)
  • 用户会话追踪