bindphone_dialog.dart 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import 'dart:async';
  2. import 'dart:math';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:shared_preferences/shared_preferences.dart';
  6. import 'package:sport/pages/login/login_widget.dart';
  7. import 'package:sport/provider/login_info_model.dart';
  8. import 'package:sport/utils/toast.dart';
  9. import 'package:sport/widgets/button_cancel.dart';
  10. import 'package:sport/widgets/button_primary.dart';
  11. import 'package:sport/widgets/dialog/request_dialog.dart';
  12. import 'package:sport/widgets/misc.dart';
  13. class BindPhoneDialog extends StatefulWidget {
  14. @override
  15. State<StatefulWidget> createState() {
  16. return _BindPhoneDialog();
  17. }
  18. }
  19. class _BindPhoneDialog extends State<BindPhoneDialog> {
  20. String _phone = "";
  21. String _code = "";
  22. FocusNode _codeFocus;
  23. Timer _timer;
  24. ValueNotifier<int> _seconds = ValueNotifier(0);
  25. @override
  26. void initState() {
  27. super.initState();
  28. _codeFocus = FocusNode();
  29. }
  30. @override
  31. void dispose() {
  32. super.dispose();
  33. _codeFocus?.dispose();
  34. _cancelTimer();
  35. }
  36. void _cancelTimer() {
  37. if (_timer != null) {
  38. _timer.cancel();
  39. _timer = null;
  40. }
  41. }
  42. void _startTimer() {
  43. _cancelTimer();
  44. _seconds.value = 60;
  45. const period = const Duration(seconds: 1);
  46. _timer = Timer.periodic(period, (timer) {
  47. //更新界面
  48. _seconds.value = _seconds.value - 1;
  49. if (_seconds.value <= 0) {
  50. setState(() {
  51. _cancelTimer();
  52. });
  53. }
  54. });
  55. setState(() {});
  56. }
  57. @override
  58. Widget build(BuildContext context) {
  59. return Dialog(
  60. backgroundColor: Colors.transparent,
  61. elevation: 0,
  62. // shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
  63. child: Container(
  64. decoration: BoxDecoration(
  65. borderRadius: BorderRadius.all(Radius.circular(10.0)),
  66. color: Colors.white,
  67. ),
  68. child: Stack(
  69. children: <Widget>[
  70. SingleChildScrollView(
  71. child: Column(
  72. children: <Widget>[
  73. SizedBox(height: 30,),
  74. Text(
  75. "绑定号码",
  76. style: Theme.of(context).textTheme.headline1,
  77. strutStyle: fixedLine,
  78. ),
  79. Padding(
  80. padding: const EdgeInsets.all(16.0),
  81. child: Column(
  82. mainAxisSize: MainAxisSize.min,
  83. children: <Widget>[
  84. Input(
  85. width: double.infinity,
  86. labelText: "请输入手机号",
  87. height: 35,
  88. textInputType: TextInputType.phone,
  89. maxLength: 11,
  90. callBack: (value) {
  91. _phone = value;
  92. _phone = _phone.substring(0, min(11, _phone.length));
  93. },
  94. ),
  95. Row(
  96. children: <Widget>[
  97. Expanded(
  98. child: Input(
  99. height: 35,
  100. width: double.infinity,
  101. focusNode: _codeFocus,
  102. labelText: "请输入验证码",
  103. textInputType: TextInputType.number,
  104. maxLength: 4,
  105. callBack: (value) {
  106. _code = value;
  107. _code = _code.substring(0, min(4, _code.length));
  108. },
  109. ),
  110. ),
  111. SizedBox(
  112. width: 10,
  113. ),
  114. InkWell(
  115. onTap: () async {
  116. if (_phone.length < 11) {
  117. ToastUtil.show("请输入正确的手机码号码");
  118. return;
  119. }
  120. if (_seconds.value > 0) return;
  121. final _loginInfoModel = LoginInfoModel();
  122. var code = await request(context, () async {
  123. return await _loginInfoModel.getCaptcha(_phone).catchError((err) {});
  124. });
  125. if (code == true) {
  126. _startTimer();
  127. _codeFocus.requestFocus();
  128. }
  129. },
  130. child: Container(
  131. width: 95,
  132. child: Center(
  133. child: _seconds.value > 0
  134. ? ValueListenableBuilder(
  135. valueListenable: _seconds,
  136. builder: (BuildContext context, int value, Widget child) => Text(
  137. "${value}s后重新获取",
  138. style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor),
  139. ),
  140. )
  141. : Text(
  142. "发送验证码",
  143. style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor),
  144. ),
  145. )))
  146. ],
  147. ),
  148. SizedBox(
  149. height: 6,
  150. ),
  151. Text(
  152. "根据相关条约与法律法规,您需要进行手机号码绑定才可进行相关操作",
  153. style: Theme.of(context).textTheme.bodyText1.copyWith(color: Color(0xffc2c2c2)),
  154. strutStyle: StrutStyle(height: 1.4),
  155. ),
  156. SizedBox(
  157. height: 16,
  158. ),
  159. Row(
  160. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  161. children: <Widget>[
  162. Expanded(
  163. child: CancelButton(
  164. height: 35,
  165. callback: () {
  166. Navigator.of(context).pop(false);
  167. },
  168. content: "取消"),
  169. ),
  170. SizedBox(
  171. width: 16,
  172. ),
  173. Expanded(
  174. child: PrimaryButton(
  175. height: 35,
  176. callback: () async {
  177. final _loginInfoModel = LoginInfoModel();
  178. var result = await _loginInfoModel.loginApi.bindPhone(_phone, _code);
  179. if (result != null && result['code'] == 0) {
  180. _loginInfoModel.saveUserInfo({"phone": _phone});
  181. ToastUtil.show("绑定成功");
  182. Navigator.of(context).pop(true);
  183. }
  184. },
  185. content: "绑定"),
  186. )
  187. ],
  188. )
  189. ],
  190. ),
  191. )
  192. ],
  193. ),
  194. ),
  195. Positioned(
  196. right: 0,top: 0,
  197. child: IconButton(
  198. icon: Image.asset("lib/assets/img/btn_close_big.png"),
  199. onPressed: () => Navigator.pop(context, false),
  200. )),
  201. ],
  202. ),
  203. ),
  204. );
  205. }
  206. }
  207. Future<bool> showBindPhoneDialog(BuildContext context) async {
  208. SharedPreferences preferences = await SharedPreferences.getInstance();
  209. bool result = (preferences.get("phone") ?? "").toString().length > 0 ;
  210. if (!result) {
  211. result = await showDialog(context: context, builder: (context) => BindPhoneDialog());
  212. }
  213. return result;
  214. }