| import React from 'react'; |
| import { cn } from '@/lib/utils'; |
| import { Loader2, AlertCircle, CheckCircle2, XCircle, Inbox } from 'lucide-react'; |
|
|
| |
| |
| |
| |
|
|
| type PanelState = 'loading' | 'empty' | 'error' | 'success' | 'disabled'; |
|
|
| interface StatePanelProps { |
| |
| state: PanelState; |
| |
| title?: string; |
| |
| description?: string; |
| |
| error?: string; |
| |
| icon?: React.ReactNode; |
| |
| action?: React.ReactNode; |
| |
| className?: string; |
| } |
|
|
| |
| const stateIcons: Record<PanelState, React.ReactNode> = { |
| loading: <Loader2 className="w-5 h-5 text-console-text-muted animate-spin" />, |
| empty: <Inbox className="w-5 h-5 text-console-text-muted" />, |
| error: <XCircle className="w-5 h-5 text-console-status-error" />, |
| success: <CheckCircle2 className="w-5 h-5 text-console-status-enabled" />, |
| disabled: <AlertCircle className="w-5 h-5 text-console-text-muted" />, |
| }; |
|
|
| |
| const stateTexts: Record<PanelState, { title: string; description: string }> = { |
| loading: { title: '加载中', description: '正在获取数据...' }, |
| empty: { title: '暂无数据', description: '当前没有可显示的内容' }, |
| error: { title: '加载失败', description: '数据获取出错,请稍后重试' }, |
| success: { title: '操作成功', description: '已完成' }, |
| disabled: { title: '已禁用', description: '此功能当前不可用' }, |
| }; |
|
|
| |
| |
| |
| |
| export function StatePanel({ |
| state, |
| title, |
| description, |
| error, |
| icon, |
| action, |
| className, |
| }: StatePanelProps) { |
| const defaults = stateTexts[state]; |
| const displayTitle = title || defaults.title; |
| const displayDescription = error || description || defaults.description; |
|
|
| return ( |
| <div |
| className={cn( |
| 'flex flex-col items-center justify-center py-8 px-4 text-center', |
| className |
| )} |
| role="status" |
| aria-live="polite" |
| > |
| {/* 图标 */} |
| <div className="mb-3"> |
| {icon || stateIcons[state]} |
| </div> |
| |
| {/* 标题 */} |
| <h3 className="text-sm font-medium text-console-text-primary mb-1"> |
| {displayTitle} |
| </h3> |
| |
| {/* 描述 */} |
| <p className="text-xs text-console-text-secondary max-w-[280px]"> |
| {displayDescription} |
| </p> |
| |
| {/* 操作按钮 */} |
| {action && ( |
| <div className="mt-4"> |
| {action} |
| </div> |
| )} |
| </div> |
| ); |
| } |
|
|