329 lines
11 KiB
Dart
329 lines
11 KiB
Dart
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 StatefulWidget {
|
|
const SettingsPage({super.key});
|
|
|
|
@override
|
|
State<SettingsPage> createState() => _SettingsPageState();
|
|
}
|
|
|
|
class _SettingsPageState extends State<SettingsPage> {
|
|
// 当前选中的货币 (实际应用中从持久化/状态管理读取)
|
|
_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(
|
|
appBar: AppBar(title: const Text('设置')),
|
|
body: ListView(
|
|
children: [
|
|
// Account & Security
|
|
_buildSection('账号与安全', [
|
|
_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: () {
|
|
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('支付密码', icon: Icons.password_rounded),
|
|
]),
|
|
|
|
// Notifications
|
|
_buildSection('通知设置', [
|
|
_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: _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('用户协议', icon: Icons.description_rounded),
|
|
_buildTile('隐私政策', icon: Icons.privacy_tip_rounded),
|
|
_buildTile('帮助中心', icon: Icons.help_outline_rounded),
|
|
]),
|
|
|
|
// Logout
|
|
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: const Text('退出登录'),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// 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<Widget> 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<bool> onChanged) {
|
|
return SwitchListTile(
|
|
title: Text(title, style: AppTypography.bodyMedium),
|
|
value: value,
|
|
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: '🇭🇰'),
|
|
];
|