import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'package:provider/provider.dart'; import '../../../core/theme/app_theme.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../core/utils/toast_utils.dart'; import '../../../providers/asset_provider.dart'; import '../../components/material_input.dart'; /// 提现页面 class WithdrawPage extends StatefulWidget { final String? balance; const WithdrawPage({super.key, this.balance}); @override State createState() => _WithdrawPageState(); } class _WithdrawPageState extends State { final _amountController = TextEditingController(); final _addressController = TextEditingController(); final _contactController = TextEditingController(); final _amountFocus = FocusNode(); bool _isSubmitting = false; List _networks = []; String? _selectedNetwork; @override void initState() { super.initState(); _amountController.addListener(() => setState(() {})); _loadNetworks(); } @override void dispose() { _amountController.dispose(); _addressController.dispose(); _contactController.dispose(); _amountFocus.dispose(); super.dispose(); } // ============================================ // 业务逻辑 // ============================================ void _loadNetworks() { context.read().getWalletNetworks().then((list) { if (mounted) { setState(() { _networks = list; if (list.isNotEmpty) _selectedNetwork = list.first; }); } }); } String get _feeText { final amount = double.tryParse(_amountController.text) ?? 0; if (amount > 0) { final fee = amount * 0.1; final receivable = amount - fee; return '手續費(10%): -${fee.toStringAsFixed(2)} USDT | 應收款: ${receivable.toStringAsFixed(2)} USDT'; } return '提現將扣除 10% 手續費'; } Future _submitWithdraw() async { final amount = double.tryParse(_amountController.text); if (amount == null || amount <= 0) { ToastUtils.showError('請輸入有效金額'); return; } final address = _addressController.text.trim(); if (address.isEmpty) { ToastUtils.showError('請輸入提現地址'); return; } if (_isSubmitting) return; setState(() => _isSubmitting = true); try { final response = await context.read().withdraw( amount: _amountController.text, withdrawAddress: address, withdrawContact: _contactController.text.trim().isNotEmpty ? _contactController.text.trim() : null, network: _selectedNetwork, ); if (!mounted) return; if (response.success) { ToastUtils.showSuccess('申請成功,請等待管理員審批'); Navigator.of(context).pop(true); } else { ToastUtils.showError(response.message ?? '申請失敗'); } } catch (e) { if (mounted) ToastUtils.showError('申請失敗: $e'); } finally { if (mounted) setState(() => _isSubmitting = false); } } // ============================================ // 构建 UI // ============================================ @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Scaffold( backgroundColor: colorScheme.surface, appBar: AppBar( leading: IconButton( icon: Icon(LucideIcons.arrowLeft, color: colorScheme.onSurface, size: 20), onPressed: () => Navigator.of(context).pop(), ), title: Text( '提現', style: AppTextStyles.headlineLarge(context).copyWith( fontWeight: FontWeight.w600, ), ), backgroundColor: Colors.transparent, elevation: 0, scrolledUnderElevation: 0, centerTitle: true, ), body: SingleChildScrollView( padding: const EdgeInsets.fromLTRB( AppSpacing.md, AppSpacing.xs, AppSpacing.md, AppSpacing.xl), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 可用余额 if (widget.balance != null) ...[ _buildBalanceRow(colorScheme), const SizedBox(height: AppSpacing.lg), ], // 提现金额 _buildAmountInput(colorScheme), const SizedBox(height: AppSpacing.sm), // 手续费提示 _buildFeeTip(colorScheme), const SizedBox(height: AppSpacing.lg), // 提现网络 if (_networks.isNotEmpty) ...[ _buildSectionLabel(colorScheme, '提現網絡'), const SizedBox(height: AppSpacing.sm), _buildNetworkSelector(colorScheme), const SizedBox(height: AppSpacing.lg), ], // 目标地址 _buildAddressInput(colorScheme), const SizedBox(height: AppSpacing.lg), // 联系方式 _buildContactInput(colorScheme), const SizedBox(height: AppSpacing.xl), // 安全提示 _buildSecurityTips(colorScheme), const SizedBox(height: AppSpacing.xl), // 提交按钮 _buildSubmitButton(colorScheme), const SizedBox(height: AppSpacing.md), _buildBottomTip(colorScheme), ], ), ), ); } // ============================================ // 组件 // ============================================ Widget _buildBalanceRow(ColorScheme colorScheme) { return Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: colorScheme.surface, borderRadius: BorderRadius.circular(14), border: Border.all( color: colorScheme.outlineVariant.withValues(alpha: 0.5), width: 1, ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '可用餘額', style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), Text( '${widget.balance} USDT', style: AppTextStyles.bodyMedium(context).copyWith( fontWeight: FontWeight.w600, ), ), ], ), ); } Widget _buildSectionLabel(ColorScheme colorScheme, String text) { return Text( text, style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, fontWeight: FontWeight.w500, ), ); } Widget _buildAmountInput(ColorScheme colorScheme) { return MaterialInput( controller: _amountController, focusNode: _amountFocus, labelText: '提現金額', hintText: '0.00', keyboardType: const TextInputType.numberWithOptions(decimal: true), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,8}')), ], suffixIcon: Padding( padding: const EdgeInsets.only(right: AppSpacing.md), child: Text( 'USDT', style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, fontWeight: FontWeight.w500, ), ), ), ); } Widget _buildFeeTip(ColorScheme colorScheme) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( children: [ Icon(LucideIcons.info, size: 13, color: colorScheme.onSurfaceVariant), const SizedBox(width: 6), Expanded( child: Text( _feeText, style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ), ], ), ); } Widget _buildNetworkSelector(ColorScheme colorScheme) { return Container( width: double.infinity, height: 48, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: colorScheme.surface, borderRadius: BorderRadius.circular(14), border: Border.all( color: colorScheme.outlineVariant.withValues(alpha: 0.5), width: 1, ), ), child: DropdownButtonHideUnderline( child: DropdownButton( value: _selectedNetwork, isExpanded: true, hint: Text( '選擇提現網絡', style: AppTextStyles.bodyMedium(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), items: _networks .map((n) => DropdownMenuItem( value: n, child: Text(n), )) .toList(), onChanged: (value) { if (value != null) setState(() => _selectedNetwork = value); }, ), ), ); } Widget _buildAddressInput(ColorScheme colorScheme) { return MaterialInput( controller: _addressController, labelText: '目標地址', hintText: '請輸入提現地址', ); } Widget _buildContactInput(ColorScheme colorScheme) { return MaterialInput( controller: _contactController, labelText: '聯繫方式(可選)', hintText: '方便客服與您聯繫', ); } Widget _buildSecurityTips(ColorScheme colorScheme) { final tips = [ '請仔細核對提現地址,地址錯誤將導致資產無法找回', '提現申請提交後需等待管理員審批', '提現將扣除 10% 手續費', ]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: tips .map((t) => Padding( padding: const EdgeInsets.only(bottom: 6), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '• ', style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), Expanded( child: Text( t, style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ), ], ), )) .toList(), ); } Widget _buildSubmitButton(ColorScheme colorScheme) { return SizedBox( width: double.infinity, height: 48, child: ElevatedButton( onPressed: _isSubmitting ? null : _submitWithdraw, style: ElevatedButton.styleFrom( backgroundColor: colorScheme.onSurface, foregroundColor: colorScheme.surface, disabledBackgroundColor: colorScheme.surfaceContainerHighest, disabledForegroundColor: colorScheme.onSurfaceVariant, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), ), child: _isSubmitting ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( colorScheme.onSurfaceVariant, ), ), ) : Text( '提交申請', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, ), ), ), ); } Widget _buildBottomTip(ColorScheme colorScheme) { return Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(LucideIcons.shieldCheck, size: 13, color: colorScheme.onSurfaceVariant), const SizedBox(width: 4), Text( '資金安全由平台全程保障', style: AppTextStyles.bodySmall(context).copyWith( color: colorScheme.onSurfaceVariant, ), ), ], ), ); } }