import 'package:flutter/material.dart'; import '../../../../app/theme/app_colors.dart'; import '../../../../app/theme/app_typography.dart'; import '../../../../app/theme/app_spacing.dart'; import '../../../../app/i18n/app_localizations.dart'; import '../../../../app/i18n/locale_manager.dart'; /// 设置页面 /// /// 账号安全、通知、支付管理、语言、货币、关于 /// 货币选择影响交易页面中的计价货币符号 class SettingsPage extends StatefulWidget { const SettingsPage({super.key}); @override State createState() => _SettingsPageState(); } class _SettingsPageState extends State { _CurrencyOption _selectedCurrency = _currencyOptions[0]; bool _notifyTrade = true; bool _notifyExpiry = true; bool _notifyMarket = false; bool _notifyMarketing = false; String get _currentLanguageDisplay { final locale = LocaleManager.userLocale.value ?? Localizations.localeOf(context); return LocaleManager.localeDisplayName(locale); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(context.t('settings.title'))), body: ListView( children: [ _buildSection(context.t('settings.accountSecurity'), [ _buildTile(context.t('settings.phone'), subtitle: '138****8888', icon: Icons.phone_rounded), _buildTile(context.t('settings.email'), subtitle: 'u***@email.com', icon: Icons.email_rounded), _buildTile(context.t('settings.changePassword'), icon: Icons.lock_rounded), _buildTile(context.t('settings.identity'), subtitle: 'L1', icon: Icons.verified_user_rounded, onTap: () { Navigator.pushNamed(context, '/kyc'); }), ]), _buildSection(context.t('settings.paymentManage'), [ _buildTile(context.t('settings.paymentMethod'), subtitle: 'Visa •••• 4242', icon: Icons.credit_card_rounded), _buildTile(context.t('settings.bankAccount'), subtitle: 'BoA •••• 6789', icon: Icons.account_balance_rounded), _buildTile(context.t('settings.paymentPassword'), icon: Icons.password_rounded), ]), _buildSection(context.t('settings.notifications'), [ _buildSwitchTile(context.t('settings.tradeNotify'), _notifyTrade, (v) => setState(() => _notifyTrade = v)), _buildSwitchTile(context.t('settings.expiryRemind'), _notifyExpiry, (v) => setState(() => _notifyExpiry = v)), _buildSwitchTile(context.t('settings.marketChange'), _notifyMarket, (v) => setState(() => _notifyMarket = v)), _buildSwitchTile( context.t('settings.marketingPush'), _notifyMarketing, (v) => setState(() => _notifyMarketing = v)), ]), _buildSection(context.t('settings.general'), [ _buildTile(context.t('settings.language'), subtitle: _currentLanguageDisplay, icon: Icons.language_rounded, onTap: () => _showLanguagePicker(context)), _buildTile(context.t('settings.currency'), subtitle: '${_selectedCurrency.code} (${_selectedCurrency.symbol})', icon: Icons.attach_money_rounded, onTap: () => _showCurrencyPicker(context)), _buildTile(context.t('settings.clearCache'), icon: Icons.cleaning_services_rounded), ]), _buildSection(context.t('settings.about'), [ _buildTile(context.t('settings.version'), subtitle: 'v1.0.0', icon: Icons.info_outline_rounded), _buildTile(context.t('settings.userAgreement'), icon: Icons.description_rounded), _buildTile(context.t('settings.privacyPolicy'), icon: Icons.privacy_tip_rounded), _buildTile(context.t('settings.helpCenter'), icon: Icons.help_outline_rounded), ]), Padding( padding: const EdgeInsets.all(20), child: OutlinedButton( onPressed: () { Navigator.of(context) .pushNamedAndRemoveUntil('/', (_) => false); }, style: OutlinedButton.styleFrom( foregroundColor: AppColors.error, side: const BorderSide(color: AppColors.error), minimumSize: const Size(double.infinity, 48), ), child: Text(context.t('settings.logout')), ), ), ], ), ); } 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: [ 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(context.t('settings.selectCurrency'), style: AppTypography.h3), ), const Divider(height: 1), ..._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( '${context.t('settings.currencySymbol')}: ${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); }, ); }), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 24), child: Text( context.t('settings.currencyNote'), style: AppTypography.caption.copyWith( color: AppColors.textTertiary, ), textAlign: TextAlign.center, ), ), ], ), ), ); } void _showLanguagePicker(BuildContext context) { final languages = [ ('简体中文', const Locale('zh', 'CN'), '🇨🇳'), ('繁體中文', const Locale('zh', 'TW'), '🇹🇼'), ('English', const Locale('en'), '🇺🇸'), ('日本語', const Locale('ja'), '🇯🇵'), ]; final currentLocale = LocaleManager.userLocale.value ?? Localizations.localeOf(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: [ 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(context.t('settings.selectLanguage'), style: AppTypography.h3), ), const Divider(height: 1), ...languages.map((lang) { final (name, locale, flag) = lang; final isSelected = currentLocale.languageCode == locale.languageCode && (locale.countryCode == null || currentLocale.countryCode == locale.countryCode); 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: () { LocaleManager.userLocale.value = locale; setState(() {}); Navigator.pop(context); }, ); }), const SizedBox(height: 24), ], ), ), ); } Widget _buildSection(String title, List children) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 8), child: Text(title, style: AppTypography.labelSmall), ), Container( color: AppColors.surface, child: Column(children: children), ), ], ); } Widget _buildTile(String title, {String? subtitle, IconData? icon, VoidCallback? onTap}) { return ListTile( 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), onTap: onTap ?? () {}, ); } Widget _buildSwitchTile( String title, bool value, ValueChanged onChanged) { return SwitchListTile( title: Text(title, style: AppTypography.bodyMedium), value: value, onChanged: onChanged, activeColor: AppColors.primary, ); } } 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: 'USD', flag: '🇺🇸'), _CurrencyOption(code: 'CNY', symbol: '¥', name: 'CNY', flag: '🇨🇳'), _CurrencyOption(code: 'EUR', symbol: '€', name: 'EUR', flag: '🇪🇺'), _CurrencyOption(code: 'GBP', symbol: '£', name: 'GBP', flag: '🇬🇧'), _CurrencyOption(code: 'JPY', symbol: '¥', name: 'JPY', flag: '🇯🇵'), _CurrencyOption(code: 'HKD', symbol: 'HK\$', name: 'HKD', flag: '🇭🇰'), ];