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

register_screen.dart 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import 'package:flutter/material.dart';
  2. import 'package:provider/provider.dart';
  3. import '../../providers/auth_provider.dart';
  4. import '../../../core/constants/route_constants.dart';
  5. import '../../widgets/common/app_button.dart';
  6. import '../../widgets/common/app_text_field.dart';
  7. import '../../widgets/common/loading_indicator.dart';
  8. class RegisterScreen extends StatefulWidget {
  9. const RegisterScreen({super.key});
  10. @override
  11. State<RegisterScreen> createState() => _RegisterScreenState();
  12. }
  13. class _RegisterScreenState extends State<RegisterScreen> {
  14. final _formKey = GlobalKey<FormState>();
  15. final _nameController = TextEditingController();
  16. final _emailController = TextEditingController();
  17. final _phoneController = TextEditingController();
  18. final _passwordController = TextEditingController();
  19. final _confirmPasswordController = TextEditingController();
  20. @override
  21. void dispose() {
  22. _nameController.dispose();
  23. _emailController.dispose();
  24. _phoneController.dispose();
  25. _passwordController.dispose();
  26. _confirmPasswordController.dispose();
  27. super.dispose();
  28. }
  29. @override
  30. Widget build(BuildContext context) {
  31. final authProvider = Provider.of<AuthProvider>(context);
  32. return Scaffold(
  33. appBar: AppBar(
  34. title: const Text('注册'),
  35. ),
  36. body: SingleChildScrollView(
  37. child: Padding(
  38. padding: const EdgeInsets.all(24.0),
  39. child: Form(
  40. key: _formKey,
  41. child: Column(
  42. crossAxisAlignment: CrossAxisAlignment.start,
  43. children: [
  44. const SizedBox(height: 20),
  45. const Text(
  46. '创建账号',
  47. style: TextStyle(
  48. fontSize: 24,
  49. fontWeight: FontWeight.bold,
  50. ),
  51. ),
  52. const SizedBox(height: 8),
  53. const Text(
  54. '请填写以下信息完成注册',
  55. style: TextStyle(
  56. fontSize: 14,
  57. color: Colors.grey,
  58. ),
  59. ),
  60. const SizedBox(height: 30),
  61. AppTextField(
  62. controller: _nameController,
  63. labelText: '姓名',
  64. hintText: '请输入您的姓名',
  65. prefixIcon: const Icon(Icons.person_outline),
  66. validator: (value) {
  67. if (value == null || value.isEmpty) {
  68. return '请输入姓名';
  69. }
  70. return null;
  71. },
  72. ),
  73. const SizedBox(height: 20),
  74. AppTextField(
  75. controller: _emailController,
  76. labelText: '邮箱地址',
  77. hintText: '请输入邮箱',
  78. keyboardType: TextInputType.emailAddress,
  79. prefixIcon: const Icon(Icons.email_outlined),
  80. validator: (value) {
  81. if (value == null || value.isEmpty) {
  82. return '请输入邮箱地址';
  83. }
  84. if (!value.contains('@')) {
  85. return '请输入有效的邮箱地址';
  86. }
  87. return null;
  88. },
  89. ),
  90. const SizedBox(height: 20),
  91. AppTextField(
  92. controller: _phoneController,
  93. labelText: '手机号码(可选)',
  94. hintText: '请输入手机号码',
  95. keyboardType: TextInputType.phone,
  96. prefixIcon: const Icon(Icons.phone_outlined),
  97. ),
  98. const SizedBox(height: 20),
  99. AppTextField(
  100. controller: _passwordController,
  101. labelText: '密码',
  102. hintText: '请输入密码',
  103. obscureText: true,
  104. prefixIcon: const Icon(Icons.lock_outline),
  105. validator: (value) {
  106. if (value == null || value.isEmpty) {
  107. return '请输入密码';
  108. }
  109. if (value.length < 6) {
  110. return '密码至少需要6位字符';
  111. }
  112. return null;
  113. },
  114. ),
  115. const SizedBox(height: 20),
  116. AppTextField(
  117. controller: _confirmPasswordController,
  118. labelText: '确认密码',
  119. hintText: '请再次输入密码',
  120. obscureText: true,
  121. prefixIcon: const Icon(Icons.lock_outline),
  122. validator: (value) {
  123. if (value == null || value.isEmpty) {
  124. return '请确认密码';
  125. }
  126. if (value != _passwordController.text) {
  127. return '两次输入的密码不一致';
  128. }
  129. return null;
  130. },
  131. ),
  132. const SizedBox(height: 30),
  133. if (authProvider.error != null)
  134. Padding(
  135. padding: const EdgeInsets.only(bottom: 16),
  136. child: Text(
  137. authProvider.error!,
  138. style: const TextStyle(
  139. color: Colors.red,
  140. fontSize: 14,
  141. ),
  142. ),
  143. ),
  144. if (authProvider.isLoading)
  145. const LoadingIndicator()
  146. else
  147. AppButton(
  148. text: '注册',
  149. onPressed: () async {
  150. if (_formKey.currentState!.validate()) {
  151. await authProvider.register(
  152. _nameController.text,
  153. _emailController.text.trim(),
  154. _passwordController.text,
  155. _passwordController.text,
  156. _phoneController.text.isNotEmpty
  157. ? _phoneController.text
  158. : null,
  159. );
  160. if (authProvider.isAuthenticated) {
  161. Navigator.of(context).pushReplacementNamed(
  162. RouteConstants.home,
  163. );
  164. }
  165. }
  166. },
  167. ),
  168. const SizedBox(height: 20),
  169. Center(
  170. child: TextButton(
  171. onPressed: () {
  172. Navigator.of(context).pop();
  173. },
  174. child: const Text(
  175. '已有账号?立即登录',
  176. style: TextStyle(
  177. fontSize: 14,
  178. color: Colors.blue,
  179. ),
  180. ),
  181. ),
  182. ),
  183. const SizedBox(height: 40),
  184. Padding(
  185. padding: const EdgeInsets.symmetric(horizontal: 16),
  186. child: RichText(
  187. textAlign: TextAlign.center,
  188. text: const TextSpan(
  189. style: TextStyle(
  190. fontSize: 12,
  191. color: Colors.grey,
  192. ),
  193. children: [
  194. TextSpan(text: '注册即表示您同意我们的'),
  195. TextSpan(
  196. text: '服务条款',
  197. style: TextStyle(color: Colors.blue),
  198. ),
  199. TextSpan(text: '和'),
  200. TextSpan(
  201. text: '隐私政策',
  202. style: TextStyle(color: Colors.blue),
  203. ),
  204. ],
  205. ),
  206. ),
  207. ),
  208. ],
  209. ),
  210. ),
  211. ),
  212. ),
  213. );
  214. }
  215. }