import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:image_picker/image_picker.dart'; import '../../../core/theme/app_colors.dart'; import '../../../shared/widgets/custom_app_bar.dart'; import '../../../core/widgets/custom_text_field.dart'; import '../../../core/widgets/custom_button.dart'; import '../../../core/providers/app_state_provider.dart'; import '../../../shared/models/user_model.dart'; /// 个人信息编辑页面 class ProfileEditScreen extends ConsumerStatefulWidget { const ProfileEditScreen({super.key}); @override ConsumerState createState() => _ProfileEditScreenState(); } class _ProfileEditScreenState extends ConsumerState { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _emailController = TextEditingController(); final _phoneController = TextEditingController(); final _bioController = TextEditingController(); final _realNameController = TextEditingController(); final _locationController = TextEditingController(); final _occupationController = TextEditingController(); String? _selectedGender; DateTime? _selectedBirthday; String? _selectedEducation; String? _selectedEnglishLevel; String? _selectedTargetLevel; String? _selectedLearningGoal; List _interests = []; String? _avatarPath; bool _isLoading = false; final List _genderOptions = ['male', 'female', 'other']; final List _educationOptions = ['高中', '专科', '本科', '硕士', '博士']; final List _englishLevelOptions = ['beginner', 'elementary', 'intermediate', 'upperIntermediate', 'advanced']; final List _learningGoalOptions = ['dailyCommunication', 'businessEnglish', 'academicEnglish', 'examPreparation', 'travelEnglish']; final List _interestOptions = ['编程', '英语学习', '阅读', '音乐', '电影', '旅行', '运动', '摄影', '绘画', '游戏']; @override void initState() { super.initState(); _loadUserData(); } @override void dispose() { _usernameController.dispose(); _emailController.dispose(); _phoneController.dispose(); _bioController.dispose(); _realNameController.dispose(); _locationController.dispose(); _occupationController.dispose(); super.dispose(); } void _loadUserData() { final authProviderNotifier = ref.read(authProvider); final user = authProviderNotifier.user; if (user != null) { _usernameController.text = user.username ?? ''; _emailController.text = user.email ?? ''; _phoneController.text = user.phone ?? ''; _bioController.text = user.bio ?? ''; _selectedGender = user.gender; _selectedBirthday = user.birthday; _selectedEnglishLevel = user.learningLevel; _avatarPath = user.avatar; } } Future _pickImage() async { final ImagePicker picker = ImagePicker(); final XFile? image = await picker.pickImage( source: ImageSource.gallery, maxWidth: 512, maxHeight: 512, imageQuality: 80, ); if (image != null) { setState(() { _avatarPath = image.path; }); } } Future _selectBirthday() async { final DateTime? picked = await showDatePicker( context: context, initialDate: _selectedBirthday ?? DateTime(1990), firstDate: DateTime(1900), lastDate: DateTime.now(), builder: (context, child) { return Theme( data: Theme.of(context).copyWith( colorScheme: ColorScheme.light( primary: AppColors.primary, onPrimary: AppColors.onPrimary, surface: AppColors.surface, onSurface: AppColors.onSurface, ), ), child: child!, ); }, ); if (picked != null) { setState(() { _selectedBirthday = picked; }); } } void _showInterestsDialog() { showDialog( context: context, builder: (context) { List tempInterests = List.from(_interests); return StatefulBuilder( builder: (context, setDialogState) { return AlertDialog( title: const Text('选择兴趣爱好'), content: SizedBox( width: double.maxFinite, child: ListView.builder( shrinkWrap: true, itemCount: _interestOptions.length, itemBuilder: (context, index) { final interest = _interestOptions[index]; final isSelected = tempInterests.contains(interest); return CheckboxListTile( title: Text(interest), value: isSelected, onChanged: (bool? value) { setDialogState(() { if (value == true) { tempInterests.add(interest); } else { tempInterests.remove(interest); } }); }, activeColor: AppColors.primary, ); }, ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () { setState(() { _interests = tempInterests; }); Navigator.pop(context); }, child: const Text('确定'), ), ], ); }, ); }, ); } Future _saveProfile() async { if (!_formKey.currentState!.validate()) return; setState(() { _isLoading = true; }); try { final authProviderNotifier = ref.read(authProvider); final success = await authProviderNotifier.updateProfile( nickname: _usernameController.text.trim(), avatar: _avatarPath, phone: _phoneController.text.trim(), birthday: _selectedBirthday, gender: _selectedGender, bio: _bioController.text.trim(), learningLevel: _selectedEnglishLevel, targetLanguage: 'english', nativeLanguage: 'chinese', dailyGoal: 30, ); if (success) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('个人信息更新成功'), backgroundColor: Colors.green, ), ); Navigator.pop(context); } } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('更新失败,请重试'), backgroundColor: Colors.red, ), ); } } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('更新失败: $e'), backgroundColor: Colors.red, ), ); } } finally { if (mounted) { setState(() { _isLoading = false; }); } } } String _getGenderDisplayName(String gender) { switch (gender) { case 'male': return '男'; case 'female': return '女'; case 'other': return '其他'; default: return gender; } } String _getEnglishLevelDisplayName(String level) { switch (level) { case 'beginner': return '初学者'; case 'elementary': return '基础'; case 'intermediate': return '中级'; case 'upperIntermediate': return '中高级'; case 'advanced': return '高级'; default: return level; } } String _getLearningGoalDisplayName(String goal) { switch (goal) { case 'dailyCommunication': return '日常交流'; case 'businessEnglish': return '商务英语'; case 'academicEnglish': return '学术英语'; case 'examPreparation': return '考试准备'; case 'travelEnglish': return '旅游英语'; default: return goal; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.surface, appBar: CustomAppBar( title: '编辑个人信息', actions: [ TextButton( onPressed: _isLoading ? null : _saveProfile, child: Text( '保存', style: TextStyle( color: _isLoading ? AppColors.onSurfaceVariant : AppColors.primary, fontWeight: FontWeight.w600, ), ), ), ], ), body: Stack( children: [ Form( key: _formKey, child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 头像部分 Center( child: GestureDetector( onTap: _pickImage, child: Container( width: 100, height: 100, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: AppColors.primary, width: 2, ), ), child: CircleAvatar( radius: 48, backgroundColor: AppColors.surface, backgroundImage: _avatarPath != null ? (_avatarPath!.startsWith('http') ? NetworkImage(_avatarPath!) : FileImage(XFile(_avatarPath!).path as dynamic)) : null, child: _avatarPath == null ? Icon( Icons.camera_alt, size: 30, color: AppColors.primary, ) : null, ), ), ), ), const SizedBox(height: 8), Center( child: Text( '点击更换头像', style: TextStyle( fontSize: 12, color: AppColors.onSurfaceVariant, ), ), ), const SizedBox(height: 32), // 基本信息 _buildSectionTitle('基本信息'), const SizedBox(height: 16), CustomTextField( controller: _usernameController, labelText: '用户名', hintText: '请输入用户名', validator: (value) { if (value == null || value.trim().isEmpty) { return '请输入用户名'; } return null; }, ), const SizedBox(height: 16), CustomTextField( controller: _realNameController, labelText: '真实姓名', hintText: '请输入真实姓名', ), const SizedBox(height: 16), CustomTextField( controller: _emailController, labelText: '邮箱', hintText: '请输入邮箱地址', keyboardType: TextInputType.emailAddress, enabled: false, // 邮箱通常不允许修改 ), const SizedBox(height: 16), CustomTextField( controller: _phoneController, labelText: '手机号', hintText: '请输入手机号', keyboardType: TextInputType.phone, ), const SizedBox(height: 16), // 性别选择 _buildDropdownField( label: '性别', value: _selectedGender, items: _genderOptions, displayNameBuilder: _getGenderDisplayName, onChanged: (value) { setState(() { _selectedGender = value; }); }, ), const SizedBox(height: 16), // 生日选择 _buildDateField( label: '生日', value: _selectedBirthday, onTap: _selectBirthday, ), const SizedBox(height: 16), CustomTextField( controller: _locationController, labelText: '所在地', hintText: '请输入所在地', ), const SizedBox(height: 16), CustomTextField( controller: _occupationController, labelText: '职业', hintText: '请输入职业', ), const SizedBox(height: 16), // 教育背景 _buildDropdownField( label: '教育背景', value: _selectedEducation, items: _educationOptions, displayNameBuilder: (value) => value, onChanged: (value) { setState(() { _selectedEducation = value; }); }, ), const SizedBox(height: 32), // 学习信息 _buildSectionTitle('学习信息'), const SizedBox(height: 16), // 当前英语水平 _buildDropdownField( label: '当前英语水平', value: _selectedEnglishLevel, items: _englishLevelOptions, displayNameBuilder: _getEnglishLevelDisplayName, onChanged: (value) { setState(() { _selectedEnglishLevel = value; }); }, ), const SizedBox(height: 16), // 目标英语水平 _buildDropdownField( label: '目标英语水平', value: _selectedTargetLevel, items: _englishLevelOptions, displayNameBuilder: _getEnglishLevelDisplayName, onChanged: (value) { setState(() { _selectedTargetLevel = value; }); }, ), const SizedBox(height: 16), // 学习目标 _buildDropdownField( label: '学习目标', value: _selectedLearningGoal, items: _learningGoalOptions, displayNameBuilder: _getLearningGoalDisplayName, onChanged: (value) { setState(() { _selectedLearningGoal = value; }); }, ), const SizedBox(height: 16), // 兴趣爱好 _buildInterestsField(), const SizedBox(height: 32), // 个人简介 _buildSectionTitle('个人简介'), const SizedBox(height: 16), CustomTextField( controller: _bioController, labelText: '个人简介', hintText: '介绍一下自己吧...', maxLines: 4, ), const SizedBox(height: 32), // 保存按钮 CustomButton( text: '保存修改', onPressed: _saveProfile, isLoading: _isLoading, ), const SizedBox(height: 32), ], ), ), ), if (_isLoading) Container( color: Colors.black.withOpacity(0.3), child: const Center( child: CircularProgressIndicator(), ), ), ], ), ); } Widget _buildSectionTitle(String title) { return Text( title, style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: AppColors.onSurface, ), ); } Widget _buildDropdownField({ required String label, required String? value, required List items, required String Function(String) displayNameBuilder, required void Function(String?) onChanged, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.onSurface, ), ), const SizedBox(height: 8), Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 12), decoration: BoxDecoration( border: Border.all(color: AppColors.outline), borderRadius: BorderRadius.circular(8), ), child: DropdownButtonHideUnderline( child: DropdownButton( value: value, hint: Text('请选择$label'), isExpanded: true, items: items.map((item) { return DropdownMenuItem( value: item, child: Text(displayNameBuilder(item)), ); }).toList(), onChanged: onChanged, ), ), ), ], ); } Widget _buildDateField({ required String label, required DateTime? value, required VoidCallback onTap, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.onSurface, ), ), const SizedBox(height: 8), GestureDetector( onTap: onTap, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), decoration: BoxDecoration( border: Border.all(color: AppColors.outline), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( value != null ? '${value.year}-${value.month.toString().padLeft(2, '0')}-${value.day.toString().padLeft(2, '0')}' : '请选择$label', style: TextStyle( fontSize: 16, color: value != null ? AppColors.onSurface : AppColors.onSurfaceVariant, ), ), Icon( Icons.calendar_today, color: AppColors.onSurfaceVariant, size: 20, ), ], ), ), ), ], ); } Widget _buildInterestsField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '兴趣爱好', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: AppColors.onSurface, ), ), const SizedBox(height: 8), GestureDetector( onTap: _showInterestsDialog, child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16), decoration: BoxDecoration( border: Border.all(color: AppColors.outline), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: _interests.isEmpty ? Text( '请选择兴趣爱好', style: TextStyle( fontSize: 16, color: AppColors.onSurfaceVariant, ), ) : Wrap( spacing: 8, runSpacing: 4, children: _interests.map((interest) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppColors.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Text( interest, style: TextStyle( fontSize: 12, color: AppColors.primary, ), ), ); }).toList(), ), ), Icon( Icons.arrow_forward_ios, color: AppColors.onSurfaceVariant, size: 16, ), ], ), ), ), ], ); } }