Files
novalon-website/src/components/ui/error-boundary.tsx
T
张翔 e78df62cd1 feat(ui): 重构核心 UI 组件库,新增 shadcn/ui 组件
- 重构 Button、Card、Badge、Input、Textarea 等基础组件
- 新增 Accordion、Alert、Dialog、Dropdown、Form 等 shadcn/ui 组件
- 新增 AnimatedCounter、StatsShowcase、MetricCard 等数据展示组件
- 新增 ScrollReveal 滚动动画组件
- 重构 Toast 通知系统与 Tooltip 提示组件
- 更新设计令牌系统,对齐新品牌视觉
2026-07-07 06:52:38 +08:00

70 lines
2.3 KiB
TypeScript
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.
'use client';
import { Component, ReactNode } from 'react';
import { trackError } from '@/lib/analytics';
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
trackError('react_error', error.message, true);
}
render() {
if (this.state.hasError) {
return this.props.fallback || (
<div className="flex items-center justify-center min-h-100 p-8" role="alert" aria-live="assertive">
<div className="text-center max-w-md">
<div className="w-16 h-16 bg-red-100 rounded-full flex items-center justify-center mx-auto mb-4" aria-hidden="true">
<svg
className="w-8 h-8 text-red-500"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</svg>
</div>
<h2 className="text-2xl font-bold text-[var(--color-text-primary)] mb-4"></h2>
<p className="text-[var(--color-text-placeholder)] mb-6">
</p>
<button
onClick={() => this.setState({ hasError: false, error: undefined })}
className="px-6 py-2.5 bg-[var(--color-brand)] text-white rounded-lg hover:bg-[var(--color-brand-hover)] transition-colors focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] focus:ring-offset-2"
aria-label="重试"
>
</button>
</div>
</div>
);
}
return this.props.children;
}
}