import 'package:flutter/material.dart'; /// 通用按钮(带 loading 态) class LoadingButton extends StatelessWidget { final String text; final VoidCallback? onPressed; final bool loading; final Color? color; final Color? textColor; final double? width; final double height; final double radius; const LoadingButton({ super.key, required this.text, this.onPressed, this.loading = false, this.color, this.textColor, this.width, this.height = 48, this.radius = 24, }); @override Widget build(BuildContext context) { final c = color ?? Theme.of(context).primaryColor; final tc = textColor ?? Colors.white; return SizedBox( width: width, height: height, child: ElevatedButton( onPressed: loading ? null : onPressed, style: ElevatedButton.styleFrom( backgroundColor: c, foregroundColor: tc, disabledBackgroundColor: c.withValues(alpha: 0.5), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(radius), ), ), child: loading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(tc), ), ) : Text( text, style: TextStyle(fontSize: 16, color: tc, fontWeight: FontWeight.w600), ), ), ); } } /// 通用 Section 头 class SectionHeader extends StatelessWidget { final String title; final String? actionText; final VoidCallback? onAction; final EdgeInsetsGeometry padding; const SectionHeader({ super.key, required this.title, this.actionText, this.onAction, this.padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 8), }); @override Widget build(BuildContext context) { return Padding( padding: padding, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), if (actionText != null) GestureDetector( onTap: onAction, child: Text(actionText!, style: TextStyle( fontSize: 13, color: Theme.of(context).primaryColor)), ), ], ), ); } } /// 通用空状态 class EmptyView extends StatelessWidget { final String text; final IconData icon; const EmptyView({super.key, this.text = '暂无数据', this.icon = Icons.inbox_outlined}); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 64, color: Colors.grey.shade400), const SizedBox(height: 8), Text(text, style: TextStyle(color: Colors.grey.shade600)), ], ), ); } }