SignUpPage.dart 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_habit/common/BaseArchitectural.dart';
  4. import 'package:flutter_habit/common/I18N.dart';
  5. import 'package:flutter_habit/common/utils/VerificationUtils.dart';
  6. import 'package:flutter_habit/network/Repository.dart';
  7. import 'package:provider/provider.dart';
  8. class SignUpPage extends StatelessWidget {
  9. @override
  10. Widget build(BuildContext context) {
  11. return MultiProvider(
  12. providers: [
  13. ChangeNotifierProvider<SignUpPageService>(
  14. create: (_) => SignUpPageService(context)),
  15. ChangeNotifierProvider<SignUpPageModel>(
  16. create: (_) => SignUpPageModel(context)),
  17. ],
  18. child: _SignUpPageView(),
  19. );
  20. }
  21. }
  22. // model
  23. class SignUpPageModel extends BaseModel {
  24. SignUpPageModel(BuildContext context) : super(context);
  25. late bool isPwdVisible;
  26. late bool isRequesting;
  27. int? counter;
  28. GlobalKey emailFormKey = GlobalKey<FormState>();
  29. GlobalKey pwdFormKey = GlobalKey<FormState>();
  30. TextEditingController? emailController;
  31. TextEditingController? authCodeController;
  32. TextEditingController? pwdController;
  33. TextEditingController? pwdRepeatController;
  34. Timer? timer;
  35. @override
  36. void init(BuildContext context) {
  37. super.init(context);
  38. isPwdVisible = false;
  39. isRequesting = false;
  40. counter = 0;
  41. emailController = TextEditingController();
  42. authCodeController = TextEditingController();
  43. pwdController = TextEditingController();
  44. pwdRepeatController = TextEditingController();
  45. timer = null;
  46. }
  47. @override
  48. void dispose() {
  49. super.dispose();
  50. if (timer != null) {
  51. timer!.cancel();
  52. }
  53. }
  54. }
  55. // service
  56. class SignUpPageService extends BaseProvider {
  57. SignUpPageService(BuildContext context) : super(context);
  58. String? validatorEmail(String? v) {
  59. if (VerifyUtils.isEmail(v)) {
  60. return null;
  61. } else {
  62. return I18N.of("邮箱格式有误");
  63. }
  64. }
  65. String? validatorPwd(String? v) {
  66. if (VerifyUtils.isPassword(v)) {
  67. return null;
  68. } else {
  69. return I18N.of("字母开头,必须包含大小写字母,可以包含字母、数字、特殊符号\n长度为8~16位");
  70. }
  71. }
  72. String? validatorPwdRepeat(BuildContext context) {
  73. SignUpPageModel model =
  74. Provider.of<SignUpPageModel>(context, listen: false);
  75. if (model.pwdController!.text == model.pwdRepeatController!.text) {
  76. return null;
  77. } else {
  78. return I18N.of("两次输入不一致");
  79. }
  80. }
  81. void pwdChangeVisible(BuildContext context) {
  82. SignUpPageModel model =
  83. Provider.of<SignUpPageModel>(context, listen: false);
  84. model.isPwdVisible = !model.isPwdVisible;
  85. model.refresh();
  86. }
  87. Future<void> sendAuthCode(BuildContext context) async {
  88. SignUpPageModel model =
  89. Provider.of<SignUpPageModel>(context, listen: false);
  90. model.isRequesting = true;
  91. model.refresh();
  92. if ((model.emailFormKey.currentState as FormState).validate()) {
  93. bool isSuccess = await Repository.getInstance()!.sendAuthCode(
  94. context,
  95. model.emailController!.text,
  96. "SIGN_UP",
  97. );
  98. if (isSuccess) {
  99. startCounter(context);
  100. }
  101. }
  102. model.isRequesting = false;
  103. model.refresh();
  104. }
  105. void startCounter(BuildContext context) {
  106. SignUpPageModel model =
  107. Provider.of<SignUpPageModel>(context, listen: false);
  108. model.counter = 60;
  109. model.refresh();
  110. model.timer = Timer.periodic(Duration(seconds: 1), (t) {
  111. model.counter--;
  112. model.refresh();
  113. if (model.counter == 0) {
  114. model.timer!.cancel();
  115. }
  116. });
  117. }
  118. Future<void> signUp(BuildContext context) async {
  119. SignUpPageModel model =
  120. Provider.of<SignUpPageModel>(context, listen: false);
  121. model.isRequesting = true;
  122. model.refresh();
  123. if ((model.pwdFormKey.currentState as FormState).validate()) {
  124. bool isSuccess = await Repository.getInstance()!.signUp(
  125. context,
  126. model.authCodeController!.text,
  127. model.emailController!.text,
  128. model.pwdController!.text,
  129. );
  130. if (isSuccess) {
  131. Navigator.of(context).pop(model.emailController!.text);
  132. }
  133. }
  134. model.isRequesting = false;
  135. model.refresh();
  136. }
  137. }
  138. // view
  139. class _SignUpPageView extends StatelessWidget {
  140. @override
  141. Widget build(BuildContext context) {
  142. SignUpPageService service =
  143. Provider.of<SignUpPageService>(context, listen: false);
  144. SignUpPageModel model = Provider.of<SignUpPageModel>(context, listen: true);
  145. return Scaffold(
  146. appBar: AppBar(
  147. title: Text("注册"),
  148. ),
  149. body: Padding(
  150. padding: EdgeInsets.all(16),
  151. child: ListView(
  152. children: <Widget>[
  153. model.isRequesting ? LinearProgressIndicator() : Container(),
  154. Center(
  155. child: Icon(
  156. Icons.compare_arrows,
  157. size: 220,
  158. color: Theme.of(context).unselectedWidgetColor,
  159. ),
  160. ),
  161. Form(
  162. key: model.emailFormKey,
  163. child: Column(
  164. children: <Widget>[
  165. TextFormField(
  166. controller: model.emailController,
  167. enabled: !model.isRequesting,
  168. decoration: InputDecoration(
  169. labelText: I18N.of("邮箱"),
  170. hintText: I18N.of("请输入您的邮箱"),
  171. prefixIcon: Icon(Icons.email),
  172. ),
  173. validator: (v) => service.validatorEmail(v),
  174. ),
  175. TextFormField(
  176. controller: model.authCodeController,
  177. keyboardType: TextInputType.number,
  178. enabled: !model.isRequesting,
  179. decoration: InputDecoration(
  180. labelText: I18N.of("验证码"),
  181. hintText: I18N.of("请输入6位验证码"),
  182. prefixIcon: Icon(Icons.security),
  183. suffixIcon: Padding(
  184. padding: EdgeInsets.only(top: 10),
  185. child: ElevatedButton(
  186. child: Text(
  187. I18N.of("获取验证码") +
  188. ((model.counter != 0)
  189. ? " ${model.counter}"
  190. : ""),
  191. style: TextStyle(
  192. color: Theme.of(context).cardColor,
  193. ),
  194. ),
  195. style: ButtonStyle(
  196. backgroundColor: MaterialStateProperty.all(
  197. Theme.of(context).colorScheme.secondary),
  198. foregroundColor: MaterialStateProperty.all(
  199. Theme.of(context).cardColor),
  200. shape: MaterialStateProperty.all(
  201. RoundedRectangleBorder(
  202. borderRadius: BorderRadius.circular(10.0),
  203. ))),
  204. onPressed: model.isRequesting || model.counter != 0
  205. ? null
  206. : () => service.sendAuthCode(context),
  207. ),
  208. ),
  209. ),
  210. ),
  211. ],
  212. ),
  213. ),
  214. Form(
  215. key: model.pwdFormKey,
  216. child: Column(
  217. children: <Widget>[
  218. TextFormField(
  219. controller: model.pwdController,
  220. enabled: !model.isRequesting,
  221. obscureText: !model.isPwdVisible,
  222. decoration: InputDecoration(
  223. labelText: I18N.of("密码"),
  224. hintText: I18N.of("请输入您的密码"),
  225. prefixIcon: Icon(Icons.lock_outline),
  226. suffixIcon: IconButton(
  227. icon: Icon(
  228. model.isPwdVisible
  229. ? Icons.visibility
  230. : Icons.visibility_off,
  231. ),
  232. onPressed: () => service.pwdChangeVisible(context),
  233. ),
  234. ),
  235. validator: (v) => service.validatorPwd(v),
  236. ),
  237. TextFormField(
  238. controller: model.pwdRepeatController,
  239. enabled: !model.isRequesting,
  240. obscureText: true,
  241. decoration: InputDecoration(
  242. labelText: I18N.of("重复密码"),
  243. hintText: I18N.of("请重复输入您的密码"),
  244. prefixIcon: Icon(Icons.lock),
  245. ),
  246. validator: (v) => service.validatorPwdRepeat(context),
  247. ),
  248. ],
  249. ),
  250. ),
  251. Padding(
  252. padding: EdgeInsets.only(top: 10),
  253. child: ElevatedButton(
  254. child: Text(
  255. I18N.of("注册"),
  256. style: TextStyle(
  257. color: Theme.of(context).cardColor,
  258. ),
  259. ),
  260. style: ButtonStyle(
  261. backgroundColor: MaterialStateProperty.all(
  262. Theme.of(context).colorScheme.secondary),
  263. foregroundColor:
  264. MaterialStateProperty.all(Theme.of(context).cardColor),
  265. shape: MaterialStateProperty.all(RoundedRectangleBorder(
  266. borderRadius: BorderRadius.circular(5.0),
  267. ))),
  268. onPressed:
  269. model.isRequesting ? null : () => service.signUp(context),
  270. ),
  271. ),
  272. ],
  273. ),
  274. ),
  275. );
  276. }
  277. }