diff --git a/frontend/genex-mobile/lib/features/profile/presentation/pages/settings_page.dart b/frontend/genex-mobile/lib/features/profile/presentation/pages/settings_page.dart index 7249d8a..d7930d9 100644 --- a/frontend/genex-mobile/lib/features/profile/presentation/pages/settings_page.dart +++ b/frontend/genex-mobile/lib/features/profile/presentation/pages/settings_page.dart @@ -1,13 +1,30 @@ import 'package:flutter/material.dart'; import '../../../../app/theme/app_colors.dart'; import '../../../../app/theme/app_typography.dart'; +import '../../../../app/theme/app_spacing.dart'; /// 设置页面 /// -/// 账号安全、通知、支付管理、语言、关于 -class SettingsPage extends StatelessWidget { +/// 账号安全、通知、支付管理、语言、货币、关于 +/// 货币选择影响交易页面中的计价货币符号 +class SettingsPage extends StatefulWidget { const SettingsPage({super.key}); + @override + State createState() => _SettingsPageState(); +} + +class _SettingsPageState extends State { + // 当前选中的货币 (实际应用中从持久化/状态管理读取) + _CurrencyOption _selectedCurrency = _currencyOptions[0]; // 默认 USD + String _selectedLanguage = '简体中文'; + + // 通知开关 + bool _notifyTrade = true; + bool _notifyExpiry = true; + bool _notifyMarket = false; + bool _notifyMarketing = false; + @override Widget build(BuildContext context) { return Scaffold( @@ -16,39 +33,59 @@ class SettingsPage extends StatelessWidget { children: [ // Account & Security _buildSection('账号与安全', [ - _buildTile('手机号', subtitle: '138****8888', icon: Icons.phone_rounded), - _buildTile('邮箱', subtitle: 'u***@email.com', icon: Icons.email_rounded), + _buildTile('手机号', + subtitle: '138****8888', icon: Icons.phone_rounded), + _buildTile('邮箱', + subtitle: 'u***@email.com', icon: Icons.email_rounded), _buildTile('修改密码', icon: Icons.lock_rounded), - _buildTile('身份认证', subtitle: 'L1 基础认证', icon: Icons.verified_user_rounded, onTap: () { + _buildTile('身份认证', + subtitle: 'L1 基础认证', + icon: Icons.verified_user_rounded, onTap: () { Navigator.pushNamed(context, '/kyc'); }), ]), // Payment _buildSection('支付管理', [ - _buildTile('支付方式', subtitle: 'Visa •••• 4242', icon: Icons.credit_card_rounded), - _buildTile('银行账户', subtitle: 'BoA •••• 6789', icon: Icons.account_balance_rounded), + _buildTile('支付方式', + subtitle: 'Visa •••• 4242', + icon: Icons.credit_card_rounded), + _buildTile('银行账户', + subtitle: 'BoA •••• 6789', + icon: Icons.account_balance_rounded), _buildTile('支付密码', icon: Icons.password_rounded), ]), // Notifications _buildSection('通知设置', [ - _buildSwitchTile('交易通知', true), - _buildSwitchTile('到期提醒', true), - _buildSwitchTile('行情变动', false), - _buildSwitchTile('营销推送', false), + _buildSwitchTile('交易通知', _notifyTrade, + (v) => setState(() => _notifyTrade = v)), + _buildSwitchTile('到期提醒', _notifyExpiry, + (v) => setState(() => _notifyExpiry = v)), + _buildSwitchTile('行情变动', _notifyMarket, + (v) => setState(() => _notifyMarket = v)), + _buildSwitchTile('营销推送', _notifyMarketing, + (v) => setState(() => _notifyMarketing = v)), ]), // General _buildSection('通用', [ - _buildTile('语言', subtitle: '简体中文', icon: Icons.language_rounded), - _buildTile('货币', subtitle: 'USD', icon: Icons.attach_money_rounded), + _buildTile('语言', + subtitle: _selectedLanguage, + icon: Icons.language_rounded, + onTap: () => _showLanguagePicker(context)), + _buildTile('货币', + subtitle: + '${_selectedCurrency.code} (${_selectedCurrency.symbol})', + icon: Icons.attach_money_rounded, + onTap: () => _showCurrencyPicker(context)), _buildTile('清除缓存', icon: Icons.cleaning_services_rounded), ]), // About _buildSection('关于', [ - _buildTile('版本', subtitle: 'v1.0.0', icon: Icons.info_outline_rounded), + _buildTile('版本', + subtitle: 'v1.0.0', icon: Icons.info_outline_rounded), _buildTile('用户协议', icon: Icons.description_rounded), _buildTile('隐私政策', icon: Icons.privacy_tip_rounded), _buildTile('帮助中心', icon: Icons.help_outline_rounded), @@ -59,7 +96,8 @@ class SettingsPage extends StatelessWidget { padding: const EdgeInsets.all(20), child: OutlinedButton( onPressed: () { - Navigator.of(context).pushNamedAndRemoveUntil('/', (_) => false); + Navigator.of(context) + .pushNamedAndRemoveUntil('/', (_) => false); }, style: OutlinedButton.styleFrom( foregroundColor: AppColors.error, @@ -74,6 +112,152 @@ class SettingsPage extends StatelessWidget { ); } + // ============================================================ + // Currency Picker + // ============================================================ + void _showCurrencyPicker(BuildContext context) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (_) => Container( + decoration: const BoxDecoration( + color: AppColors.surface, + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Handle + Container( + margin: const EdgeInsets.only(top: 12), + width: 36, + height: 4, + decoration: BoxDecoration( + color: AppColors.gray200, + borderRadius: AppSpacing.borderRadiusFull, + ), + ), + // Title + Padding( + padding: const EdgeInsets.all(16), + child: Text('选择计价货币', style: AppTypography.h3), + ), + const Divider(height: 1), + // Currency list + ..._currencyOptions.map((option) { + final isSelected = _selectedCurrency.code == option.code; + return ListTile( + leading: Text(option.flag, style: const TextStyle(fontSize: 24)), + title: Text( + '${option.name} (${option.code})', + style: AppTypography.bodyMedium.copyWith( + fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, + color: isSelected + ? AppColors.primary + : AppColors.textPrimary, + ), + ), + subtitle: Text( + '符号: ${option.symbol}', + style: AppTypography.caption, + ), + trailing: isSelected + ? const Icon(Icons.check_circle_rounded, + color: AppColors.primary, size: 22) + : null, + onTap: () { + setState(() => _selectedCurrency = option); + Navigator.pop(context); + }, + ); + }), + // Note + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 24), + child: Text( + '此设置影响交易页面中所有价格的计价货币显示', + style: AppTypography.caption.copyWith( + color: AppColors.textTertiary, + ), + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ); + } + + // ============================================================ + // Language Picker + // ============================================================ + void _showLanguagePicker(BuildContext context) { + final languages = [ + ('简体中文', 'zh-CN', '🇨🇳'), + ('繁體中文', 'zh-TW', '🇹🇼'), + ('English', 'en', '🇺🇸'), + ('日本語', 'ja', '🇯🇵'), + ]; + + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (_) => Container( + decoration: const BoxDecoration( + color: AppColors.surface, + borderRadius: BorderRadius.vertical(top: Radius.circular(16)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + margin: const EdgeInsets.only(top: 12), + width: 36, + height: 4, + decoration: BoxDecoration( + color: AppColors.gray200, + borderRadius: AppSpacing.borderRadiusFull, + ), + ), + Padding( + padding: const EdgeInsets.all(16), + child: Text('选择语言', style: AppTypography.h3), + ), + const Divider(height: 1), + ...languages.map((lang) { + final (name, _, flag) = lang; + final isSelected = _selectedLanguage == name; + return ListTile( + leading: Text(flag, style: const TextStyle(fontSize: 24)), + title: Text( + name, + style: AppTypography.bodyMedium.copyWith( + fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, + color: isSelected + ? AppColors.primary + : AppColors.textPrimary, + ), + ), + trailing: isSelected + ? const Icon(Icons.check_circle_rounded, + color: AppColors.primary, size: 22) + : null, + onTap: () { + setState(() => _selectedLanguage = name); + Navigator.pop(context); + }, + ); + }), + const SizedBox(height: 24), + ], + ), + ), + ); + } + + // ============================================================ + // Shared Builders + // ============================================================ Widget _buildSection(String title, List children) { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -90,22 +274,55 @@ class SettingsPage extends StatelessWidget { ); } - Widget _buildTile(String title, {String? subtitle, IconData? icon, VoidCallback? onTap}) { + Widget _buildTile(String title, + {String? subtitle, IconData? icon, VoidCallback? onTap}) { return ListTile( - leading: icon != null ? Icon(icon, size: 22, color: AppColors.textSecondary) : null, + leading: icon != null + ? Icon(icon, size: 22, color: AppColors.textSecondary) + : null, title: Text(title, style: AppTypography.bodyMedium), - subtitle: subtitle != null ? Text(subtitle, style: AppTypography.caption) : null, - trailing: const Icon(Icons.chevron_right_rounded, size: 20, color: AppColors.textTertiary), + subtitle: subtitle != null + ? Text(subtitle, style: AppTypography.caption) + : null, + trailing: const Icon(Icons.chevron_right_rounded, + size: 20, color: AppColors.textTertiary), onTap: onTap ?? () {}, ); } - Widget _buildSwitchTile(String title, bool value) { + Widget _buildSwitchTile( + String title, bool value, ValueChanged onChanged) { return SwitchListTile( title: Text(title, style: AppTypography.bodyMedium), value: value, - onChanged: (_) {}, + onChanged: onChanged, activeColor: AppColors.primary, ); } } + +// ============================================================ +// Currency Options +// ============================================================ +class _CurrencyOption { + final String code; + final String symbol; + final String name; + final String flag; + + const _CurrencyOption({ + required this.code, + required this.symbol, + required this.name, + required this.flag, + }); +} + +const _currencyOptions = [ + _CurrencyOption(code: 'USD', symbol: '\$', name: '美元', flag: '🇺🇸'), + _CurrencyOption(code: 'CNY', symbol: '¥', name: '人民币', flag: '🇨🇳'), + _CurrencyOption(code: 'EUR', symbol: '€', name: '欧元', flag: '🇪🇺'), + _CurrencyOption(code: 'GBP', symbol: '£', name: '英镑', flag: '🇬🇧'), + _CurrencyOption(code: 'JPY', symbol: '¥', name: '日元', flag: '🇯🇵'), + _CurrencyOption(code: 'HKD', symbol: 'HK\$', name: '港币', flag: '🇭🇰'), +];