refactor(profile): 重新实现深色模式,保留原有浅色模式配色

问题:之前的深色模式实现使用了 colorScheme,导致浅色模式的原有配色也被改变

修复方案:
- 定义浅色/深色两套色彩常量,浅色模式使用原有设计色值
- 添加基于 Theme.brightness 的颜色辅助函数动态返回对应颜色
- 浅色模式:保持原有 #1F2937/#6B7280/#9CA3AF/#F3F4F6/白色配色
- 深色模式:使用 #E5E7EB/#9CA3AF/#6B7280/#111827/#1F2937 配色
- 所有 widget 方法更新为使用动态颜色函数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-19 18:44:31 -08:00
parent d8df50a68f
commit b00de68b01
1 changed files with 92 additions and 66 deletions

View File

@ -15,6 +15,32 @@ class ProfilePage extends ConsumerWidget {
static const Color _green = Color(0xFF10B981); static const Color _green = Color(0xFF10B981);
static const Color _red = Color(0xFFEF4444); static const Color _red = Color(0xFFEF4444);
//
static const Color _lightDarkText = Color(0xFF1F2937);
static const Color _lightGrayText = Color(0xFF6B7280);
static const Color _lightLightGray = Color(0xFF9CA3AF);
static const Color _lightBgGray = Color(0xFFF3F4F6);
static const Color _lightCardBg = Colors.white;
//
static const Color _darkDarkText = Color(0xFFE5E7EB);
static const Color _darkGrayText = Color(0xFF9CA3AF);
static const Color _darkLightGray = Color(0xFF6B7280);
static const Color _darkBgGray = Color(0xFF111827);
static const Color _darkCardBg = Color(0xFF1F2937);
///
static Color _darkText(BuildContext context) =>
Theme.of(context).brightness == Brightness.dark ? _darkDarkText : _lightDarkText;
static Color _grayText(BuildContext context) =>
Theme.of(context).brightness == Brightness.dark ? _darkGrayText : _lightGrayText;
static Color _lightGray(BuildContext context) =>
Theme.of(context).brightness == Brightness.dark ? _darkLightGray : _lightLightGray;
static Color _bgGray(BuildContext context) =>
Theme.of(context).brightness == Brightness.dark ? _darkBgGray : _lightBgGray;
static Color _cardBg(BuildContext context) =>
Theme.of(context).brightness == Brightness.dark ? _darkCardBg : _lightCardBg;
// //
static const List<Color> _avatarColors = [ static const List<Color> _avatarColors = [
Color(0xFFFF6B00), // Color(0xFFFF6B00), //
@ -31,13 +57,12 @@ class ProfilePage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userNotifierProvider); final user = ref.watch(userNotifierProvider);
final statsAsync = ref.watch(userStatsProvider); final statsAsync = ref.watch(userStatsProvider);
final colorScheme = Theme.of(context).colorScheme;
final isStatsLoading = statsAsync.isLoading; final isStatsLoading = statsAsync.isLoading;
final stats = statsAsync.valueOrNull; final stats = statsAsync.valueOrNull;
return Scaffold( return Scaffold(
backgroundColor: colorScheme.surfaceContainerHighest, backgroundColor: _bgGray(context),
body: SafeArea( body: SafeArea(
bottom: false, bottom: false,
child: RefreshIndicator( child: RefreshIndicator(
@ -50,36 +75,37 @@ class ProfilePage extends ConsumerWidget {
child: Column( child: Column(
children: [ children: [
// //
_buildUserHeader(context, user, colorScheme), _buildUserHeader(context, user),
const SizedBox(height: 16), const SizedBox(height: 16),
// //
_buildStatsRow(context, stats, isStatsLoading, colorScheme), _buildStatsRow(context, stats, isStatsLoading),
const SizedBox(height: 16), const SizedBox(height: 16),
// //
_buildAccountSettings(context, user, colorScheme), _buildAccountSettings(context, user),
const SizedBox(height: 16), const SizedBox(height: 16),
// //
_buildRecordsSection(context, colorScheme), _buildRecordsSection(context),
const SizedBox(height: 16), const SizedBox(height: 16),
// //
// _buildTeamEarningsSection(context, colorScheme), _buildTeamEarningsSection(context),
// const SizedBox(height: 16),
const SizedBox(height: 16),
// //
_buildOtherSettings(context, ref, colorScheme), _buildOtherSettings(context, ref),
const SizedBox(height: 24), const SizedBox(height: 24),
// 退 // 退
_buildLogoutButton(context, ref, colorScheme), _buildLogoutButton(context, ref),
const SizedBox(height: 16), const SizedBox(height: 16),
@ -88,7 +114,7 @@ class ProfilePage extends ConsumerWidget {
'Version 1.0.0', 'Version 1.0.0',
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: colorScheme.outline, color: _lightGray(context),
), ),
), ),
@ -101,12 +127,12 @@ class ProfilePage extends ConsumerWidget {
); );
} }
Widget _buildUserHeader(BuildContext context, UserState user, ColorScheme colorScheme) { Widget _buildUserHeader(BuildContext context, UserState user) {
final avatarColor = _avatarColors[user.avatarIndex % _avatarColors.length]; final avatarColor = _avatarColors[user.avatarIndex % _avatarColors.length];
return Container( return Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
color: colorScheme.surface, color: _cardBg(context),
child: Row( child: Row(
children: [ children: [
// //
@ -156,7 +182,7 @@ class ProfilePage extends ConsumerWidget {
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
@ -196,7 +222,7 @@ class ProfilePage extends ConsumerWidget {
'ID: ${user.phone}', 'ID: ${user.phone}',
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: colorScheme.onSurfaceVariant, color: _grayText(context),
), ),
), ),
], ],
@ -208,7 +234,7 @@ class ProfilePage extends ConsumerWidget {
onPressed: () => context.push(Routes.editProfile), onPressed: () => context.push(Routes.editProfile),
icon: Icon( icon: Icon(
Icons.edit_outlined, Icons.edit_outlined,
color: colorScheme.onSurfaceVariant, color: _grayText(context),
), ),
), ),
], ],
@ -216,46 +242,46 @@ class ProfilePage extends ConsumerWidget {
); );
} }
Widget _buildStatsRow(BuildContext context, UserStats? stats, bool isLoading, ColorScheme colorScheme) { Widget _buildStatsRow(BuildContext context, UserStats? stats, bool isLoading) {
return Container( return Container(
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
color: colorScheme.surface, color: _cardBg(context),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
_buildStatItem( _buildStatItem(
context,
'参与状态', '参与状态',
stats?.hasAdopted == true ? '已参与' : '未参与', stats?.hasAdopted == true ? '已参与' : '未参与',
isLoading, isLoading,
colorScheme,
), ),
_buildDivider(colorScheme), _buildDivider(context),
_buildStatItem( _buildStatItem(
context,
'引荐人数', '引荐人数',
stats?.directReferralAdoptedCount.toString() ?? '0', stats?.directReferralAdoptedCount.toString() ?? '0',
isLoading, isLoading,
colorScheme,
), ),
_buildDivider(colorScheme), _buildDivider(context),
_buildStatItem( _buildStatItem(
context,
'团队下贡献值', '团队下贡献值',
stats?.unlockedLevelDepth.toString() ?? '0', stats?.unlockedLevelDepth.toString() ?? '0',
isLoading, isLoading,
colorScheme,
), ),
_buildDivider(colorScheme), _buildDivider(context),
_buildStatItem( _buildStatItem(
context,
'团队上贡献值', '团队上贡献值',
'15', '15',
isLoading, isLoading,
colorScheme,
), ),
], ],
), ),
); );
} }
Widget _buildStatItem(String label, String value, bool isLoading, ColorScheme colorScheme) { Widget _buildStatItem(BuildContext context, String label, String value, bool isLoading) {
return Column( return Column(
children: [ children: [
DataText( DataText(
@ -265,7 +291,7 @@ class ProfilePage extends ConsumerWidget {
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
@ -273,26 +299,26 @@ class ProfilePage extends ConsumerWidget {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: colorScheme.onSurfaceVariant, color: _grayText(context),
), ),
), ),
], ],
); );
} }
Widget _buildDivider(ColorScheme colorScheme) { Widget _buildDivider(BuildContext context) {
return Container( return Container(
width: 1, width: 1,
height: 30, height: 30,
color: colorScheme.outlineVariant, color: _bgGray(context),
); );
} }
Widget _buildAccountSettings(BuildContext context, UserState user, ColorScheme colorScheme) { Widget _buildAccountSettings(BuildContext context, UserState user) {
return Container( return Container(
margin: const EdgeInsets.symmetric(horizontal: 16), margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.surface, color: _cardBg(context),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Column( child: Column(
@ -305,16 +331,16 @@ class ProfilePage extends ConsumerWidget {
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
), ),
_buildSettingItem( _buildSettingItem(
context: context,
icon: Icons.security, icon: Icons.security,
label: '账户安全', label: '账户安全',
onTap: () => context.push(Routes.changePassword), onTap: () => context.push(Routes.changePassword),
showDivider: false, showDivider: false,
colorScheme: colorScheme,
), ),
], ],
), ),
@ -322,22 +348,22 @@ class ProfilePage extends ConsumerWidget {
} }
Widget _buildSettingItem({ Widget _buildSettingItem({
required BuildContext context,
required IconData icon, required IconData icon,
required String label, required String label,
Widget? trailing, Widget? trailing,
required VoidCallback onTap, required VoidCallback onTap,
bool showDivider = true, bool showDivider = true,
required ColorScheme colorScheme,
}) { }) {
return Column( return Column(
children: [ children: [
ListTile( ListTile(
leading: Icon(icon, color: colorScheme.onSurfaceVariant, size: 22), leading: Icon(icon, color: _grayText(context), size: 22),
title: Text( title: Text(
label, label,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
trailing: Row( trailing: Row(
@ -345,7 +371,7 @@ class ProfilePage extends ConsumerWidget {
children: [ children: [
if (trailing != null) trailing, if (trailing != null) trailing,
if (trailing != null) const SizedBox(width: 8), if (trailing != null) const SizedBox(width: 8),
Icon(Icons.chevron_right, color: colorScheme.outline, size: 20), Icon(Icons.chevron_right, color: _lightGray(context), size: 20),
], ],
), ),
onTap: onTap, onTap: onTap,
@ -356,12 +382,12 @@ class ProfilePage extends ConsumerWidget {
); );
} }
Widget _buildRecordsSection(BuildContext context, ColorScheme colorScheme) { Widget _buildRecordsSection(BuildContext context) {
return Container( return Container(
margin: const EdgeInsets.symmetric(horizontal: 16), margin: const EdgeInsets.symmetric(horizontal: 16),
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.surface, color: _cardBg(context),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Column( child: Column(
@ -372,7 +398,7 @@ class ProfilePage extends ConsumerWidget {
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
@ -380,22 +406,22 @@ class ProfilePage extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [ children: [
_buildRecordIcon( _buildRecordIcon(
context: context,
icon: Icons.eco, icon: Icons.eco,
label: '参与记录', label: '参与记录',
onTap: () => context.push(Routes.plantingRecords), onTap: () => context.push(Routes.plantingRecords),
colorScheme: colorScheme,
), ),
_buildRecordIcon( _buildRecordIcon(
context: context,
icon: Icons.assignment, icon: Icons.assignment,
label: '分配记录', label: '分配记录',
onTap: () => context.push(Routes.miningRecords), onTap: () => context.push(Routes.miningRecords),
colorScheme: colorScheme,
), ),
_buildRecordIcon( _buildRecordIcon(
context: context,
icon: Icons.receipt_long, icon: Icons.receipt_long,
label: '交易记录', label: '交易记录',
onTap: () => context.push(Routes.tradingRecords), onTap: () => context.push(Routes.tradingRecords),
colorScheme: colorScheme,
), ),
], ],
), ),
@ -405,10 +431,10 @@ class ProfilePage extends ConsumerWidget {
} }
Widget _buildRecordIcon({ Widget _buildRecordIcon({
required BuildContext context,
required IconData icon, required IconData icon,
required String label, required String label,
required VoidCallback onTap, required VoidCallback onTap,
required ColorScheme colorScheme,
}) { }) {
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
@ -429,7 +455,7 @@ class ProfilePage extends ConsumerWidget {
label, label,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: colorScheme.onSurfaceVariant, color: _grayText(context),
), ),
), ),
], ],
@ -437,11 +463,11 @@ class ProfilePage extends ConsumerWidget {
); );
} }
Widget _buildTeamEarningsSection(BuildContext context, ColorScheme colorScheme) { Widget _buildTeamEarningsSection(BuildContext context) {
return Container( return Container(
margin: const EdgeInsets.symmetric(horizontal: 16), margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.surface, color: _cardBg(context),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Column( child: Column(
@ -454,30 +480,30 @@ class ProfilePage extends ConsumerWidget {
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
), ),
_buildSettingItem( _buildSettingItem(
context: context,
icon: Icons.people, icon: Icons.people,
label: '我的团队', label: '我的团队',
onTap: () => context.push(Routes.myTeam), onTap: () => context.push(Routes.myTeam),
showDivider: false, showDivider: false,
colorScheme: colorScheme,
), ),
], ],
), ),
); );
} }
Widget _buildOtherSettings(BuildContext context, WidgetRef ref, ColorScheme colorScheme) { Widget _buildOtherSettings(BuildContext context, WidgetRef ref) {
final notificationsEnabled = ref.watch(notificationsEnabledProvider); final notificationsEnabled = ref.watch(notificationsEnabledProvider);
final darkModeEnabled = ref.watch(darkModeEnabledProvider); final darkModeEnabled = ref.watch(darkModeEnabledProvider);
return Container( return Container(
margin: const EdgeInsets.symmetric(horizontal: 16), margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colorScheme.surface, color: _cardBg(context),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Column( child: Column(
@ -490,40 +516,40 @@ class ProfilePage extends ConsumerWidget {
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
), ),
_buildSwitchItem( _buildSwitchItem(
context: context,
icon: Icons.notifications_outlined, icon: Icons.notifications_outlined,
label: '消息通知', label: '消息通知',
value: notificationsEnabled, value: notificationsEnabled,
onChanged: (value) { onChanged: (value) {
ref.read(notificationsEnabledProvider.notifier).setEnabled(value); ref.read(notificationsEnabledProvider.notifier).setEnabled(value);
}, },
colorScheme: colorScheme,
), ),
_buildSwitchItem( _buildSwitchItem(
context: context,
icon: Icons.dark_mode_outlined, icon: Icons.dark_mode_outlined,
label: '深色模式', label: '深色模式',
value: darkModeEnabled, value: darkModeEnabled,
onChanged: (value) { onChanged: (value) {
ref.read(darkModeEnabledProvider.notifier).setEnabled(value); ref.read(darkModeEnabledProvider.notifier).setEnabled(value);
}, },
colorScheme: colorScheme,
), ),
_buildSettingItem( _buildSettingItem(
context: context,
icon: Icons.help_outline, icon: Icons.help_outline,
label: '帮助中心', label: '帮助中心',
onTap: () => context.push(Routes.helpCenter), onTap: () => context.push(Routes.helpCenter),
colorScheme: colorScheme,
), ),
_buildSettingItem( _buildSettingItem(
context: context,
icon: Icons.info_outline, icon: Icons.info_outline,
label: '关于我们', label: '关于我们',
onTap: () => context.push(Routes.about), onTap: () => context.push(Routes.about),
showDivider: false, showDivider: false,
colorScheme: colorScheme,
), ),
], ],
), ),
@ -531,21 +557,21 @@ class ProfilePage extends ConsumerWidget {
} }
Widget _buildSwitchItem({ Widget _buildSwitchItem({
required BuildContext context,
required IconData icon, required IconData icon,
required String label, required String label,
required bool value, required bool value,
required ValueChanged<bool> onChanged, required ValueChanged<bool> onChanged,
required ColorScheme colorScheme,
}) { }) {
return Column( return Column(
children: [ children: [
ListTile( ListTile(
leading: Icon(icon, color: colorScheme.onSurfaceVariant, size: 22), leading: Icon(icon, color: _grayText(context), size: 22),
title: Text( title: Text(
label, label,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: colorScheme.onSurface, color: _darkText(context),
), ),
), ),
trailing: Switch( trailing: Switch(
@ -560,7 +586,7 @@ class ProfilePage extends ConsumerWidget {
); );
} }
Widget _buildLogoutButton(BuildContext context, WidgetRef ref, ColorScheme colorScheme) { Widget _buildLogoutButton(BuildContext context, WidgetRef ref) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
child: SizedBox( child: SizedBox(
@ -569,17 +595,17 @@ class ProfilePage extends ConsumerWidget {
onPressed: () { onPressed: () {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (dialogContext) => AlertDialog(
title: const Text('退出登录'), title: const Text('退出登录'),
content: const Text('确定要退出登录吗?'), content: const Text('确定要退出登录吗?'),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(dialogContext),
child: const Text('取消'), child: const Text('取消'),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(dialogContext);
ref.read(userNotifierProvider.notifier).logout(); ref.read(userNotifierProvider.notifier).logout();
}, },
child: const Text( child: const Text(
@ -592,7 +618,7 @@ class ProfilePage extends ConsumerWidget {
); );
}, },
style: TextButton.styleFrom( style: TextButton.styleFrom(
backgroundColor: colorScheme.surface, backgroundColor: _cardBg(context),
padding: const EdgeInsets.symmetric(vertical: 14), padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),