refactor: 枚举移入Models目录,命名空间更新为Rainbow.Entity.Models
大石头 authored at 2026-07-02 12:54:58
1.88 KiB
RainbowBridge
import { Component, type ReactNode, type ErrorInfo } from 'react'
import { Icon } from '@/components/common/Icon'

interface ErrorBoundaryProps {
  children: ReactNode
  fallback?: ReactNode
  onError?: (error: Error, info: ErrorInfo) => void
}

interface ErrorBoundaryState {
  hasError: Boolean
  error: Error | null
}

/**
 * 通用错误边界。捕获子组件渲染错误,防止整页白屏。
 */
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props)
    this.state = { hasError: false, error: null }
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error }
  }

  componentDidCatch(error: Error, info: ErrorInfo): void {
    console.error('[ErrorBoundary] 捕获到渲染错误:', error, info.componentStack)
    this.props.onError?.(error, info)
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: null })
  }

  render() {
    if (this.state.hasError) {
      if (this.props.fallback) return this.props.fallback

      return (
        <div className="flex flex-col items-center justify-center gap-3 p-8 text-center">
          <Icon name="error_outline" size="xl" className="text-[var(--color-text-tertiary)]" />
          <div>
            <p className="text-sm font-medium text-[var(--color-text-secondary)]">页面加载失败</p>
            <p className="text-xs text-[var(--color-text-tertiary)] mt-1">
              {this.state.error?.message ?? '未知错误'}
            </p>
          </div>
          <button
            onClick={this.handleRetry}
            className="px-4 py-1.5 text-xs font-medium rounded-lg bg-[color:var(--color-brand-500)] text-white hover:bg-[color:var(--color-brand-600)] transition-colors"
          >
            重试
          </button>
        </div>
      )
    }

    return this.props.children
  }
}