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'; import 'transfer_page.dart'; /// 资产页面 - Material Design 3 风格 class AssetPage extends StatefulWidget { const AssetPage({super.key}); @override State createState() => _AssetPageState(); } class _AssetPageState extends State with AutomaticKeepAliveClientMixin { int _activeTab = 0; @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( children: [ _TabSelector( tabs: const ['资金账户', '交易账户'], selectedIndex: _activeTab, onChanged: (index) => setState(() => _activeTab = index), ), SizedBox(height: AppSpacing.md), _activeTab == 0 ? _FundAccountCard(provider: provider) : _TradeAccountCard( holdings: provider.holdings, tradeBalance: provider.overview?.tradeBalance, ), ], ), ), ); }, ), ); } } /// 资产总览卡片 - Material Design 3 风格 class _AssetCard extends StatelessWidget { final dynamic overview; const _AssetCard({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.lg + AppSpacing.sm), 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( children: [ Text( 'PORTFOLIO VALUE', style: TextStyle( fontSize: 10, fontWeight: FontWeight.w700, letterSpacing: 0.2, color: Colors.white.withOpacity(0.7), ), ), SizedBox(height: AppSpacing.sm), Text( '\$${overview?.totalAsset ?? '0.00'}', style: GoogleFonts.spaceGrotesk( fontSize: 36, fontWeight: FontWeight.bold, color: Colors.white, ), ), SizedBox(height: AppSpacing.md), Container( padding: EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: AppSpacing.xs + AppSpacing.xs, ), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.full), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( LucideIcons.trendingUp, color: Colors.white.withOpacity(0.7), size: 14, ), SizedBox(width: AppSpacing.xs), Text( '总盈亏: ${overview?.totalProfit ?? '0.00'} USDT', style: TextStyle( fontSize: 12, color: Colors.white.withOpacity(0.7), ), ), ], ), ), ], ), ); } } /// Tab 选择器 - Material Design 3 风格 class _TabSelector extends StatelessWidget { final List tabs; final int selectedIndex; final ValueChanged onChanged; const _TabSelector({ required this.tabs, required this.selectedIndex, required this.onChanged, }); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; return Container( padding: EdgeInsets.all(AppSpacing.xs), decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(AppRadius.lg), ), child: Row( children: tabs.asMap().entries.map((entry) { final index = entry.key; final label = entry.value; final isSelected = index == selectedIndex; return Expanded( child: GestureDetector( onTap: () => onChanged(index), child: AnimatedContainer( duration: const Duration(milliseconds: 200), padding: EdgeInsets.symmetric(vertical: AppSpacing.sm + AppSpacing.xs), decoration: BoxDecoration( color: isSelected ? colorScheme.primary : Colors.transparent, borderRadius: BorderRadius.circular(AppRadius.md), boxShadow: isSelected ? [ BoxShadow( color: colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08), blurRadius: 10, ), ] : null, ), child: Center( child: Text( label, style: TextStyle( color: isSelected ? colorScheme.onPrimary : colorScheme.onSurfaceVariant, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), ), ), ), ), ); }).toList(), ), ); } } /// 资金账户卡片 - Glass Panel 风格 class _FundAccountCard extends StatelessWidget { final AssetProvider provider; const _FundAccountCard({required this.provider}); @override Widget build(BuildContext context) { final fund = provider.fundAccount; final overview = provider.overview; final colorScheme = Theme.of(context).colorScheme; // 优先使用fund数据,如果为null则使用overview的fundBalance final displayBalance = fund?.balance ?? overview?.fundBalance ?? '0.00'; return GlassPanel( padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.xs), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'USDT 余额', style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), GestureDetector( onTap: () => Navigator.push( context, MaterialPageRoute(builder: (_) => const FundOrdersPage()), ), child: Row( children: [ Text( '充提记录', style: TextStyle( color: colorScheme.primary, fontSize: 12, ), ), Icon( LucideIcons.chevronRight, size: 14, color: colorScheme.primary, ), ], ), ), ], ), SizedBox(height: AppSpacing.sm), Text( displayBalance, style: GoogleFonts.spaceGrotesk( fontSize: 28, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.lg), Row( children: [ Expanded( child: NeonButton( text: '充值', type: NeonButtonType.tertiary, icon: Icons.add, onPressed: () => _showDepositDialog(context), height: 44, showGlow: false, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: NeonButton( text: '提现', type: NeonButtonType.secondary, icon: Icons.remove, onPressed: () => _showWithdrawDialog(context, fund?.balance), height: 44, showGlow: false, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: NeonButton( text: '划转', type: NeonButtonType.outline, icon: Icons.swap_horiz, onPressed: () => _navigateToTransfer(context), height: 44, showGlow: false, ), ), ], ), ], ), ); } } /// 交易账户卡片 - Glass Panel 风格 class _TradeAccountCard extends StatelessWidget { final List holdings; final String? tradeBalance; const _TradeAccountCard({required this.holdings, this.tradeBalance}); @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; // 计算总市值(所有持仓折算成USDT) double totalValue = 0; for (var h in holdings) { final value = double.tryParse(h.currentValue?.toString() ?? '0') ?? 0; totalValue += value; } // 对持仓进行排序:USDT 放在最上面 final sortedHoldings = List.from(holdings); sortedHoldings.sort((a, b) { final codeA = (a.coinCode ?? a['coinCode'] ?? '').toString().toUpperCase(); final codeB = (b.coinCode ?? b['coinCode'] ?? '').toString().toUpperCase(); if (codeA == 'USDT') return -1; if (codeB == 'USDT') return 1; return 0; }); return GlassPanel( padding: AppSpacing.cardPadding, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题行 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Container( width: 36, height: 36, decoration: BoxDecoration( color: colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.md), ), child: Icon( LucideIcons.trendingUp, size: 18, color: colorScheme.primary, ), ), SizedBox(width: AppSpacing.sm), Text( '交易账户', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), ], ), Icon( LucideIcons.chevronRight, size: 14, color: colorScheme.primary, ), ], ), SizedBox(height: AppSpacing.md), // 余额 Text( '余额 (USDT)', style: TextStyle( fontSize: 11, color: colorScheme.onSurfaceVariant, ), ), SizedBox(height: AppSpacing.xs), Text( totalValue.toStringAsFixed(2), style: GoogleFonts.spaceGrotesk( fontSize: 28, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.lg), // 持仓列表标题 Text( '持仓列表', style: GoogleFonts.spaceGrotesk( fontSize: 14, fontWeight: FontWeight.w600, color: colorScheme.onSurfaceVariant, ), ), SizedBox(height: AppSpacing.md), if (sortedHoldings.isEmpty) const _EmptyState(icon: LucideIcons.wallet, message: '暂无持仓') else ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: sortedHoldings.length, separatorBuilder: (_, __) => Container( margin: EdgeInsets.only(left: 56), height: 1, color: AppColorScheme.glassPanelBorder, ), itemBuilder: (context, index) => _HoldingItem(holding: sortedHoldings[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 _HoldingItem extends StatelessWidget { final dynamic holding; const _HoldingItem({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.sm), child: Row( children: [ Container( width: 40, height: 40, 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, ), ), ), ), SizedBox(width: AppSpacing.sm + AppSpacing.xs), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( holding.coinCode, style: GoogleFonts.spaceGrotesk( fontSize: 14, fontWeight: FontWeight.w600, color: colorScheme.onSurface, ), ), Text( '数量: ${holding.quantity}', style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '${holding.currentValue} USDT', style: TextStyle( fontSize: 12, color: colorScheme.onSurface, ), ), 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( 'Deposit (充值)', 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( '提现 (Withdraw)', 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 _navigateToTransfer(BuildContext context) async { final result = await Navigator.push( context, MaterialPageRoute(builder: (_) => const TransferPage()), ); // 如果划转成功,刷新数据 if (result == true && context.mounted) { context.read().refreshAll(force: true); } } 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, ), ), ], ), ), ), ); }