import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:image_picker/image_picker.dart'; import 'dart:io'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_text_styles.dart'; import '../../../core/theme/app_dimensions.dart'; import '../../../core/widgets/custom_button.dart'; import '../../../core/widgets/custom_text_field.dart'; import '../../../core/models/user_model.dart'; import '../../auth/providers/auth_provider.dart'; import '../widgets/profile_avatar.dart'; import '../widgets/profile_info_card.dart'; import '../widgets/learning_preferences_card.dart'; /// 个人资料详情屏幕 class ProfileDetailScreen extends StatefulWidget { const ProfileDetailScreen({super.key}); @override State createState() => _ProfileDetailScreenState(); } class _ProfileDetailScreenState extends State with TickerProviderStateMixin { late TabController _tabController; final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _emailController = TextEditingController(); final _phoneController = TextEditingController(); final _bioController = TextEditingController(); bool _isEditing = false; bool _isLoading = false; File? _selectedImage; // 学习偏好设置 int _dailyWordGoal = 20; int _dailyStudyMinutes = 30; EnglishLevel _englishLevel = EnglishLevel.intermediate; bool _notificationsEnabled = true; bool _soundEnabled = true; bool _vibrationEnabled = true; @override void initState() { super.initState(); _tabController = TabController(length: 3, vsync: this); _loadUserData(); } @override void dispose() { _tabController.dispose(); _usernameController.dispose(); _emailController.dispose(); _phoneController.dispose(); _bioController.dispose(); super.dispose(); } /// 加载用户数据 void _loadUserData() { final authProvider = Provider.of(context, listen: false); final user = authProvider.state.user; if (user != null) { _usernameController.text = user.username; _emailController.text = user.email; _phoneController.text = user.profile?.phone ?? ''; _bioController.text = user.profile?.bio ?? ''; if (user.profile?.settings != null) { _dailyWordGoal = user.profile!.settings!.dailyWordGoal; _dailyStudyMinutes = user.profile!.settings!.dailyStudyMinutes; _notificationsEnabled = user.profile!.settings!.notificationsEnabled; _soundEnabled = user.profile!.settings!.soundEnabled; _vibrationEnabled = user.profile!.settings!.vibrationEnabled; } if (user.profile?.englishLevel != null) { _englishLevel = user.profile!.englishLevel!; } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.background, appBar: _buildAppBar(), body: Column( children: [ // Tab栏 Container( color: AppColors.surface, child: TabBar( controller: _tabController, labelColor: AppColors.primary, unselectedLabelColor: AppColors.onSurfaceVariant, indicatorColor: AppColors.primary, indicatorWeight: 3, labelStyle: AppTextStyles.titleSmall.copyWith( fontWeight: FontWeight.w600, ), unselectedLabelStyle: AppTextStyles.titleSmall, tabs: const [ Tab(text: '基本信息'), Tab(text: '学习偏好'), Tab(text: '账户设置'), ], ), ), // Tab内容 Expanded( child: TabBarView( controller: _tabController, children: [ _buildBasicInfoTab(), _buildLearningPreferencesTab(), _buildAccountSettingsTab(), ], ), ), ], ), ); } /// 构建应用栏 PreferredSizeWidget _buildAppBar() { return AppBar( backgroundColor: AppColors.primary, foregroundColor: AppColors.onPrimary, title: Text( '个人资料', style: AppTextStyles.titleLarge.copyWith( color: AppColors.onPrimary, fontWeight: FontWeight.w600, ), ), actions: [ if (_isEditing) TextButton( onPressed: _isLoading ? null : _saveProfile, child: _isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(AppColors.onPrimary), ), ) : Text( '保存', style: AppTextStyles.titleSmall.copyWith( color: AppColors.onPrimary, fontWeight: FontWeight.w600, ), ), ) else IconButton( onPressed: () => setState(() => _isEditing = true), icon: Icon( Icons.edit, color: AppColors.onPrimary, ), ), const SizedBox(width: AppDimensions.spacingSm), ], ); } /// 构建基本信息标签页 Widget _buildBasicInfoTab() { return SingleChildScrollView( padding: const EdgeInsets.all(AppDimensions.spacingMd), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 头像部分 _buildAvatarSection(), const SizedBox(height: AppDimensions.spacingLg), // 基本信息表单 ProfileInfoCard( title: '基本信息', child: Column( children: [ CustomTextField( controller: _usernameController, labelText: '用户名', enabled: _isEditing, validator: (value) { if (value == null || value.isEmpty) { return '请输入用户名'; } if (value.length < 2) { return '用户名至少2个字符'; } return null; }, ), const SizedBox(height: AppDimensions.spacingMd), CustomTextField( controller: _emailController, labelText: '邮箱', enabled: false, // 邮箱不允许修改 keyboardType: TextInputType.emailAddress, ), const SizedBox(height: AppDimensions.spacingMd), CustomTextField( controller: _phoneController, labelText: '手机号', enabled: _isEditing, keyboardType: TextInputType.phone, validator: (value) { if (value != null && value.isNotEmpty) { if (!RegExp(r'^1[3-9]\d{9}$').hasMatch(value)) { return '请输入正确的手机号'; } } return null; }, ), const SizedBox(height: AppDimensions.spacingMd), CustomTextField( controller: _bioController, labelText: '个人简介', enabled: _isEditing, maxLines: 3, maxLength: 200, validator: (value) { if (value != null && value.length > 200) { return '个人简介不能超过200个字符'; } return null; }, ), ], ), ), ], ), ), ); } /// 构建学习偏好标签页 Widget _buildLearningPreferencesTab() { return SingleChildScrollView( padding: const EdgeInsets.all(AppDimensions.spacingMd), child: Column( children: [ LearningPreferencesCard( title: '学习目标', child: Column( children: [ _buildSliderSetting( title: '每日单词目标', value: _dailyWordGoal.toDouble(), min: 5, max: 100, divisions: 19, unit: '个', onChanged: _isEditing ? (value) => setState(() => _dailyWordGoal = value.round()) : null, ), const SizedBox(height: AppDimensions.spacingMd), _buildSliderSetting( title: '每日学习时长', value: _dailyStudyMinutes.toDouble(), min: 10, max: 120, divisions: 22, unit: '分钟', onChanged: _isEditing ? (value) => setState(() => _dailyStudyMinutes = value.round()) : null, ), ], ), ), const SizedBox(height: AppDimensions.spacingMd), LearningPreferencesCard( title: '英语水平', child: _buildEnglishLevelSelector(), ), const SizedBox(height: AppDimensions.spacingMd), LearningPreferencesCard( title: '通知设置', child: Column( children: [ _buildSwitchSetting( title: '学习提醒', subtitle: '每日学习时间提醒', value: _notificationsEnabled, onChanged: _isEditing ? (value) => setState(() => _notificationsEnabled = value) : null, ), _buildSwitchSetting( title: '音效', subtitle: '操作反馈音效', value: _soundEnabled, onChanged: _isEditing ? (value) => setState(() => _soundEnabled = value) : null, ), _buildSwitchSetting( title: '震动反馈', subtitle: '操作震动反馈', value: _vibrationEnabled, onChanged: _isEditing ? (value) => setState(() => _vibrationEnabled = value) : null, ), ], ), ), ], ), ); } /// 构建账户设置标签页 Widget _buildAccountSettingsTab() { return SingleChildScrollView( padding: const EdgeInsets.all(AppDimensions.spacingMd), child: Column( children: [ ProfileInfoCard( title: '安全设置', child: Column( children: [ _buildSettingItem( icon: Icons.lock_outline, title: '修改密码', subtitle: '定期修改密码保护账户安全', onTap: () => Navigator.pushNamed(context, '/change-password'), ), const Divider(), _buildSettingItem( icon: Icons.security, title: '两步验证', subtitle: '增强账户安全性', onTap: () => _showComingSoon('两步验证'), ), ], ), ), const SizedBox(height: AppDimensions.spacingMd), ProfileInfoCard( title: '数据管理', child: Column( children: [ _buildSettingItem( icon: Icons.download, title: '导出数据', subtitle: '导出学习记录和个人数据', onTap: () => _showComingSoon('数据导出'), ), const Divider(), _buildSettingItem( icon: Icons.delete_outline, title: '清除缓存', subtitle: '清除应用缓存数据', onTap: _clearCache, ), ], ), ), const SizedBox(height: AppDimensions.spacingMd), ProfileInfoCard( title: '账户操作', child: Column( children: [ _buildSettingItem( icon: Icons.logout, title: '退出登录', subtitle: '退出当前账户', onTap: _logout, textColor: AppColors.warning, ), const Divider(), _buildSettingItem( icon: Icons.delete_forever, title: '注销账户', subtitle: '永久删除账户和所有数据', onTap: () => _showDeleteAccountDialog(), textColor: AppColors.error, ), ], ), ), ], ), ); } /// 构建头像部分 Widget _buildAvatarSection() { return Consumer(builder: (context, authProvider, child) { final user = authProvider.state.user; return Center( child: Column( children: [ ProfileAvatar( imageUrl: user?.profile?.avatar, selectedImage: _selectedImage, size: 100, isEditing: _isEditing, onImageSelected: _selectImage, ), const SizedBox(height: AppDimensions.spacingMd), Text( user?.username ?? '用户', style: AppTextStyles.headlineSmall.copyWith( color: AppColors.onSurface, fontWeight: FontWeight.w600, ), ), const SizedBox(height: AppDimensions.spacingXs), Text( user?.email ?? '', style: AppTextStyles.bodyMedium.copyWith( color: AppColors.onSurfaceVariant, ), ), ], ), ); }); } /// 构建滑块设置 Widget _buildSliderSetting({ required String title, required double value, required double min, required double max, required int divisions, required String unit, ValueChanged? onChanged, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: AppTextStyles.titleSmall.copyWith( color: AppColors.onSurface, fontWeight: FontWeight.w500, ), ), Text( '${value.round()} $unit', style: AppTextStyles.titleSmall.copyWith( color: AppColors.primary, fontWeight: FontWeight.w600, ), ), ], ), const SizedBox(height: AppDimensions.spacingSm), Slider( value: value, min: min, max: max, divisions: divisions, activeColor: AppColors.primary, inactiveColor: AppColors.primary.withOpacity(0.3), onChanged: onChanged, ), ], ); } /// 构建开关设置 Widget _buildSwitchSetting({ required String title, required String subtitle, required bool value, ValueChanged? onChanged, }) { return ListTile( contentPadding: EdgeInsets.zero, title: Text( title, style: AppTextStyles.titleSmall.copyWith( color: AppColors.onSurface, fontWeight: FontWeight.w500, ), ), subtitle: Text( subtitle, style: AppTextStyles.bodySmall.copyWith( color: AppColors.onSurfaceVariant, ), ), trailing: Switch( value: value, onChanged: onChanged, activeColor: AppColors.primary, ), ); } /// 构建英语水平选择器 Widget _buildEnglishLevelSelector() { return Column( children: EnglishLevel.values.map((level) { return RadioListTile( contentPadding: EdgeInsets.zero, title: Text( _getEnglishLevelText(level), style: AppTextStyles.titleSmall.copyWith( color: AppColors.onSurface, fontWeight: FontWeight.w500, ), ), subtitle: Text( _getEnglishLevelDescription(level), style: AppTextStyles.bodySmall.copyWith( color: AppColors.onSurfaceVariant, ), ), value: level, groupValue: _englishLevel, onChanged: _isEditing ? (value) => setState(() => _englishLevel = value!) : null, activeColor: AppColors.primary, ); }).toList(), ); } /// 构建设置项 Widget _buildSettingItem({ required IconData icon, required String title, required String subtitle, required VoidCallback onTap, Color? textColor, }) { return ListTile( contentPadding: EdgeInsets.zero, leading: Icon( icon, color: textColor ?? AppColors.onSurface, ), title: Text( title, style: AppTextStyles.titleSmall.copyWith( color: textColor ?? AppColors.onSurface, fontWeight: FontWeight.w500, ), ), subtitle: Text( subtitle, style: AppTextStyles.bodySmall.copyWith( color: AppColors.onSurfaceVariant, ), ), trailing: Icon( Icons.chevron_right, color: AppColors.onSurfaceVariant, ), onTap: onTap, ); } /// 选择图片 Future _selectImage() async { final picker = ImagePicker(); final pickedFile = await picker.pickImage( source: ImageSource.gallery, maxWidth: 512, maxHeight: 512, imageQuality: 80, ); if (pickedFile != null) { setState(() { _selectedImage = File(pickedFile.path); }); } } /// 保存个人资料 Future _saveProfile() async { if (!_formKey.currentState!.validate()) { return; } setState(() => _isLoading = true); try { final authProvider = Provider.of(context, listen: false); // TODO: 如果有选择新头像,先上传头像 String? avatarUrl; if (_selectedImage != null) { // avatarUrl = await _uploadAvatar(_selectedImage!); } await authProvider.updateProfile( username: _usernameController.text, phone: _phoneController.text, avatar: avatarUrl, ); setState(() { _isEditing = false; _selectedImage = null; }); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('个人资料更新成功'), backgroundColor: AppColors.success, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), ); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('更新失败: $e'), backgroundColor: AppColors.error, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), ); } } finally { if (mounted) { setState(() => _isLoading = false); } } } /// 清除缓存 Future _clearCache() async { // TODO: 实现清除缓存功能 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('缓存已清除'), backgroundColor: AppColors.success, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), ); } /// 退出登录 Future _logout() async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('确认退出'), content: const Text('确定要退出登录吗?'), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: Text( '退出', style: TextStyle(color: AppColors.warning), ), ), ], ), ); if (confirmed == true) { final authProvider = Provider.of(context, listen: false); await authProvider.logout(); if (mounted) { Navigator.pushNamedAndRemoveUntil( context, '/login', (route) => false, ); } } } /// 显示注销账户对话框 Future _showDeleteAccountDialog() async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: Text( '注销账户', style: TextStyle(color: AppColors.error), ), content: const Text( '注销账户将永久删除您的所有数据,包括学习记录、个人信息等。此操作不可恢复,请谨慎操作。', ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: Text( '确认注销', style: TextStyle(color: AppColors.error), ), ), ], ), ); if (confirmed == true) { // TODO: 实现注销账户功能 _showComingSoon('账户注销'); } } /// 显示即将上线提示 void _showComingSoon(String feature) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('$feature功能即将上线'), backgroundColor: AppColors.info, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.0), ), ), ); } /// 获取英语水平文本 String _getEnglishLevelText(EnglishLevel level) { switch (level) { case EnglishLevel.beginner: return '初级 (Beginner)'; case EnglishLevel.elementary: return '基础 (Elementary)'; case EnglishLevel.intermediate: return '中级 (Intermediate)'; case EnglishLevel.upperIntermediate: return '中高级 (Upper Intermediate)'; case EnglishLevel.advanced: return '高级 (Advanced)'; case EnglishLevel.proficient: return '精通 (Proficient)'; case EnglishLevel.expert: return '专家 (Expert)'; } } /// 获取英语水平描述 String _getEnglishLevelDescription(EnglishLevel level) { switch (level) { case EnglishLevel.beginner: return '基础词汇和语法,适合英语入门学习者'; case EnglishLevel.elementary: return '掌握基本词汇,能进行简单交流'; case EnglishLevel.intermediate: return '中等词汇量,能进行日常对话和阅读'; case EnglishLevel.upperIntermediate: return '较好的词汇量,能处理复杂话题'; case EnglishLevel.advanced: return '丰富词汇量,能流利交流和理解复杂内容'; case EnglishLevel.proficient: return '熟练掌握英语,能应对各种语言场景'; case EnglishLevel.expert: return '接近母语水平,能处理专业和学术内容'; } } }