Some checks failed
CI Check / check (push) Has been cancelled
- 创建统一UI三层架构系统(基础层、颜色层、组合层) - 拆分Admin页面为独立Tab组件(MonitorTab、UsersTab、DepartmentsTab等) - 提取公共逻辑到Hooks(useToast、useDataFetch、useUserOperations等) - 提取工具函数(validators、formatters、api等) - 创建统一弹窗组件(Modal)和useModal Hook - 添加错误边界和统一状态组件 - 完善类型定义和可访问性支持 - 更新文档(优化记录、优化计划、更新日志)
73 lines
1.8 KiB
TypeScript
73 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import { Component, type ErrorInfo, type ReactNode } from 'react'
|
|
import { cardStyles, buttonStyles, cn } from '@/lib/ui-styles'
|
|
|
|
interface TabErrorBoundaryProps {
|
|
tabKey: string
|
|
children: ReactNode
|
|
onRetry?: () => Promise<void> | void
|
|
fallbackTitle?: string
|
|
fallbackDescription?: string
|
|
}
|
|
|
|
interface TabErrorBoundaryState {
|
|
hasError: boolean
|
|
error?: Error
|
|
}
|
|
|
|
export class TabErrorBoundary extends Component<TabErrorBoundaryProps, TabErrorBoundaryState> {
|
|
state: TabErrorBoundaryState = {
|
|
hasError: false,
|
|
error: undefined,
|
|
}
|
|
|
|
static getDerivedStateFromError(error: Error): TabErrorBoundaryState {
|
|
return { hasError: true, error }
|
|
}
|
|
|
|
componentDidCatch(error: Error, info: ErrorInfo) {
|
|
console.error(`Tab "${this.props.tabKey}" render error:`, error, info)
|
|
}
|
|
|
|
componentDidUpdate(prevProps: TabErrorBoundaryProps) {
|
|
if (prevProps.tabKey !== this.props.tabKey && this.state.hasError) {
|
|
this.reset()
|
|
}
|
|
}
|
|
|
|
reset = () => {
|
|
this.setState({ hasError: false, error: undefined })
|
|
}
|
|
|
|
handleRetry = async () => {
|
|
this.reset()
|
|
await this.props.onRetry?.()
|
|
}
|
|
|
|
render() {
|
|
if (this.state.hasError) {
|
|
return (
|
|
<div className={cn(cardStyles.base, 'text-center py-10')}>
|
|
<h3 className="text-lg font-semibold text-slate-900 dark:text-white">
|
|
{this.props.fallbackTitle || '模块加载失败'}
|
|
</h3>
|
|
<p className="text-sm text-slate-500 dark:text-slate-400 mt-2">
|
|
{this.props.fallbackDescription || '请重试或联系管理员'}
|
|
</p>
|
|
<div className="mt-6">
|
|
<button onClick={this.handleRetry} className={cn(buttonStyles.primary)}>
|
|
重试
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return this.props.children
|
|
}
|
|
}
|
|
|
|
export default TabErrorBoundary
|
|
|