pref: ErrorPage 功能增强
ErrorPage 新增功能: - 浮动动画效果 (keyframes) - 可配置错误原因列表 (reasons prop) - 技术详情折叠面板 (techDetails prop) - 可选搜索功能 (search prop) - 更丰富的导航选项
This commit is contained in:
335
src/components/ErrorPage/README.md
Normal file
335
src/components/ErrorPage/README.md
Normal file
@@ -0,0 +1,335 @@
|
||||
# ErrorPage 通用错误页面组件
|
||||
|
||||
通用错误页面组件,用于显示加载失败、网络错误、404 等异常状态。
|
||||
|
||||
**设计风格**:黑色背景 (`#1A202C`) + 金色边框 (`#D4A574`)
|
||||
|
||||
## 效果预览
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ ╭──────────╮ │
|
||||
│ │ ⚠️ │ (金色圆形) │
|
||||
│ ╰──────────╯ │
|
||||
│ │
|
||||
│ 事件走丢了 │
|
||||
│ ID: ZXY-101 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────┐ │
|
||||
│ │ 抱歉,我们找不到您请求的事件... │ │
|
||||
│ │ │ │
|
||||
│ │ 🔍 事件ID输入错误 │ │
|
||||
│ │ 请检查URL中的事件ID是否正确 │ │
|
||||
│ │ │ │
|
||||
│ │ 🗑️ 该事件已被删除或下架 │ │
|
||||
│ │ 该事件可能因过期而被移除 │ │
|
||||
│ │ │ │
|
||||
│ │ 🔄 系统暂时无法访问该事件 │ │
|
||||
│ │ 请稍后重试或联系技术支持 │ │
|
||||
│ │ │ │
|
||||
│ │ [查看技术信息 ▼] │ │
|
||||
│ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ [返回] [重试] │
|
||||
│ │
|
||||
│ 点击右下角联系客服 │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 基础用法
|
||||
|
||||
```tsx
|
||||
import ErrorPage from '@/components/ErrorPage';
|
||||
|
||||
// 最简单的用法 - 使用所有默认配置
|
||||
<ErrorPage />
|
||||
|
||||
// 自定义标题和描述
|
||||
<ErrorPage
|
||||
title="事件走丢了"
|
||||
description="抱歉,我们找不到您请求的事件"
|
||||
/>
|
||||
```
|
||||
|
||||
### 完整配置示例
|
||||
|
||||
```tsx
|
||||
<ErrorPage
|
||||
// 基础配置
|
||||
title="事件走丢了"
|
||||
subtitle="ID: ZXY-101"
|
||||
description="抱歉,我们找不到您请求的事件,这可能是因为:"
|
||||
|
||||
// 错误原因列表
|
||||
reasons={[
|
||||
{
|
||||
icon: '🔍',
|
||||
title: '事件ID输入错误',
|
||||
description: '请检查URL中的事件ID是否正确',
|
||||
},
|
||||
{
|
||||
icon: '🗑️',
|
||||
title: '该事件已被删除或下架',
|
||||
description: '该事件可能因过期或内容调整而被移除',
|
||||
},
|
||||
{
|
||||
icon: '🔄',
|
||||
title: '系统暂时无法访问该事件',
|
||||
description: '请稍后重试或联系技术支持',
|
||||
},
|
||||
]}
|
||||
|
||||
// 技术详情(可展开)
|
||||
techDetails={{
|
||||
requestUrl: 'http://localhost:3000/event-detail?id=ZXY-101',
|
||||
errorType: '404 - Event Not Found',
|
||||
errorMessage: 'Unexpected token...',
|
||||
timestamp: '2024-01-15 14:30:22',
|
||||
relatedId: '101',
|
||||
}}
|
||||
|
||||
// 操作按钮
|
||||
showBack
|
||||
showRetry
|
||||
onRetry={() => window.location.reload()}
|
||||
showHome
|
||||
homePath="/community"
|
||||
|
||||
// 网络状态检查
|
||||
checkOffline
|
||||
|
||||
// 错误上报
|
||||
onErrorReport={(info) => {
|
||||
analytics.track('error_page_view', info);
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
### 基础配置
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `title` | `string` | `'加载失败'` | 错误标题 |
|
||||
| `subtitle` | `string` | - | 错误副标题(如显示错误 ID) |
|
||||
| `description` | `string` | `'我们无法找到您请求的内容,这可能是因为:'` | 错误描述信息 |
|
||||
| `detail` | `string` | - | 详细信息值(与 subtitle 二选一) |
|
||||
| `detailLabel` | `string` | `'ID'` | 详细信息标签 |
|
||||
|
||||
### 错误原因配置
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `reasons` | `ErrorReasonItem[]` | 默认 3 条 | 错误原因列表 |
|
||||
|
||||
**ErrorReasonItem 结构:**
|
||||
|
||||
```typescript
|
||||
interface ErrorReasonItem {
|
||||
icon: string | React.ReactNode; // 图标(emoji 或组件)
|
||||
title: string; // 原因标题
|
||||
description: string; // 原因描述
|
||||
}
|
||||
```
|
||||
|
||||
**默认错误原因:**
|
||||
|
||||
```typescript
|
||||
[
|
||||
{ icon: '🔍', title: 'ID 可能输入错误', description: '请检查 URL 中的 ID 是否正确' },
|
||||
{ icon: '🗑️', title: '内容可能已被删除', description: '该内容可能因过期或调整而被下架' },
|
||||
{ icon: '🔄', title: '系统暂时无法访问', description: '请稍后重试或联系技术支持' },
|
||||
]
|
||||
```
|
||||
|
||||
### 技术详情配置
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `techDetails` | `TechDetails` | - | 技术详情(可展开查看) |
|
||||
|
||||
**TechDetails 结构:**
|
||||
|
||||
```typescript
|
||||
interface TechDetails {
|
||||
requestUrl?: string; // 请求 URL
|
||||
errorType?: string; // 错误类型
|
||||
errorMessage?: string; // 错误信息
|
||||
timestamp?: string; // 时间戳
|
||||
relatedId?: string; // 相关 ID
|
||||
customFields?: Record<string, string>; // 自定义字段
|
||||
}
|
||||
```
|
||||
|
||||
### 操作按钮配置
|
||||
|
||||
#### 快捷配置
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `showBack` | `boolean` | `false` | 是否显示返回按钮 |
|
||||
| `onBack` | `() => void` | `history.back()` | 返回回调 |
|
||||
| `showRetry` | `boolean` | `false` | 是否显示重试按钮 |
|
||||
| `onRetry` | `() => void` | - | 重试回调 |
|
||||
| `showHome` | `boolean` | `false` | 是否显示返回首页按钮 |
|
||||
| `homePath` | `string` | `'/'` | 首页路径 |
|
||||
|
||||
#### 自定义按钮
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `actions` | `ActionButton[]` | - | 自定义操作按钮列表(覆盖快捷配置) |
|
||||
|
||||
**ActionButton 结构:**
|
||||
|
||||
```typescript
|
||||
interface ActionButton {
|
||||
label: string; // 按钮文本
|
||||
icon?: string; // 按钮图标(可选)
|
||||
variant?: 'primary' | 'secondary' | 'outline'; // 按钮类型
|
||||
onClick?: () => void; // 点击回调
|
||||
href?: string; // 跳转链接(与 onClick 二选一)
|
||||
}
|
||||
```
|
||||
|
||||
**示例:**
|
||||
|
||||
```tsx
|
||||
<ErrorPage
|
||||
actions={[
|
||||
{ label: '刷新页面', variant: 'primary', onClick: () => location.reload() },
|
||||
{ label: '返回列表', variant: 'outline', href: '/events' },
|
||||
]}
|
||||
/>
|
||||
```
|
||||
|
||||
### 布局配置
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `fullScreen` | `boolean` | `true` | 是否全屏显示 |
|
||||
| `maxWidth` | `string` | `'500px'` | 最大宽度 |
|
||||
|
||||
### 功能增强
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `checkOffline` | `boolean` | `true` | 是否检查网络状态并显示离线提示 |
|
||||
| `enableBuiltInReport` | `boolean` | `true` | 是否启用内置 PostHog 错误上报 |
|
||||
| `onErrorReport` | `(errorInfo: Record<string, unknown>) => void` | - | 自定义错误上报回调(与内置上报同时生效) |
|
||||
|
||||
**内置错误上报**:
|
||||
|
||||
组件默认会自动上报错误到 PostHog,上报事件名为 `error_page_view`,包含以下数据:
|
||||
|
||||
```typescript
|
||||
{
|
||||
error_title: string; // 错误标题
|
||||
error_detail: string; // 详细信息(如事件ID)
|
||||
error_type: string; // 错误类型(如 "404 - Event Not Found")
|
||||
error_message: string; // 错误信息
|
||||
page_url: string; // 当前页面 URL
|
||||
referrer: string; // 来源页面
|
||||
user_agent: string; // 用户代理
|
||||
event_id: string; // 相关 ID
|
||||
timestamp: string; // 时间戳(自动添加)
|
||||
}
|
||||
```
|
||||
|
||||
**禁用内置上报:**
|
||||
|
||||
```tsx
|
||||
<ErrorPage enableBuiltInReport={false} />
|
||||
```
|
||||
|
||||
**自定义上报回调示例:**
|
||||
|
||||
```tsx
|
||||
<ErrorPage
|
||||
onErrorReport={(errorInfo) => {
|
||||
// 自定义上报逻辑(与内置 PostHog 上报同时生效)
|
||||
customAnalytics.track('custom_error_event', errorInfo);
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## 场景示例
|
||||
|
||||
### 1. 事件详情 404 页面
|
||||
|
||||
```tsx
|
||||
<ErrorPage
|
||||
title="事件走丢了"
|
||||
subtitle={`ID: ${eventId}`}
|
||||
description="抱歉,我们找不到您请求的事件,这可能是因为:"
|
||||
reasons={[
|
||||
{ icon: '🔍', title: '事件ID输入错误', description: '请检查URL中的事件ID是否正确' },
|
||||
{ icon: '🗑️', title: '该事件已被删除或下架', description: '该事件可能因过期或内容调整而被移除' },
|
||||
{ icon: '🔄', title: '系统暂时无法访问该事件', description: '请稍后重试或联系技术支持' },
|
||||
]}
|
||||
techDetails={{
|
||||
requestUrl: window.location.href,
|
||||
errorType: '404 - Event Not Found',
|
||||
errorMessage: error.message,
|
||||
timestamp: new Date().toISOString(),
|
||||
relatedId: eventId,
|
||||
}}
|
||||
showRetry
|
||||
onRetry={() => window.location.reload()}
|
||||
showBack
|
||||
showHome
|
||||
homePath="/community"
|
||||
/>
|
||||
```
|
||||
|
||||
### 2. 网络错误页面
|
||||
|
||||
```tsx
|
||||
<ErrorPage
|
||||
title="网络连接失败"
|
||||
description="无法连接到服务器,请检查网络后重试"
|
||||
reasons={[
|
||||
{ icon: '📶', title: '网络连接中断', description: '请检查您的网络连接是否正常' },
|
||||
{ icon: '🔧', title: '服务器维护中', description: '服务器可能正在进行维护,请稍后重试' },
|
||||
]}
|
||||
showRetry
|
||||
onRetry={() => window.location.reload()}
|
||||
/>
|
||||
```
|
||||
|
||||
### 3. 简洁模式(无原因列表)
|
||||
|
||||
```tsx
|
||||
<ErrorPage
|
||||
title="加载失败"
|
||||
description="数据加载失败,请重试"
|
||||
reasons={[]} // 不显示原因列表
|
||||
fullScreen={false}
|
||||
maxWidth="400px"
|
||||
showRetry
|
||||
onRetry={refetch}
|
||||
/>
|
||||
```
|
||||
|
||||
## 类型导出
|
||||
|
||||
组件导出以下 TypeScript 类型,方便外部使用:
|
||||
|
||||
```typescript
|
||||
import ErrorPage, {
|
||||
ErrorPageProps,
|
||||
ErrorReasonItem,
|
||||
ActionButton,
|
||||
TechDetails,
|
||||
} from '@/components/ErrorPage';
|
||||
```
|
||||
|
||||
## 设计说明
|
||||
|
||||
- **配色**:黑色背景 (`#1A202C`) + 金色边框/按钮 (`#D4A574`)
|
||||
- **图标**:金色圆形背景 (50px) + 黑色感叹号
|
||||
- **布局**:居中卡片式布局,最大宽度 500px
|
||||
- **底部提示**:"点击右下角联系客服"(纯文本,无链接)
|
||||
Reference in New Issue
Block a user