import 'package:flutter/material.dart'; class AppErrorState extends StatelessWidget { final String title; final String? message; final IconData icon; final VoidCallback? onRetry; final Widget? action; final bool compact; final bool panel; final Color? foregroundColor; const AppErrorState({ super.key, this.title = '加载失败', this.message, this.icon = Icons.error_outline, this.onRetry, this.action, this.compact = false, this.panel = false, this.foregroundColor, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final child = ConstrainedBox( constraints: BoxConstraints(maxWidth: compact ? 420 : 520), child: Padding( padding: EdgeInsets.all(compact ? 16 : 28), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: compact ? 36 : 48, height: compact ? 36 : 48, decoration: BoxDecoration( color: theme.colorScheme.errorContainer.withValues(alpha: 0.72), borderRadius: BorderRadius.circular(8), ), child: Icon( icon, size: compact ? 20 : 26, color: theme.colorScheme.onErrorContainer, ), ), SizedBox(height: compact ? 10 : 14), Text( title, textAlign: TextAlign.center, style: (compact ? theme.textTheme.titleSmall : theme.textTheme.titleMedium) ?.copyWith( color: foregroundColor, fontWeight: FontWeight.w600, ), ), if (message != null && message!.isNotEmpty) ...[ const SizedBox(height: 8), Text( message!, textAlign: TextAlign.center, style: theme.textTheme.bodyMedium?.copyWith( color: foregroundColor?.withValues(alpha: 0.72) ?? theme.colorScheme.onSurfaceVariant, height: 1.4, ), ), ], if (action != null || onRetry != null) ...[ SizedBox(height: compact ? 14 : 18), action ?? _RetryButton(onPressed: onRetry!), ], ], ), ), ); final content = panel ? DecoratedBox( decoration: BoxDecoration( color: theme.colorScheme.surface.withValues(alpha: 0.86), borderRadius: BorderRadius.circular(8), border: Border.all( color: theme.colorScheme.outlineVariant.withValues(alpha: 0.5), ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.10), blurRadius: 28, offset: const Offset(0, 16), ), ], ), child: child, ) : child; return Center( child: Padding( padding: EdgeInsets.all(compact ? 16 : 32), child: content, ), ); } } class _RetryButton extends StatelessWidget { final VoidCallback onPressed; const _RetryButton({required this.onPressed}); @override Widget build(BuildContext context) { return FilledButton.icon( onPressed: onPressed, icon: const Icon(Icons.refresh, size: 18), label: const Text('重试'), style: FilledButton.styleFrom( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), ), ); } }