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 '../../../core/utils/toast_utils.dart'; import '../../../core/event/app_event_bus.dart'; import '../../../data/services/bonus_service.dart'; import '../../../providers/asset_provider.dart'; import '../../../providers/auth_provider.dart'; import '../../components/glass_panel.dart'; import '../../components/neon_glow.dart'; /// 福利中心页面 class WelfareCenterPage extends StatefulWidget { const WelfareCenterPage({super.key}); @override State createState() => _WelfareCenterPageState(); } class _WelfareCenterPageState extends State { Map? _welfareData; bool _isLoading = true; @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) => _loadData()); } Future _loadData() async { try { final bonusService = context.read(); final response = await bonusService.getWelfareStatus(); if (mounted) { setState(() { _welfareData = response.data; _isLoading = false; }); } } catch (_) { if (mounted) setState(() => _isLoading = false); } } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; return Scaffold( backgroundColor: colorScheme.background, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, title: Text( '福利中心', style: GoogleFonts.spaceGrotesk( fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), leading: IconButton( icon: Icon(LucideIcons.chevronLeft, color: colorScheme.onSurface), onPressed: () => Navigator.of(context).pop(), ), ), body: _isLoading ? Center( child: CircularProgressIndicator(color: colorScheme.primary), ) : RefreshIndicator( onRefresh: _loadData, color: colorScheme.primary, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), padding: AppSpacing.pagePadding, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 推广码卡片 _buildReferralCodeCard(colorScheme), SizedBox(height: AppSpacing.lg), // 首充福利卡片 _buildNewUserBonusCard(colorScheme), SizedBox(height: AppSpacing.lg), // 推广奖励列表 _buildReferralRewardsSection(colorScheme), SizedBox(height: AppSpacing.lg), // 规则说明 _buildRulesCard(colorScheme), ], ), ), ), ); } /// 推广码卡片 Widget _buildReferralCodeCard(ColorScheme colorScheme) { final referralCode = _welfareData?['referralCode'] as String? ?? ''; return GlassPanel( padding: EdgeInsets.all(AppSpacing.lg), child: Column( 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.users, color: colorScheme.primary, size: 20, ), ), SizedBox(width: AppSpacing.md), Text( '我的推广码', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), ], ), SizedBox(height: AppSpacing.lg), Container( width: double.infinity, padding: EdgeInsets.symmetric( horizontal: AppSpacing.lg, vertical: AppSpacing.md, ), decoration: BoxDecoration( color: colorScheme.surfaceContainerHigh, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.2), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( referralCode.isEmpty ? '暂无推广码' : referralCode, style: GoogleFonts.spaceGrotesk( fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 4, color: referralCode.isEmpty ? colorScheme.onSurfaceVariant : colorScheme.primary, ), ), if (referralCode.isNotEmpty) ...[ SizedBox(width: AppSpacing.md), GestureDetector( onTap: () { Clipboard.setData(ClipboardData(text: referralCode)); ToastUtils.show('推广码已复制'); }, child: Container( padding: EdgeInsets.all(AppSpacing.xs + 2), decoration: BoxDecoration( color: colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Icon( LucideIcons.copy, size: 18, color: colorScheme.primary, ), ), ), ], ], ), ), SizedBox(height: AppSpacing.sm), Text( '分享推广码给好友,好友注册并充值满1000u后您可领取100u奖励', style: TextStyle( fontSize: 11, color: colorScheme.onSurfaceVariant, ), ), ], ), ); } /// 首充福利卡片 Widget _buildNewUserBonusCard(ColorScheme colorScheme) { final newUserBonus = _welfareData?['newUserBonus'] as Map?; final eligible = newUserBonus?['eligible'] as bool? ?? false; final claimed = newUserBonus?['claimed'] as bool? ?? false; final deposited = newUserBonus?['deposited'] as bool? ?? false; String statusText; Color statusColor; String buttonText; bool canClaim; if (claimed) { statusText = '100 USDT 已领取'; statusColor = AppColorScheme.up; buttonText = '已领取'; canClaim = false; } else if (eligible) { statusText = '符合条件,立即领取!'; statusColor = colorScheme.primary; buttonText = '领取 100u'; canClaim = true; } else { statusText = deposited ? '已完成充值' : '完成首次充值后可领取'; statusColor = colorScheme.onSurfaceVariant; buttonText = '未解锁'; canClaim = false; } return GlassPanel( padding: EdgeInsets.all(AppSpacing.lg), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( padding: EdgeInsets.all(AppSpacing.sm), decoration: BoxDecoration( color: (claimed ? AppColorScheme.up : colorScheme.primary) .withOpacity(0.1), borderRadius: BorderRadius.circular(AppRadius.md), ), child: Icon( claimed ? LucideIcons.check : LucideIcons.gift, color: claimed ? AppColorScheme.up : colorScheme.primary, size: 20, ), ), SizedBox(width: AppSpacing.md), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '首充福利', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: 2), Text( statusText, style: TextStyle( fontSize: 12, color: statusColor, ), ), ], ), ), SizedBox( child: NeonButton( text: buttonText, type: canClaim ? NeonButtonType.primary : NeonButtonType.outline, onPressed: canClaim ? () => _claimNewUserBonus() : null, height: 36, showGlow: canClaim, ), ), ], ), SizedBox(height: AppSpacing.md), Text( '新用户首次充值完成后可领取 100 USDT', style: TextStyle( fontSize: 11, color: colorScheme.onSurfaceVariant, ), ), ], ), ); } /// 推广奖励列表 Widget _buildReferralRewardsSection(ColorScheme colorScheme) { final referralRewards = _welfareData?['referralRewards'] as List? ?? []; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '推广奖励', style: GoogleFonts.spaceGrotesk( fontSize: 16, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), ), SizedBox(height: AppSpacing.sm), Text( '被推广人每累计充值满 1000u,您可领取 100u 奖励(每人最多8次)', style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), SizedBox(height: AppSpacing.md), if (referralRewards.isEmpty) GlassPanel( padding: EdgeInsets.all(AppSpacing.xl), child: Center( child: Column( children: [ Icon( LucideIcons.users, size: 36, color: colorScheme.onSurfaceVariant.withOpacity(0.4), ), SizedBox(height: AppSpacing.sm), Text( '暂无推广用户', style: TextStyle( color: colorScheme.onSurfaceVariant, fontSize: 13, ), ), ], ), ), ) else ...referralRewards.map((item) { final data = item as Map; return _buildReferralRewardCard(data, colorScheme); }), ], ); } Widget _buildReferralRewardCard( Map data, ColorScheme colorScheme) { final username = data['username'] as String? ?? ''; final totalDeposit = data['totalDeposit']?.toString() ?? '0'; final claimableCount = data['claimableCount'] as int? ?? 0; final milestones = data['milestones'] as List? ?? []; return Padding( padding: EdgeInsets.only(bottom: AppSpacing.md), child: GlassPanel( padding: EdgeInsets.all(AppSpacing.md), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ CircleAvatar( radius: 16, backgroundColor: colorScheme.primary.withOpacity(0.1), child: Text( username.isNotEmpty ? username[0].toUpperCase() : '?', style: TextStyle( color: colorScheme.primary, fontWeight: FontWeight.bold, fontSize: 14, ), ), ), SizedBox(width: AppSpacing.sm), Text( username, style: GoogleFonts.spaceGrotesk( fontSize: 14, fontWeight: FontWeight.w600, color: colorScheme.onSurface, ), ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '累计充值: $totalDeposit U', style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), if (claimableCount > 0) Text( '$claimableCount 个可领取', style: TextStyle( fontSize: 11, color: colorScheme.primary, fontWeight: FontWeight.w600, ), ), ], ), ], ), SizedBox(height: AppSpacing.sm), // 里程碑进度 Wrap( spacing: 6, runSpacing: 6, children: milestones.map((m) { final milestone = m as Map; final earned = milestone['earned'] as bool? ?? false; final claimed = milestone['claimed'] as bool? ?? false; final claimable = milestone['claimable'] as bool? ?? false; final milestoneNum = milestone['milestone'] as int? ?? 0; Color bgColor; Color textColor; VoidCallback? onTap; if (claimed) { bgColor = AppColorScheme.up.withOpacity(0.15); textColor = AppColorScheme.up; onTap = null; } else if (claimable) { bgColor = colorScheme.primary.withOpacity(0.15); textColor = colorScheme.primary; onTap = () => _claimReferralBonus( data['userId'] as int, milestoneNum, ); } else if (earned) { bgColor = colorScheme.surfaceContainerHigh; textColor = colorScheme.onSurfaceVariant; onTap = null; } else { bgColor = colorScheme.surfaceContainerHighest .withOpacity(0.5); textColor = colorScheme.onSurfaceVariant.withOpacity(0.5); onTap = null; } return GestureDetector( onTap: onTap, child: Container( padding: EdgeInsets.symmetric( horizontal: 10, vertical: 6, ), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(AppRadius.md), border: Border.all( color: claimable ? colorScheme.primary.withOpacity(0.3) : Colors.transparent, ), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ if (claimed) Icon(LucideIcons.check, size: 12, color: textColor) else if (claimable) Icon(LucideIcons.gift, size: 12, color: textColor), if (claimed || claimable) SizedBox(width: 4), Text( '${milestoneNum}k', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: textColor, ), ), ], ), ), ); }).toList(), ), ], ), ), ); } /// 规则说明 Widget _buildRulesCard(ColorScheme colorScheme) { return Container( padding: EdgeInsets.all(AppSpacing.md), decoration: BoxDecoration( color: colorScheme.surfaceContainerHigh.withOpacity(0.3), borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all( color: colorScheme.outlineVariant.withOpacity(0.1), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(LucideIcons.info, size: 16, color: colorScheme.onSurfaceVariant), SizedBox(width: AppSpacing.sm), Text( '规则说明', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: colorScheme.onSurface, ), ), ], ), SizedBox(height: AppSpacing.sm), _buildRuleItem('新用户首次充值完成后可领取 100 USDT 首充福利', colorScheme), _buildRuleItem('被推广人累计充值每满 1000u,推广人可领 100u', colorScheme), _buildRuleItem('每位被推广人最多可触发 8 次推广奖励', colorScheme), _buildRuleItem('所有奖励将直接存入资金账户', colorScheme), ], ), ); } Widget _buildRuleItem(String text, ColorScheme colorScheme) { return Padding( padding: EdgeInsets.symmetric(vertical: 3), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( margin: EdgeInsets.only(top: 6), width: 4, height: 4, decoration: BoxDecoration( color: colorScheme.onSurfaceVariant, shape: BoxShape.circle, ), ), SizedBox(width: AppSpacing.sm), Expanded( child: Text( text, style: TextStyle( fontSize: 12, color: colorScheme.onSurfaceVariant, ), ), ), ], ), ); } Future _claimNewUserBonus() async { try { final bonusService = context.read(); final response = await bonusService.claimNewUserBonus(); if (!mounted) return; if (response.success) { context.read().refreshAll(force: true); context.read().fire(AppEventType.assetChanged); ToastUtils.show('领取成功!100 USDT 已到账'); _loadData(); } else { ToastUtils.show(response.message ?? '领取失败'); } } catch (e) { ToastUtils.show('领取失败: $e'); } } Future _claimReferralBonus(int referredUserId, int milestone) async { try { final bonusService = context.read(); final response = await bonusService.claimReferralBonus( referredUserId, milestone, ); if (!mounted) return; if (response.success) { context.read().refreshAll(force: true); context.read().fire(AppEventType.assetChanged); ToastUtils.show('领取成功!100 USDT 已到账'); _loadData(); } else { ToastUtils.show(response.message ?? '领取失败'); } } catch (e) { ToastUtils.show('领取失败: $e'); } } }