import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../../core/di/injection_container.dart'; import '../../../../routes/route_paths.dart'; /// 结算币种枚举 enum SettlementCurrency { bnb, og, usdt, dst } /// 兑换页面 - 显示可结算收益和兑换功能 /// 支持一键结算和DST转USDT class TradingPage extends ConsumerStatefulWidget { const TradingPage({super.key}); @override ConsumerState createState() => _TradingPageState(); } class _TradingPageState extends ConsumerState { // 当前选中的结算币种 SettlementCurrency _selectedCurrency = SettlementCurrency.usdt; // 钱包数据(从 wallet-service 获取) double _settleableAmount = 0.0; double _dstBalance = 0.0; double _usdtBalance = 0.0; bool _isLoading = true; bool _isSettling = false; @override void initState() { super.initState(); _loadWalletData(); } /// 加载钱包数据 Future _loadWalletData() async { try { debugPrint('[TradingPage] 开始加载数据...'); // 从 reward-service 获取可结算收益(与 Profile 页面保持一致) final rewardService = ref.read(rewardServiceProvider); final summary = await rewardService.getMyRewardSummary(); // 从 wallet-service 获取 DST 余额 final walletService = ref.read(walletServiceProvider); final wallet = await walletService.getMyWallet(); if (mounted) { setState(() { _settleableAmount = summary.settleableUsdt; _dstBalance = wallet.balances.dst.available; _usdtBalance = wallet.balances.usdt.available; _isLoading = false; }); debugPrint('[TradingPage] 数据加载成功:'); debugPrint('[TradingPage] 可结算 USDT: $_settleableAmount (from reward-service)'); debugPrint('[TradingPage] DST 余额: $_dstBalance (from wallet-service)'); debugPrint('[TradingPage] USDT 余额: $_usdtBalance (from wallet-service)'); } } catch (e, stackTrace) { debugPrint('[TradingPage] 加载数据失败: $e'); debugPrint('[TradingPage] 堆栈: $stackTrace'); if (mounted) { setState(() { _isLoading = false; }); } } } /// 选择结算币种 void _selectCurrency(SettlementCurrency currency) { setState(() { _selectedCurrency = currency; }); } /// 一键结算 void _onSettlement() { if (_settleableAmount <= 0) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('没有可结算的收益'), backgroundColor: Color(0xFF8B5A2B), ), ); return; } showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认结算'), content: Text( '确定将 ${_formatNumber(_settleableAmount)} 绿积分 结算为 ${_getCurrencyName(_selectedCurrency)} 吗?', ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () { Navigator.pop(context); _doSettlement(); }, child: const Text('确认'), ), ], ), ); } /// 执行结算 Future _doSettlement() async { if (_isSettling) return; setState(() { _isSettling = true; }); try { debugPrint('[TradingPage] 开始结算...'); debugPrint('[TradingPage] 金额: $_settleableAmount USDT'); debugPrint('[TradingPage] 币种: ${_getCurrencyName(_selectedCurrency)}'); final walletService = ref.read(walletServiceProvider); final orderId = await walletService.settleRewards( usdtAmount: _settleableAmount, settleCurrency: _getCurrencyName(_selectedCurrency), ); debugPrint('[TradingPage] 结算成功: orderId=$orderId'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('结算成功'), backgroundColor: Color(0xFFD4AF37), ), ); // 刷新钱包数据 _loadWalletData(); } } catch (e) { debugPrint('[TradingPage] 结算失败: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('结算失败: $e'), backgroundColor: Colors.red, ), ); } } finally { if (mounted) { setState(() { _isSettling = false; }); } } } /// 卖出DST转换为USDT void _onSellDst() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('卖出 DST'), content: Text( '确定将 ${_formatNumber(_dstBalance)} DST 转换为 绿积分 吗?', ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('转换成功'), backgroundColor: Color(0xFFD4AF37), ), ); }, child: const Text('确认'), ), ], ), ); } /// 格式化数字(添加千分位) String _formatNumber(double number) { final parts = number.toStringAsFixed(2).split('.'); final intPart = parts[0].replaceAllMapped( RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]},', ); return '$intPart.${parts[1]}'; } /// 获取币种名称 String _getCurrencyName(SettlementCurrency currency) { switch (currency) { case SettlementCurrency.bnb: return 'BNB'; case SettlementCurrency.og: return 'OG'; case SettlementCurrency.usdt: return 'USDT'; case SettlementCurrency.dst: return 'DST'; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Container( width: double.infinity, height: double.infinity, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFFFFF5E6), Color(0xFFFFE4B5), ], ), ), child: SafeArea( child: SingleChildScrollView( child: Column( children: [ // 顶部标题栏 _buildAppBar(), const SizedBox(height: 16), // 可结算收益卡片 _buildSettleableCard(), const SizedBox(height: 24), // 一键结算按钮 _buildSettlementButton(), const SizedBox(height: 16), // 结算币种选择 _buildCurrencySelector(), const SizedBox(height: 24), // 分隔线 _buildDivider(), // TODO: 暂时屏蔽卖出DST功能,待开放后取消注释 // const SizedBox(height: 24), // // 卖出DST按钮 // _buildSellDstButton(), // const SizedBox(height: 8), // // DST余额显示 // _buildDstBalance(), // const SizedBox(height: 24), // // 分隔线 // _buildDivider(), const SizedBox(height: 24), // 提取按钮 _buildWithdrawButton(), const SizedBox(height: 8), // USDT余额显示 _buildUsdtBalance(), ], ), ), ), ), ); } /// 构建顶部标题栏 Widget _buildAppBar() { return Container( height: 56, padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ const Spacer(), const Text( '兑换', style: TextStyle( fontSize: 18, fontFamily: 'Inter', fontWeight: FontWeight.w700, height: 1.25, letterSpacing: -0.27, color: Color(0xFF5D4037), ), ), const Spacer(), // 账本明细入口 GestureDetector( onTap: () => context.push(RoutePaths.ledgerDetail), child: Container( width: 36, height: 36, decoration: BoxDecoration( color: const Color(0x1A8B5A2B), borderRadius: BorderRadius.circular(8), ), child: const Icon( Icons.receipt_long_outlined, color: Color(0xFF5D4037), size: 20, ), ), ), ], ), ); } /// 构建可结算收益卡片 Widget _buildSettleableCard() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Container( width: double.infinity, padding: const EdgeInsets.all(24), decoration: BoxDecoration( color: const Color(0x1A8B5A2B), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ const Text( '可结算收益', style: TextStyle( fontSize: 14, fontFamily: 'Inter', height: 1.5, color: Color(0xCC8B5A2B), ), ), const SizedBox(height: 8), _isLoading ? const SizedBox( width: 24, height: 24, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), ), ) : Text( '${_formatNumber(_settleableAmount)} 绿积分', style: const TextStyle( fontSize: 32, fontFamily: 'Inter', fontWeight: FontWeight.w700, height: 1.25, letterSpacing: -0.8, color: Color(0xFF5D4037), ), ), ], ), ), ); } /// 构建一键结算按钮 /// 注意:一键结算功能暂时禁用 Widget _buildSettlementButton() { // 功能暂时禁用,始终不可点击 const bool canSettle = false; return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: GestureDetector( onTap: null, // 功能暂时禁用 child: Container( width: double.infinity, height: 56, decoration: BoxDecoration( color: const Color(0x80D4AF37), // 禁用状态颜色 borderRadius: BorderRadius.circular(12), ), child: const Center( child: Text( '一键结算(暂未开放)', style: TextStyle( fontSize: 16, fontFamily: 'Inter', fontWeight: FontWeight.w700, height: 1.5, letterSpacing: 0.24, color: Colors.white, ), ), ), ), ), ); } /// 构建结算币种选择器 Widget _buildCurrencySelector() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( children: [ const Text( '结算的币种', style: TextStyle( fontSize: 14, fontFamily: 'Inter', fontWeight: FontWeight.w700, height: 1.5, letterSpacing: 0.21, color: Color(0xCC8B5A2B), ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(6), decoration: BoxDecoration( color: const Color(0x1A8B5A2B), borderRadius: BorderRadius.circular(12), ), child: Row( children: [ // TODO: BNB, OG, DST 暂时屏蔽,待开放后取消注释 // _buildCurrencyChip(SettlementCurrency.bnb, 'BNB'), // const SizedBox(width: 8), // _buildCurrencyChip(SettlementCurrency.og, 'OG'), // const SizedBox(width: 8), _buildCurrencyChip(SettlementCurrency.usdt, 'RMB/CNY'), // const SizedBox(width: 8), // _buildCurrencyChip(SettlementCurrency.dst, 'DST'), ], ), ), ], ), ); } /// 构建币种选择标签 Widget _buildCurrencyChip(SettlementCurrency currency, String label) { final isSelected = _selectedCurrency == currency; return Expanded( child: GestureDetector( onTap: () => _selectCurrency(currency), child: Container( height: 40, decoration: BoxDecoration( color: isSelected ? const Color(0xFFD4AF37) : Colors.transparent, borderRadius: BorderRadius.circular(8), ), child: Center( child: Text( label, style: TextStyle( fontSize: 14, fontFamily: 'Inter', fontWeight: isSelected ? FontWeight.w700 : FontWeight.w600, height: 1.43, color: isSelected ? Colors.white : const Color(0xCC5D4037), ), ), ), ), ), ); } /// 构建分隔线 Widget _buildDivider() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Container( height: 1, color: const Color(0x1A8B5A2B), ), ); } /// 构建卖出DST按钮 /// 注意:卖出DST功能暂时禁用 Widget _buildSellDstButton() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: GestureDetector( onTap: null, // 功能暂时禁用 child: Container( width: double.infinity, height: 56, decoration: BoxDecoration( color: const Color(0x1A8B5A2B), // 禁用状态颜色更浅 borderRadius: BorderRadius.circular(12), border: Border.all( color: const Color(0x408B5A2B), // 禁用状态边框更浅 width: 1, ), ), child: const Center( child: Text( '卖出 DST 转换为 绿积分(暂未开放)', style: TextStyle( fontSize: 16, fontFamily: 'Inter', fontWeight: FontWeight.w700, height: 1.5, letterSpacing: 0.24, color: Color(0x808B5A2B), // 禁用状态文字颜色更浅 ), ), ), ), ), ); } /// 构建DST余额显示 Widget _buildDstBalance() { return _isLoading ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), ), ) : Text( 'DST 余额: ${_formatNumber(_dstBalance)}', style: const TextStyle( fontSize: 14, fontFamily: 'Inter', height: 1.5, color: Color(0x995D4037), ), ); } /// 构建提取按钮 /// 当 USDT 余额为 0 时禁用 Widget _buildWithdrawButton() { // 余额为0时禁用 final bool canWithdraw = !_isLoading && _usdtBalance > 0; return Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: GestureDetector( onTap: canWithdraw ? () { context.push(RoutePaths.withdrawUsdt); } : null, child: Container( width: double.infinity, height: 56, decoration: BoxDecoration( color: canWithdraw ? const Color(0xFFD4AF37) : const Color(0x80D4AF37), // 禁用状态颜色 borderRadius: BorderRadius.circular(12), boxShadow: canWithdraw ? const [ BoxShadow( color: Color(0x4DD4AF37), blurRadius: 14, offset: Offset(0, 4), ), ] : null, // 禁用时无阴影 ), child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.account_balance_wallet_outlined, color: canWithdraw ? Colors.white : Colors.white70, size: 20, ), const SizedBox(width: 8), Text( '提取', style: TextStyle( fontSize: 16, fontFamily: 'Inter', fontWeight: FontWeight.w700, height: 1.5, letterSpacing: 0.24, color: canWithdraw ? Colors.white : Colors.white70, ), ), ], ), ), ), ), ); } /// 构建USDT余额显示 Widget _buildUsdtBalance() { return _isLoading ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Color(0xFFD4AF37)), ), ) : Text( '绿积分 余额: ${_formatNumber(_usdtBalance)}', style: const TextStyle( fontSize: 14, fontFamily: 'Inter', height: 1.5, color: Color(0x995D4037), ), ); } }