diff --git a/flutter_monisuo/build/99111e0c5b6228829e100ef67db14ea2.cache.dill.track.dill b/flutter_monisuo/build/99111e0c5b6228829e100ef67db14ea2.cache.dill.track.dill index e5cafcb..6acbbf8 100644 Binary files a/flutter_monisuo/build/99111e0c5b6228829e100ef67db14ea2.cache.dill.track.dill and b/flutter_monisuo/build/99111e0c5b6228829e100ef67db14ea2.cache.dill.track.dill differ diff --git a/flutter_monisuo/lib/ui/pages/home/bills_page.dart b/flutter_monisuo/lib/ui/pages/home/bills_page.dart index 18591bd..0faa6eb 100644 --- a/flutter_monisuo/lib/ui/pages/home/bills_page.dart +++ b/flutter_monisuo/lib/ui/pages/home/bills_page.dart @@ -67,28 +67,70 @@ class _BillsPageState extends State with SingleTickerProviderStateMix List> _parseWelfareRecords(Map data) { final records = >[]; + // 新人福利 final newUser = data['newUserBonus'] as Map?; if (newUser != null) { + final claimed = newUser['claimed'] as bool? ?? false; + final eligible = newUser['eligible'] as bool? ?? false; + // 状态: 1=已领取, 0=可领取(待领取), 2=不可用(未解锁) + final int status; + if (claimed) { + status = 1; + } else if (eligible) { + status = 0; + } else { + status = 2; + } records.add({ 'type': 'new_user', 'title': '新人福利', - 'amount': newUser['amount']?.toString() ?? '0.00', - 'status': newUser['status'] ?? 0, + 'amount': newUser['amount']?.toString() ?? '100.00', + 'status': status, 'time': newUser['claimTime'] ?? newUser['createTime'], }); } + // 推广福利列表 - final referrals = data['referralBonuses'] as List?; - if (referrals != null) { - for (var r in referrals) { - final map = r as Map; + final referralRewards = data['referralRewards'] as List? ?? []; + for (var r in referralRewards) { + final map = r as Map; + final username = map['username'] as String? ?? '用户'; + final milestones = map['milestones'] as List? ?? []; + final claimableCount = map['claimableCount'] as int? ?? 0; + + // 每个 milestone 生成一条记录 + for (var m in milestones) { + final ms = m as Map; + final earned = ms['earned'] as bool? ?? false; + final claimable = ms['claimable'] as bool? ?? false; + final milestoneVal = ms['milestone'] as int? ?? 1; + + final int status; + if (earned) { + status = 1; // 已领取 + } else if (claimable) { + status = 0; // 可领取 + } else { + status = 2; // 未达标 + } records.add({ 'type': 'referral', - 'title': '推广福利 - ${map['referredUsername'] ?? '用户'}', - 'amount': map['amount']?.toString() ?? '0.00', - 'status': map['status'] ?? 0, - 'time': map['claimTime'] ?? map['createTime'], + 'title': '推广福利 - $username (${milestoneVal}000)', + 'amount': '100.00', + 'status': status, + 'time': ms['claimTime'] ?? ms['createTime'], + }); + } + + // 如果没有 milestone 但有 claimableCount,也生成记录 + if (milestones.isEmpty && claimableCount > 0) { + records.add({ + 'type': 'referral', + 'title': '推广福利 - $username', + 'amount': '${claimableCount * 100}', + 'status': 0, + 'time': null, }); } } @@ -340,7 +382,7 @@ class _BillsPageState extends State with SingleTickerProviderStateMix final amount = double.tryParse(record['amount']?.toString() ?? '0') ?? 0; final status = record['status'] as int? ?? 0; - // status: 0=待领取, 1=已领取, 2=已过期 + // status: 0=待领取, 1=已领取, 2=未达标 String statusText; Color statusColor; switch (status) { @@ -349,7 +391,7 @@ class _BillsPageState extends State with SingleTickerProviderStateMix statusColor = context.appColors.up; break; case 2: - statusText = '已过期'; + statusText = '未达标'; statusColor = colorScheme.onSurfaceVariant; break; default: diff --git a/flutter_monisuo/lib/ui/pages/mine/welfare_center_page.dart b/flutter_monisuo/lib/ui/pages/mine/welfare_center_page.dart index 23418ef..51fbd93 100644 --- a/flutter_monisuo/lib/ui/pages/mine/welfare_center_page.dart +++ b/flutter_monisuo/lib/ui/pages/mine/welfare_center_page.dart @@ -355,6 +355,19 @@ class _WelfareCenterPageState extends State { final referralRewards = _welfareData?['referralRewards'] as List? ?? []; + // 汇总统计 + int totalEarned = 0; + int totalClaimable = 0; + for (var r in referralRewards) { + final map = r as Map; + final milestones = map['milestones'] as List? ?? []; + for (var m in milestones) { + final ms = m as Map; + if (ms['claimed'] as bool? ?? false) totalEarned++; + if (ms['claimable'] as bool? ?? false) totalClaimable++; + } + } + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -370,6 +383,29 @@ class _WelfareCenterPageState extends State { color: context.appColors.onSurfaceMuted, ), ), + // 汇总统计 + if (referralRewards.isNotEmpty) ...[ + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm), + decoration: BoxDecoration( + color: context.appColors.surfaceCard, + borderRadius: BorderRadius.circular(AppRadius.md), + border: Border.all(color: context.appColors.ghostBorder), + ), + child: Row( + children: [ + _buildStatItem('已邀请', '${referralRewards.length}人'), + Container(width: 1, height: 20, color: context.appColors.ghostBorder), + _buildStatItem('已获得', '${totalEarned * 100} USDT'), + if (totalClaimable > 0) ...[ + Container(width: 1, height: 20, color: context.appColors.ghostBorder), + _buildStatItem('待领取', '$totalClaimable个', highlight: true), + ], + ], + ), + ), + ], const SizedBox(height: 12), // 推广列表卡片 @@ -384,6 +420,23 @@ class _WelfareCenterPageState extends State { ); } + Widget _buildStatItem(String label, String value, {bool highlight = false}) { + return Expanded( + child: Column( + children: [ + Text(label, style: AppTextStyles.bodySmall(context).copyWith( + color: context.colors.onSurfaceVariant, + )), + const SizedBox(height: 2), + Text(value, style: AppTextStyles.headlineSmall(context).copyWith( + fontWeight: FontWeight.w700, + color: highlight ? context.appColors.up : context.colors.onSurface, + )), + ], + ), + ); + } + Widget _buildEmptyReferralList(BuildContext context) { return Padding( padding: const EdgeInsets.all(32), @@ -416,6 +469,7 @@ class _WelfareCenterPageState extends State { final totalDeposit = data['totalDeposit']?.toString() ?? '0'; final claimableCount = data['claimableCount'] as int? ?? 0; final milestones = data['milestones'] as List? ?? []; + final userId = data['userId'] as int? ?? 0; final isLast = index == referralRewards.length - 1; // 进度计算 @@ -446,7 +500,7 @@ class _WelfareCenterPageState extends State { Text( username, style: AppTextStyles.headlineSmall(context).copyWith( - fontWeight: FontWeight.w500, // 添加 w500 + fontWeight: FontWeight.w500, ), ), const SizedBox(width: 10), @@ -472,6 +526,11 @@ class _WelfareCenterPageState extends State { ), ), ), + // 里程碑详情 + if (milestones.isNotEmpty) ...[ + const SizedBox(height: 12), + _buildMilestoneDetails(milestones, userId), + ], ], ), ), @@ -487,6 +546,66 @@ class _WelfareCenterPageState extends State { ); } + /// 里程碑详情行 — 显示每个里程碑状态 + Widget _buildMilestoneDetails(List milestones, int userId) { + final upColor = context.appColors.up; + + return Wrap( + spacing: 6, + runSpacing: 6, + children: milestones.map((m) { + final ms = m as Map; + final milestoneVal = ms['milestone'] as int? ?? 1; + final earned = ms['earned'] as bool? ?? false; + final claimed = ms['claimed'] as bool? ?? false; + final claimable = ms['claimable'] as bool? ?? false; + final threshold = ms['threshold']?.toString() ?? '${milestoneVal * 1000}'; + + Color bgColor; + Color textColor; + String label; + + if (claimed) { + bgColor = upColor.withValues(alpha: 0.1); + textColor = upColor; + label = '${threshold}✓'; + } else if (claimable) { + bgColor = context.appColors.accentPrimary.withValues(alpha: 0.15); + textColor = context.appColors.accentPrimary; + label = '${threshold}🎁'; + } else if (earned) { + bgColor = upColor.withValues(alpha: 0.06); + textColor = upColor; + label = '${threshold}'; + } else { + bgColor = context.appColors.surfaceCardHigh; + textColor = context.colors.onSurfaceVariant; + label = '${threshold}'; + } + + return GestureDetector( + onTap: claimable ? () => _claimReferralBonus(userId, milestoneVal) : null, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: bgColor, + borderRadius: BorderRadius.circular(AppRadius.sm), + border: claimable ? Border.all(color: textColor.withValues(alpha: 0.3)) : null, + ), + child: Text( + label, + style: AppTextStyles.bodySmall(context).copyWith( + fontSize: 11, + fontWeight: FontWeight.w600, + color: textColor, + ), + ), + ), + ); + }).toList(), + ); + } + Widget _buildAvatar(String username) { return Container( width: 32,