import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:provider/provider.dart'; import 'package:google_fonts/google_fonts.dart'; import '../../../core/theme/app_color_scheme.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../providers/asset_provider.dart'; import '../../shared/ui_constants.dart'; import '../../components/glass_panel.dart'; import '../../components/neon_glow.dart'; import '../orders/fund_orders_page.dart'; /// 资产页面 - 钱包风格 class AssetPage extends StatefulWidget { const AssetPage({super.key}); @override State createState() => _AssetPageState(); } class _AssetPageState extends State with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @override void initState() { super.initState(); // 强制刷新数据,确保加载最新数据 WidgetsBinding.instance.addPostFrameCallback((_) => _loadData()); } void _loadData() { // 强制刷新,不使用缓存 context.read().refreshAll(force: true); } @override Widget build(BuildContext context) { super.build(context); final colorScheme = Theme.of(context).colorScheme; return Scaffold( backgroundColor: colorScheme.background, body: Consumer( builder: (context, provider, _) { return RefreshIndicator( onRefresh: () => provider.refreshAll(force: true), color: colorScheme.primary, backgroundColor: colorScheme.surfaceContainerHighest, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), padding: AppSpacing.pagePadding, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 1. 总资产估值卡片 _TotalAssetCard(overview: provider.overview), SizedBox(height: AppSpacing.lg), // 2. 操作按钮 _ActionButtons(provider: provider), SizedBox(height: AppSpacing.lg), // 3. 资产组合 _AssetComposition(provider: provider), SizedBox(height: AppSpacing.lg), // 4. 代币列表 _TokenList(holdings: provider.holdings), ], ), ), ); }, ), ); } } /// 总资产估值卡片 class _TotalAssetCard extends StatelessWidget { final dynamic overview; const _TotalAssetCard({required this.overview}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Container( width: double.infinity, padding: EdgeInsets.all(AppSpacing.xl), decoration: BoxDecoration( gradient: AppColorScheme.assetCardGradient, borderRadius: BorderRadius.circular(AppRadius.xl), boxShadow: [ BoxShadow( color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08), blurRadius: 20, ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '总资产估值', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, letterSpacing: 0.5, color: Colors.white.withOpacity(0.7), ), ), SizedBox(height: AppSpacing.sm), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '\$${overview?.totalAsset ?? '0.00'}', style: GoogleFonts.spaceGrotesk( fontSize: 40, fontWeight: FontWeight.bold, color: Colors.white, ), ), SizedBox(width: AppSpacing.sm), Padding( padding: EdgeInsets.only(bottom: 8), child: Text( 'USDT', style: TextStyle( fontSize: 14, color: Colors.white.withOpacity(0.7), ), ), ), ], ), SizedBox(height: AppSpacing.md), Row( children: [ Container( padding: EdgeInsets.symmetric( horizontal: AppSpacing.sm, vertical: AppSpacing.xs, ), decoration: BoxDecoration( color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(AppRadius.full), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( LucideIcons.trendingUp, color: Colors.white.withOpacity(0.9), size: 12, ), SizedBox(width: AppSpacing.xs), Text( '今日收益: ${overview?.totalProfit ?? '0.00'} USDT', style: TextStyle( fontSize: 11, color: Colors.white.withOpacity(0.9), ), ), ], ), ), ], ), ], ), ); } } /// 操作按钮 class _ActionButtons extends StatelessWidget { final AssetProvider provider; const _ActionButtons({required this.provider}); @override Widget build(BuildContext context) { return Row( children: [ Expanded( child: _ActionButton( icon: LucideIcons.download, label: '充币', onTap: () => _showDepositDialog(context), ), ), SizedBox(width: AppSpacing.sm), Expanded( child: _ActionButton( icon: LucideIcons.upload, label: '提币', onTap: () => _showWithdrawDialog(context, provider.fundAccount?.balance), ), ), SizedBox(width: AppSpacing.sm), Expanded( child: _ActionButton( icon: LucideIcons.arrowLeftRight, label: '划转', onTap: () => _showTransferDialog(context), ), ), ], ); } } /// 操作按钮项 class _ActionButton extends StatelessWidget { final IconData icon; final String label; final VoidCallback onTap; const _ActionButton({ required this.icon, required this.label, required this.onTap, }); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return GestureDetector( onTap: onTap, child: Container( padding: EdgeInsets.symmetric(vertical: AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.2), ), ), child: Column( children: [ Icon( icon, color: colorScheme.primary, size: 24, ), SizedBox(height: AppSpacing.xs), Text( label, style: TextStyle( fontSize: 12, color: colorScheme.onSurface, fontWeight: FontWeight.w500, ), ), ], ), ), ); } } /// 资产组合 class _AssetComposition extends StatelessWidget { final AssetProvider provider; const _AssetComposition({required this.provider}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final fund = provider.fundAccount; final overview = provider.overview; final fundBalance = fund?.balance ?? overview?.fundBalance ?? '0.00'; final tradeBalance = overview?.tradeBalance ?? '0'; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '资产组合', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.md), Row( children: [ Expanded( child: _AssetCard( icon: LucideIcons.wallet, title: '资金账户', amount: '$fundBalance USDT', onTap: () {}, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: _AssetCard( icon: LucideIcons.trendingUp, title: '交易账户', amount: '$tradeBalance USDT', onTap: () {}, ), ), ], ), ], ); } } /// 资产卡片 class _AssetCard extends StatelessWidget { final IconData icon; final String title; final String amount; final VoidCallback onTap; const _AssetCard({ required this.icon, required this.title, required this.amount, required this.onTap, }); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return GestureDetector( onTap: onTap, child: Container( padding: EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.2), ), ), child: Column( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: colorScheme.primary.withOpacity(0.1), shape: BoxShape.circle, ), child: Center( child: Icon( icon, color: colorScheme.primary, size: 20, ), ), ), SizedBox(height: AppSpacing.sm), Text( title, style: TextStyle( fontSize: 11, color: colorScheme.onSurfaceVariant, ), ), SizedBox(height: AppSpacing.xs), Text( amount, style: GoogleFonts.spaceGrotesk( fontSize: 14, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), ], ), ), ); } } /// 代币列表 class _TokenList extends StatelessWidget { final List holdings; const _TokenList({required this.holdings}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '代币列表', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.md), if (holdings.isEmpty) _EmptyState(icon: LucideIcons.wallet, message: '暂无持仓') else ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: holdings.length, separatorBuilder: (_, __) => Divider( height: 1, color: colorScheme.outlineVariant.withOpacity(0.2), ), itemBuilder: (context, index) => _TokenItem(holding: holdings[index]), ), ], ); } } /// 空状态 class _EmptyState extends StatelessWidget { final IconData icon; final String message; const _EmptyState({required this.icon, required this.message}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Center( child: Padding( padding: EdgeInsets.all(AppSpacing.xl), child: Column( children: [ Icon( icon, size: 48, color: colorScheme.onSurfaceVariant, ), SizedBox(height: AppSpacing.sm + AppSpacing.xs), Text( message, style: TextStyle(color: colorScheme.onSurfaceVariant), ), ], ), ), ); } } /// 代币项 class _TokenItem extends StatelessWidget { final dynamic holding; const _TokenItem({required this.holding}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Padding( padding: EdgeInsets.symmetric(vertical: AppSpacing.md), child: Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( color: colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.md), ), child: Center( child: Text( holding.coinCode.substring(0, 1), style: TextStyle( color: colorScheme.primary, fontWeight: FontWeight.bold, fontSize: 18, ), ), ), ), SizedBox(width: AppSpacing.md), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( holding.coinCode, style: GoogleFonts.spaceGrotesk( fontSize: 15, fontWeight: FontWeight.w600, color: colorScheme.onSurface, ), ), SizedBox(width: AppSpacing.sm), Container( padding: EdgeInsets.symmetric( horizontal: AppSpacing.xs, vertical: 2, ), decoration: BoxDecoration( color: AppColorScheme.getUpColor(isDark).withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Text( '+5.2%', style: TextStyle( fontSize: 10, color: AppColorScheme.getUpColor(isDark), fontWeight: FontWeight.w600, ), ), ), ], ), SizedBox(height: AppSpacing.xs), Text( holding.quantity, style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '${holding.currentValue} USDT', style: GoogleFonts.spaceGrotesk( fontSize: 15, fontWeight: FontWeight.w600, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.xs), Text( holding.formattedProfitRate, style: TextStyle( color: holding.isProfit ? AppColorScheme.getUpColor(isDark) : AppColorScheme.down, fontSize: 12, fontWeight: FontWeight.w600, ), ), ], ), ], ), ); } } // ============================================ // Dialogs - Glass Panel 风格 // ============================================ void _showDepositDialog(BuildContext context) { final amountController = TextEditingController(); final formKey = GlobalKey(); final colorScheme = Theme.of(context).colorScheme; showShadDialog( context: context, builder: (ctx) => Dialog( backgroundColor: Colors.transparent, child: GlassPanel( borderRadius: BorderRadius.circular(AppRadius.xxl), padding: EdgeInsets.all(AppSpacing.lg), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '充币', style: GoogleFonts.spaceGrotesk( fontSize: 24, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.xs), Text( 'Asset: USDT', style: TextStyle( fontSize: 12, letterSpacing: 0.1, color: colorScheme.onSurfaceVariant, ), ), ], ), Container( padding: EdgeInsets.all(AppSpacing.sm), decoration: BoxDecoration( color: colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.md), ), child: Icon( LucideIcons.wallet, color: colorScheme.secondary, ), ), ], ), SizedBox(height: AppSpacing.lg), ShadForm( key: formKey, child: ShadInputFormField( id: 'amount', controller: amountController, label: const Text('充值金额'), placeholder: const Text('0.00'), keyboardType: const TextInputType.numberWithOptions(decimal: true), validator: Validators.amount, ), ), SizedBox(height: AppSpacing.lg), Row( children: [ Expanded( child: NeonButton( text: '取消', type: NeonButtonType.outline, onPressed: () => Navigator.of(ctx).pop(), height: 48, showGlow: false, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: NeonButton( text: '下一步', type: NeonButtonType.primary, onPressed: () async { if (formKey.currentState!.saveAndValidate()) { Navigator.of(ctx).pop(); final response = await context.read().deposit( amount: amountController.text, ); if (context.mounted) { if (response.success && response.data != null) { _showDepositResultDialog(context, response.data!); } else { _showResultDialog(context, '申请失败', response.message); } } } }, height: 48, showGlow: true, ), ), ], ), ], ), ), ), ); } void _showDepositResultDialog(BuildContext context, Map data) { final orderNo = data['orderNo'] as String? ?? ''; final amount = data['amount']?.toString() ?? '0.00'; final walletAddress = data['walletAddress'] as String? ?? ''; final walletNetwork = data['walletNetwork'] as String? ?? 'TRC20'; final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; showShadDialog( context: context, builder: (ctx) => Dialog( backgroundColor: Colors.transparent, child: GlassPanel( borderRadius: BorderRadius.circular(AppRadius.xxl), padding: EdgeInsets.all(AppSpacing.lg), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ NeonIcon( icon: Icons.check_circle, color: AppColorScheme.getUpColor(isDark), size: 24, ), SizedBox(width: AppSpacing.sm), Text( '充值申请成功', style: GoogleFonts.spaceGrotesk( fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), ], ), SizedBox(height: AppSpacing.lg), _InfoRow(label: '订单号', value: orderNo), SizedBox(height: AppSpacing.sm), _InfoRow(label: '充值金额', value: '$amount USDT', isBold: true), SizedBox(height: AppSpacing.lg), Text( '请向以下地址转账:', style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), SizedBox(height: AppSpacing.sm), _WalletAddressCard(address: walletAddress, network: walletNetwork), SizedBox(height: AppSpacing.md), Container( padding: EdgeInsets.all(AppSpacing.sm), decoration: BoxDecoration( color: AppColorScheme.warning.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: AppColorScheme.warning.withOpacity(0.2), ), ), child: Row( children: [ Icon(Icons.info_outline, size: 16, color: AppColorScheme.warning), SizedBox(width: AppSpacing.sm), Expanded( child: Text( '转账完成后请点击"已打款"按钮确认', style: TextStyle(fontSize: 12, color: AppColorScheme.warning), ), ), ], ), ), SizedBox(height: AppSpacing.lg), Row( children: [ Expanded( child: NeonButton( text: '稍后确认', type: NeonButtonType.outline, onPressed: () => Navigator.of(ctx).pop(), height: 44, showGlow: false, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: NeonButton( text: '已打款', type: NeonButtonType.primary, onPressed: () async { Navigator.of(ctx).pop(); final response = await context.read().confirmPay(orderNo); if (context.mounted) { _showResultDialog( context, response.success ? '确认成功' : '确认失败', response.success ? '请等待管理员审核' : response.message, ); } }, height: 44, showGlow: true, ), ), ], ), ], ), ), ), ); } class _InfoRow extends StatelessWidget { final String label; final String value; final bool isBold; const _InfoRow({required this.label, required this.value, this.isBold = false}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( label, style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), Text( value, style: TextStyle( fontSize: 12, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, color: colorScheme.onSurface, ), ), ], ); } } class _WalletAddressCard extends StatelessWidget { final String address; final String network; const _WalletAddressCard({required this.address, required this.network}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Container( padding: EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.3), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( address, style: TextStyle( fontFamily: 'monospace', fontSize: 12, color: colorScheme.onSurface, ), ), ), GestureDetector( onTap: () { Clipboard.setData(ClipboardData(text: address)); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('地址已复制到剪贴板')), ); }, child: Container( padding: EdgeInsets.all(AppSpacing.xs), decoration: BoxDecoration( color: colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Icon( LucideIcons.copy, size: 16, color: colorScheme.primary, ), ), ), ], ), SizedBox(height: AppSpacing.sm), Text( '网络: $network', style: TextStyle( fontSize: 11, color: colorScheme.onSurfaceVariant, ), ), ], ), ); } } void _showWithdrawDialog(BuildContext context, String? balance) { final amountController = TextEditingController(); final addressController = TextEditingController(); final contactController = TextEditingController(); final formKey = GlobalKey(); final colorScheme = Theme.of(context).colorScheme; showShadDialog( context: context, builder: (ctx) => Dialog( backgroundColor: Colors.transparent, child: GlassPanel( borderRadius: BorderRadius.circular(AppRadius.xxl), padding: EdgeInsets.all(AppSpacing.lg), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: EdgeInsets.all(AppSpacing.sm), decoration: BoxDecoration( color: colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.md), ), child: Icon( LucideIcons.wallet, color: colorScheme.primary, ), ), SizedBox(width: AppSpacing.sm), Text( '提币', style: GoogleFonts.spaceGrotesk( fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), ], ), SizedBox(height: AppSpacing.xs), Text( 'Securely transfer your assets to an external wallet address.', style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), if (balance != null) ...[ SizedBox(height: AppSpacing.md), Container( padding: EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: AppSpacing.sm, ), decoration: BoxDecoration( color: AppColorScheme.up.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.full), border: Border.all( color: AppColorScheme.up.withOpacity(0.2), ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Text( '可用余额: ', style: TextStyle( fontSize: 10, letterSpacing: 0.1, color: colorScheme.onSurfaceVariant, ), ), Text( '$balance USDT', style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, color: AppColorScheme.up, ), ), ], ), ), ], SizedBox(height: AppSpacing.lg), ShadForm( key: formKey, child: Column( children: [ ShadInputFormField( id: 'amount', controller: amountController, label: const Text('提币金额'), placeholder: const Text('请输入提币金额(USDT)'), keyboardType: const TextInputType.numberWithOptions(decimal: true), validator: Validators.amount, ), SizedBox(height: AppSpacing.md), ShadInputFormField( id: 'address', controller: addressController, label: const Text('目标地址'), placeholder: const Text('请输入提币地址'), validator: (v) => Validators.required(v, '提币地址'), ), SizedBox(height: AppSpacing.md), ShadInputFormField( id: 'contact', controller: contactController, label: const Text('联系方式(可选)'), placeholder: const Text('联系方式'), ), ], ), ), SizedBox(height: AppSpacing.lg), Row( children: [ Expanded( child: NeonButton( text: '取消', type: NeonButtonType.outline, onPressed: () => Navigator.of(ctx).pop(), height: 44, showGlow: false, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: NeonButton( text: '提交', type: NeonButtonType.primary, onPressed: () async { if (formKey.currentState!.saveAndValidate()) { Navigator.of(ctx).pop(); final response = await context.read().withdraw( amount: amountController.text, withdrawAddress: addressController.text, withdrawContact: contactController.text.isNotEmpty ? contactController.text : null, ); if (context.mounted) { _showResultDialog( context, response.success ? '申请成功' : '申请失败', response.success ? '请等待管理员审批' : response.message, ); } } }, height: 44, showGlow: true, ), ), ], ), SizedBox(height: AppSpacing.md), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.verified_user, size: 12, color: colorScheme.onSurfaceVariant.withOpacity(0.5), ), SizedBox(width: AppSpacing.xs), Text( 'End-to-End Encrypted Transaction', style: TextStyle( fontSize: 10, letterSpacing: 0.1, color: colorScheme.onSurfaceVariant.withOpacity(0.5), ), ), ], ), ], ), ), ), ), ); } void _showTransferDialog(BuildContext context) { final controller = TextEditingController(); final formKey = GlobalKey(); int direction = 1; final colorScheme = Theme.of(context).colorScheme; showShadDialog( context: context, builder: (ctx) => StatefulBuilder( builder: (ctx, setState) => Dialog( backgroundColor: Colors.transparent, child: GlassPanel( borderRadius: BorderRadius.circular(AppRadius.xxl), padding: EdgeInsets.all(AppSpacing.lg), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '划转', style: GoogleFonts.spaceGrotesk( fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.lg), Row( children: [ Expanded( child: _DirectionButton( label: '资金→交易', isSelected: direction == 1, onTap: () => setState(() => direction = 1), ), ), SizedBox(width: AppSpacing.sm), Expanded( child: _DirectionButton( label: '交易→资金', isSelected: direction == 2, onTap: () => setState(() => direction = 2), ), ), ], ), SizedBox(height: AppSpacing.lg), ShadForm( key: formKey, child: ShadInputFormField( id: 'amount', controller: controller, label: const Text('划转金额'), placeholder: const Text('请输入划转金额(USDT)'), keyboardType: const TextInputType.numberWithOptions(decimal: true), validator: Validators.amount, ), ), SizedBox(height: AppSpacing.lg), Row( children: [ Expanded( child: NeonButton( text: '取消', type: NeonButtonType.outline, onPressed: () => Navigator.of(ctx).pop(), height: 44, showGlow: false, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: NeonButton( text: '确认', type: NeonButtonType.primary, onPressed: () async { if (formKey.currentState!.saveAndValidate()) { Navigator.of(ctx).pop(); final response = await context.read().transfer( direction: direction, amount: controller.text, ); if (context.mounted) { _showResultDialog( context, response.success ? '划转成功' : '划转失败', response.message, ); } } }, height: 44, showGlow: true, ), ), ], ), ], ), ), ), ), ); } class _DirectionButton extends StatelessWidget { final String label; final bool isSelected; final VoidCallback onTap; const _DirectionButton({ required this.label, required this.isSelected, required this.onTap, }); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return GestureDetector( onTap: onTap, child: AnimatedContainer( duration: const Duration(milliseconds: 200), padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs), decoration: BoxDecoration( color: isSelected ? colorScheme.primary.withOpacity(0.15) : colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.md), border: isSelected ? Border.all( color: colorScheme.primary.withOpacity(0.3), ) : null, ), child: Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ if (isSelected) Icon( LucideIcons.check, size: 14, color: colorScheme.primary, ) else SizedBox(width: 14), SizedBox(width: AppSpacing.xs), Text( label, style: TextStyle( color: isSelected ? colorScheme.primary : colorScheme.onSurfaceVariant, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, fontSize: 12, ), ), ], ), ), ), ); } } void _showResultDialog(BuildContext context, String title, String? message) { final colorScheme = Theme.of(context).colorScheme; showShadDialog( context: context, builder: (ctx) => Dialog( backgroundColor: Colors.transparent, child: GlassPanel( borderRadius: BorderRadius.circular(AppRadius.xxl), padding: EdgeInsets.all(AppSpacing.lg), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( title, style: GoogleFonts.spaceGrotesk( fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), if (message != null) ...[ SizedBox(height: AppSpacing.sm), Text( message, style: TextStyle( color: colorScheme.onSurfaceVariant, ), textAlign: TextAlign.center, ), ], SizedBox(height: AppSpacing.lg), SizedBox( width: double.infinity, child: NeonButton( text: '确定', type: NeonButtonType.primary, onPressed: () => Navigator.of(ctx).pop(), height: 44, showGlow: false, ), ), ], ), ), ), ); }