From 2745995a1a04f9ea6d90fc78840d3025c917e091 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 19 Jan 2026 19:32:06 -0800 Subject: [PATCH] =?UTF-8?q?feat(frontend):=20=E8=B4=A1=E7=8C=AE=E5=80=BC?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=AE=8C=E6=95=B4=E6=94=AF=E6=8C=81=E6=B7=B1?= =?UTF-8?q?=E8=89=B2=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 所有卡片背景使用 AppColors.cardOf(context) 动态颜色 - 所有文字颜色改用动态方法 textPrimaryOf/textSecondaryOf/textMutedOf - 图标背景透明度根据深色模式调整 (isDark ? 0.2 : 0.1) - 分隔线和边框使用 AppColors.borderOf(context) - 移除未使用的静态颜色常量 Co-Authored-By: Claude Opus 4.5 --- .../pages/contribution/contribution_page.dart | 177 ++++++++++-------- 1 file changed, 96 insertions(+), 81 deletions(-) diff --git a/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart b/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart index 5edf0fe9..be8df5a6 100644 --- a/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart +++ b/frontend/mining-app/lib/presentation/pages/contribution/contribution_page.dart @@ -16,12 +16,6 @@ class ContributionPage extends ConsumerWidget { static const Color _orange = AppColors.orange; static const Color _green = AppColors.primary; - // 浅色模式设计色彩(保持原有配色) - static const Color _grayText = Color(0xFF6B7280); - static const Color _darkText = Color(0xFF1F2937); - static const Color _bgGray = Color(0xFFF3F4F6); - static const Color _lightGray = Color(0xFFF9FAFB); - @override Widget build(BuildContext context, WidgetRef ref) { final user = ref.watch(userNotifierProvider); @@ -78,22 +72,22 @@ class ContributionPage extends ConsumerWidget { sliver: SliverList( delegate: SliverChildListDelegate([ // 总贡献值卡片 - _buildTotalContributionCard(ref, contribution, isLoading, sharePoolBalance, isSharePoolLoading), + _buildTotalContributionCard(context, ref, contribution, isLoading, sharePoolBalance, isSharePoolLoading), const SizedBox(height: 16), // 三栏统计 - _buildThreeColumnStats(ref, contribution, isLoading), + _buildThreeColumnStats(context, ref, contribution, isLoading), const SizedBox(height: 16), // 今日预估收益 - _buildTodayEstimateCard(ref, estimatedEarnings, isLoading || isStatsLoading), + _buildTodayEstimateCard(context, ref, estimatedEarnings, isLoading || isStatsLoading), const SizedBox(height: 16), // 贡献值明细(三类汇总) _buildContributionDetailCard(context, ref, contribution, isLoading), const SizedBox(height: 16), // 团队下贡献值统计 - _buildTeamStatsCard(contribution, isLoading), + _buildTeamStatsCard(context, contribution, isLoading), const SizedBox(height: 16), // 贡献值失效倒计时 - _buildExpirationCard(contribution, isLoading), + _buildExpirationCard(context, contribution, isLoading), const SizedBox(height: 24), ]), ), @@ -106,8 +100,9 @@ class ContributionPage extends ConsumerWidget { } Widget _buildAppBar(BuildContext context) { + final isDark = AppColors.isDark(context); return Container( - color: _lightGray, + color: AppColors.cardOf(context), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ @@ -116,32 +111,32 @@ class ContributionPage extends ConsumerWidget { width: 32, height: 32, decoration: BoxDecoration( - color: _orange.withOpacity(0.1), + color: _orange.withOpacity(isDark ? 0.2 : 0.1), borderRadius: BorderRadius.circular(8), ), child: const Icon(Icons.eco, color: _orange, size: 20), ), const SizedBox(width: 8), - const Text( + Text( '股行', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, - color: _darkText, + color: AppColors.textPrimaryOf(context), letterSpacing: 0.45, ), ), const Spacer(), // 客服 IconButton( - icon: const Icon(Icons.headset_mic_outlined, color: _grayText), + icon: Icon(Icons.headset_mic_outlined, color: AppColors.textSecondaryOf(context)), onPressed: () {}, ), // 通知(带红点) Stack( children: [ IconButton( - icon: const Icon(Icons.notifications_outlined, color: _grayText), + icon: Icon(Icons.notifications_outlined, color: AppColors.textSecondaryOf(context)), onPressed: () {}, ), Positioned( @@ -164,18 +159,20 @@ class ContributionPage extends ConsumerWidget { } Widget _buildTotalContributionCard( + BuildContext context, WidgetRef ref, Contribution? contribution, bool isLoading, SharePoolBalance? sharePoolBalance, bool isSharePoolLoading, ) { + final isDark = AppColors.isDark(context); final total = contribution?.totalContribution ?? '0'; final hideAmounts = ref.watch(hideAmountsProvider); return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.cardOf(context), borderRadius: BorderRadius.circular(16), ), child: Column( @@ -184,9 +181,9 @@ class ContributionPage extends ConsumerWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Text( + Text( '总贡献值', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _grayText), + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.textSecondaryOf(context)), ), GestureDetector( onTap: () { @@ -194,7 +191,7 @@ class ContributionPage extends ConsumerWidget { }, child: Icon( hideAmounts ? Icons.visibility_off_outlined : Icons.visibility_outlined, - color: _grayText.withOpacity(0.5), + color: AppColors.textMutedOf(context), size: 18, ), ), @@ -218,7 +215,7 @@ class ContributionPage extends ConsumerWidget { children: [ Text( '积分股池实时余量: ', - style: TextStyle(fontSize: 12, color: _grayText.withOpacity(0.9)), + style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)), ), isSharePoolLoading ? const ShimmerText( @@ -236,17 +233,17 @@ class ContributionPage extends ConsumerWidget { Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( - color: _lightGray, + color: isDark ? AppColors.backgroundOf(context) : const Color(0xFFF9FAFB), borderRadius: BorderRadius.circular(999), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon(Icons.info_outline, size: 14, color: _grayText.withOpacity(0.7)), + Icon(Icons.info_outline, size: 14, color: AppColors.textMutedOf(context)), const SizedBox(width: 6), Text( '贡献值有效期: 730 天', - style: TextStyle(fontSize: 12, color: _grayText.withOpacity(0.9)), + style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)), ), ], ), @@ -256,42 +253,42 @@ class ContributionPage extends ConsumerWidget { ); } - Widget _buildThreeColumnStats(WidgetRef ref, Contribution? contribution, bool isLoading) { + Widget _buildThreeColumnStats(BuildContext context, WidgetRef ref, Contribution? contribution, bool isLoading) { final hideAmounts = ref.watch(hideAmountsProvider); return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.cardOf(context), borderRadius: BorderRadius.circular(16), ), child: Row( children: [ - _buildStatColumn('个人贡献值', contribution?.personalContribution, isLoading, false, hideAmounts), - _buildStatColumn('团队下贡献值', contribution?.teamLevelContribution, isLoading, true, hideAmounts), - _buildStatColumn('团队上贡献值', contribution?.teamBonusContribution, isLoading, true, hideAmounts), + _buildStatColumn(context, '个人贡献值', contribution?.personalContribution, isLoading, false, hideAmounts), + _buildStatColumn(context, '团队下贡献值', contribution?.teamLevelContribution, isLoading, true, hideAmounts), + _buildStatColumn(context, '团队上贡献值', contribution?.teamBonusContribution, isLoading, true, hideAmounts), ], ), ); } - Widget _buildStatColumn(String label, String? value, bool isLoading, bool showLeftBorder, bool hideAmounts) { + Widget _buildStatColumn(BuildContext context, String label, String? value, bool isLoading, bool showLeftBorder, bool hideAmounts) { return Expanded( child: Container( decoration: showLeftBorder - ? const BoxDecoration( - border: Border(left: BorderSide(color: Color(0xFFE5E7EB), width: 1)), + ? BoxDecoration( + border: Border(left: BorderSide(color: AppColors.borderOf(context), width: 1)), ) : null, padding: const EdgeInsets.symmetric(horizontal: 4), child: Column( children: [ - Text(label, style: const TextStyle(fontSize: 12, color: _grayText)), + Text(label, style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context))), const SizedBox(height: 4), DataText( data: value != null ? (hideAmounts ? '****' : formatAmount(value)) : null, isLoading: isLoading, placeholder: '--', - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: _darkText), + style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: AppColors.textPrimaryOf(context)), textAlign: TextAlign.center, ), ], @@ -300,12 +297,13 @@ class ContributionPage extends ConsumerWidget { ); } - Widget _buildTodayEstimateCard(WidgetRef ref, EstimatedEarnings earnings, bool isLoading) { + Widget _buildTodayEstimateCard(BuildContext context, WidgetRef ref, EstimatedEarnings earnings, bool isLoading) { + final isDark = AppColors.isDark(context); final hideAmounts = ref.watch(hideAmountsProvider); return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.cardOf(context), borderRadius: BorderRadius.circular(16), ), child: Row( @@ -315,7 +313,7 @@ class ContributionPage extends ConsumerWidget { width: 40, height: 40, decoration: BoxDecoration( - color: _green.withOpacity(0.1), + color: _green.withOpacity(isDark ? 0.2 : 0.1), borderRadius: BorderRadius.circular(12), ), child: const Icon(Icons.trending_up, color: _green, size: 24), @@ -326,13 +324,13 @@ class ContributionPage extends ConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( '今日预估收益', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _grayText), + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.textSecondaryOf(context)), ), Text( '基于当前贡献值占比计算', - style: TextStyle(fontSize: 12, color: _grayText.withOpacity(0.7)), + style: TextStyle(fontSize: 12, color: AppColors.textMutedOf(context)), ), ], ), @@ -377,11 +375,12 @@ class ContributionPage extends ConsumerWidget { Contribution? contribution, bool isLoading, ) { + final isDark = AppColors.isDark(context); final hideAmounts = ref.watch(hideAmountsProvider); return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.cardOf(context), borderRadius: BorderRadius.circular(16), ), child: Column( @@ -390,9 +389,9 @@ class ContributionPage extends ConsumerWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Text( + Text( '贡献值明细', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _darkText), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: AppColors.textPrimaryOf(context)), ), GestureDetector( onTap: () { @@ -410,11 +409,13 @@ class ContributionPage extends ConsumerWidget { const SizedBox(height: 16), // 三类汇总 if (isLoading) - _buildDetailSummaryShimmer() + _buildDetailSummaryShimmer(context) else Column( children: [ _buildDetailSummaryRow( + context: context, + isDark: isDark, icon: Icons.eco_outlined, iconColor: _orange, title: '本人', @@ -422,8 +423,10 @@ class ContributionPage extends ConsumerWidget { amount: contribution?.personalContribution ?? '0', hideAmounts: hideAmounts, ), - const Divider(height: 24), + Divider(height: 24, color: AppColors.borderOf(context)), _buildDetailSummaryRow( + context: context, + isDark: isDark, icon: Icons.groups_outlined, iconColor: Colors.blue, title: '团队下贡献值', @@ -431,8 +434,10 @@ class ContributionPage extends ConsumerWidget { amount: contribution?.teamLevelContribution ?? '0', hideAmounts: hideAmounts, ), - const Divider(height: 24), + Divider(height: 24, color: AppColors.borderOf(context)), _buildDetailSummaryRow( + context: context, + isDark: isDark, icon: Icons.card_giftcard_outlined, iconColor: Colors.purple, title: '团队上贡献值', @@ -447,19 +452,19 @@ class ContributionPage extends ConsumerWidget { ); } - Widget _buildDetailSummaryShimmer() { + Widget _buildDetailSummaryShimmer(BuildContext context) { return Column( children: [ - _buildShimmerSummaryRow(), - const Divider(height: 24), - _buildShimmerSummaryRow(), - const Divider(height: 24), - _buildShimmerSummaryRow(), + _buildShimmerSummaryRow(context), + Divider(height: 24, color: AppColors.borderOf(context)), + _buildShimmerSummaryRow(context), + Divider(height: 24, color: AppColors.borderOf(context)), + _buildShimmerSummaryRow(context), ], ); } - Widget _buildShimmerSummaryRow() { + Widget _buildShimmerSummaryRow(BuildContext context) { return Row( children: [ const ShimmerBox(width: 40, height: 40), @@ -467,15 +472,15 @@ class ContributionPage extends ConsumerWidget { Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: const [ + children: [ ShimmerText( placeholder: '本人', - style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _darkText), + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.textPrimaryOf(context)), ), - SizedBox(height: 2), + const SizedBox(height: 2), ShimmerText( placeholder: '个人参与产生的贡献值', - style: TextStyle(fontSize: 12, color: _grayText), + style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)), ), ], ), @@ -489,6 +494,8 @@ class ContributionPage extends ConsumerWidget { } Widget _buildDetailSummaryRow({ + required BuildContext context, + required bool isDark, required IconData icon, required Color iconColor, required String title, @@ -502,7 +509,7 @@ class ContributionPage extends ConsumerWidget { width: 40, height: 40, decoration: BoxDecoration( - color: iconColor.withOpacity(0.1), + color: iconColor.withOpacity(isDark ? 0.2 : 0.1), borderRadius: BorderRadius.circular(10), ), child: Icon(icon, color: iconColor, size: 22), @@ -514,12 +521,12 @@ class ContributionPage extends ConsumerWidget { children: [ Text( title, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: _darkText), + style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.textPrimaryOf(context)), ), const SizedBox(height: 2), Text( subtitle, - style: TextStyle(fontSize: 11, color: _grayText.withOpacity(0.8)), + style: TextStyle(fontSize: 11, color: AppColors.textMutedOf(context)), ), ], ), @@ -532,25 +539,26 @@ class ContributionPage extends ConsumerWidget { ); } - Widget _buildTeamStatsCard(Contribution? contribution, bool isLoading) { + Widget _buildTeamStatsCard(BuildContext context, Contribution? contribution, bool isLoading) { return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.cardOf(context), borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + Text( '团队下贡献值统计', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _darkText), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: AppColors.textPrimaryOf(context)), ), const SizedBox(height: 16), // 第一行 Row( children: [ _buildTeamStatItem( + context, '引荐人数', contribution?.directReferralAdoptedCount.toString(), '人', @@ -558,6 +566,7 @@ class ContributionPage extends ConsumerWidget { ), const SizedBox(width: 16), _buildTeamStatItem( + context, '已解锁上级', '15', '', @@ -570,6 +579,7 @@ class ContributionPage extends ConsumerWidget { Row( children: [ _buildTeamStatItem( + context, '已解锁下级', contribution?.unlockedLevelDepth.toString(), '', @@ -577,6 +587,7 @@ class ContributionPage extends ConsumerWidget { ), const SizedBox(width: 16), _buildTeamStatItem( + context, '是否参与', contribution != null ? (contribution.hasAdopted == true ? '是' : '否') : null, '', @@ -589,18 +600,19 @@ class ContributionPage extends ConsumerWidget { ); } - Widget _buildTeamStatItem(String label, String? value, String unit, bool isLoading) { + Widget _buildTeamStatItem(BuildContext context, String label, String? value, String unit, bool isLoading) { + final isDark = AppColors.isDark(context); return Expanded( child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: _bgGray, + color: isDark ? AppColors.backgroundOf(context) : const Color(0xFFF3F4F6), borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(label, style: const TextStyle(fontSize: 12, color: _grayText)), + Text(label, style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context))), const SizedBox(height: 4), isLoading ? ShimmerText( @@ -617,7 +629,7 @@ class ContributionPage extends ConsumerWidget { if (unit.isNotEmpty) TextSpan( text: unit, - style: const TextStyle(fontSize: 12, color: _grayText), + style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)), ), ], ), @@ -629,9 +641,11 @@ class ContributionPage extends ConsumerWidget { } Widget _buildExpirationCard( + BuildContext context, Contribution? contribution, bool isLoading, ) { + final isDark = AppColors.isDark(context); // 贡献值有效期为2年(730天) // 暂时使用固定信息,后续可从后端获取最近过期日期 const int validityDays = 730; @@ -643,24 +657,25 @@ class ContributionPage extends ConsumerWidget { ? '贡献值自生效日起 $validityDays 天内有效' : '暂无贡献值'; final double progress = hasContribution ? 1.0 : 0.0; + final bgGrayColor = isDark ? AppColors.backgroundOf(context) : const Color(0xFFF3F4F6); return Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( - color: Colors.white, + color: AppColors.cardOf(context), borderRadius: BorderRadius.circular(16), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题 - const Row( + Row( children: [ - Icon(Icons.timer_outlined, color: _orange, size: 24), - SizedBox(width: 8), + const Icon(Icons.timer_outlined, color: _orange, size: 24), + const SizedBox(width: 8), Text( '贡献值失效倒计时', - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: _darkText), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: AppColors.textPrimaryOf(context)), ), ], ), @@ -671,22 +686,22 @@ class ContributionPage extends ConsumerWidget { child: LinearProgressIndicator( value: isLoading ? 1.0 : progress, minHeight: 10, - backgroundColor: _bgGray, + backgroundColor: bgGrayColor, valueColor: AlwaysStoppedAnimation( - isLoading ? _bgGray : _orange, + isLoading ? bgGrayColor : _orange, ), ), ), const SizedBox(height: 12), // 说明文字 isLoading - ? const ShimmerText( + ? ShimmerText( placeholder: '贡献值有效期信息加载中...', - style: TextStyle(fontSize: 12, color: _grayText), + style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)), ) : Text( expireDateText, - style: const TextStyle(fontSize: 12, color: _grayText), + style: TextStyle(fontSize: 12, color: AppColors.textSecondaryOf(context)), ), const SizedBox(height: 4), isLoading @@ -694,9 +709,9 @@ class ContributionPage extends ConsumerWidget { placeholder: '有效期 --- 天', style: TextStyle(fontSize: 12, color: _orange, fontWeight: FontWeight.w500), ) - : Text( + : const Text( '有效期 $validityDays 天', - style: const TextStyle(fontSize: 12, color: _orange, fontWeight: FontWeight.w500), + style: TextStyle(fontSize: 12, color: _orange, fontWeight: FontWeight.w500), ), ], ),