这是CaiYouHui前端,一个关于flutter的安卓app,前端使用flutter实现

profile_detail_screen.dart 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import 'package:flutter/material.dart';
  2. import 'package:provider/provider.dart';
  3. import '../../../data/models/user.dart';
  4. import '../../providers/user_provider.dart';
  5. import '../../widgets/common/app_button.dart';
  6. import '../../widgets/common/app_text_field.dart';
  7. class ProfileDetailScreen extends StatefulWidget {
  8. const ProfileDetailScreen({super.key});
  9. @override
  10. State<ProfileDetailScreen> createState() => _ProfileDetailScreenState();
  11. }
  12. class _ProfileDetailScreenState extends State<ProfileDetailScreen> {
  13. late User _currentUser;
  14. late TextEditingController _nameController;
  15. late TextEditingController _emailController;
  16. late TextEditingController _phoneController;
  17. final _formKey = GlobalKey<FormState>();
  18. @override
  19. void initState() {
  20. super.initState();
  21. final userProvider = Provider.of<UserProvider>(context, listen: false);
  22. _currentUser = userProvider.user ?? User(id: '', email: '', name: '');
  23. _nameController = TextEditingController(text: _currentUser.name);
  24. _emailController = TextEditingController(text: _currentUser.email);
  25. _phoneController = TextEditingController(text: _currentUser.phone ?? '');
  26. }
  27. @override
  28. void dispose() {
  29. _nameController.dispose();
  30. _emailController.dispose();
  31. _phoneController.dispose();
  32. super.dispose();
  33. }
  34. @override
  35. Widget build(BuildContext context) {
  36. final userProvider = Provider.of<UserProvider>(context);
  37. return Scaffold(
  38. appBar: AppBar(
  39. title: const Text('个人信息'),
  40. actions: [
  41. if (userProvider.isLoading)
  42. const Padding(
  43. padding: EdgeInsets.only(right: 16),
  44. child: Center(
  45. child: SizedBox(
  46. width: 24,
  47. height: 24,
  48. child: CircularProgressIndicator(strokeWidth: 2),
  49. ),
  50. ),
  51. ),
  52. ],
  53. ),
  54. body: SingleChildScrollView(
  55. padding: const EdgeInsets.all(20),
  56. child: Form(
  57. key: _formKey,
  58. child: Column(
  59. children: [
  60. // 头像编辑
  61. GestureDetector(
  62. onTap: () {
  63. // 选择头像
  64. },
  65. child: Stack(
  66. alignment: Alignment.center,
  67. children: [
  68. CircleAvatar(
  69. radius: 60,
  70. backgroundColor: Colors.blue[100],
  71. backgroundImage: _currentUser.avatarUrl != null
  72. ? NetworkImage(_currentUser.avatarUrl!)
  73. : null,
  74. child: _currentUser.avatarUrl == null
  75. ? const Icon(
  76. Icons.person,
  77. size: 80,
  78. color: Colors.blue,
  79. )
  80. : null,
  81. ),
  82. Positioned(
  83. bottom: 0,
  84. right: 0,
  85. child: Container(
  86. padding: const EdgeInsets.all(8),
  87. decoration: BoxDecoration(
  88. color: Colors.blue,
  89. borderRadius: BorderRadius.circular(20),
  90. border: Border.all(
  91. color: Colors.white,
  92. width: 2,
  93. ),
  94. ),
  95. child: const Icon(
  96. Icons.camera_alt,
  97. size: 20,
  98. color: Colors.white,
  99. ),
  100. ),
  101. ),
  102. ],
  103. ),
  104. ),
  105. const SizedBox(height: 20),
  106. TextButton(
  107. onPressed: () {},
  108. child: const Text(
  109. '更换头像',
  110. style: TextStyle(color: Colors.blue),
  111. ),
  112. ),
  113. const SizedBox(height: 40),
  114. // 表单字段
  115. AppTextField(
  116. controller: _nameController,
  117. labelText: '姓名',
  118. hintText: '请输入您的姓名',
  119. validator: (value) {
  120. if (value == null || value.isEmpty) {
  121. return '请输入姓名';
  122. }
  123. return null;
  124. },
  125. ),
  126. const SizedBox(height: 20),
  127. AppTextField(
  128. controller: _emailController,
  129. labelText: '邮箱地址',
  130. hintText: '请输入邮箱',
  131. keyboardType: TextInputType.emailAddress,
  132. enabled: false, // 邮箱通常不可修改
  133. validator: (value) {
  134. if (value == null || value.isEmpty) {
  135. return '请输入邮箱地址';
  136. }
  137. if (!value.contains('@')) {
  138. return '请输入有效的邮箱地址';
  139. }
  140. return null;
  141. },
  142. ),
  143. const SizedBox(height: 20),
  144. AppTextField(
  145. controller: _phoneController,
  146. labelText: '手机号码',
  147. hintText: '请输入手机号码',
  148. keyboardType: TextInputType.phone,
  149. ),
  150. const SizedBox(height: 40),
  151. // 错误提示
  152. if (userProvider.error != null)
  153. Padding(
  154. padding: const EdgeInsets.only(bottom: 16),
  155. child: Text(
  156. userProvider.error!,
  157. style: const TextStyle(color: Colors.red),
  158. ),
  159. ),
  160. // 保存按钮
  161. AppButton(
  162. text: '保存修改',
  163. isLoading: userProvider.isLoading, // 传入加载状态
  164. enabled: !userProvider.isLoading, // 加载时禁用按钮
  165. onPressed: () async {
  166. if (_formKey.currentState!.validate()) {
  167. final updatedUser = _currentUser.copyWith(
  168. name: _nameController.text.trim(),
  169. phone: _phoneController.text.trim().isNotEmpty
  170. ? _phoneController.text.trim()
  171. : null,
  172. );
  173. await userProvider.updateUserProfile(updatedUser);
  174. if (userProvider.error == null) {
  175. ScaffoldMessenger.of(context).showSnackBar(
  176. const SnackBar(
  177. content: Text('个人信息已更新'),
  178. duration: Duration(seconds: 2),
  179. ),
  180. );
  181. Navigator.of(context).pop();
  182. }
  183. }
  184. },
  185. ),
  186. const SizedBox(height: 20),
  187. ],
  188. ),
  189. ),
  190. ),
  191. );
  192. }
  193. }