phone_code.dart 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:dio/dio.dart';
  4. import 'package:fast/constants.dart';
  5. import 'package:fast/model/model.dart';
  6. import 'package:fast/utils/api.dart';
  7. import 'package:fast/utils/global.dart';
  8. import 'package:fast/utils/http_utils.dart';
  9. import 'package:fast/utils/size_fit.dart';
  10. import 'package:fast/utils/storage.dart';
  11. import 'package:fast/view/component/fast_btn.dart';
  12. import 'package:fast/view/invite_code.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:get/get.dart';
  15. import 'component/header.dart';
  16. import 'component/toast.dart';
  17. import 'index.dart';
  18. class PhoneCode extends StatefulWidget {
  19. int type; //1 login 2 bind phone
  20. String phone;
  21. PhoneCode({Key? key, required this.phone, required this.type})
  22. : super(key: key);
  23. @override
  24. State<PhoneCode> createState() => _PhoneCodeState();
  25. }
  26. class _PhoneCodeState extends State<PhoneCode> {
  27. String strCode = '';
  28. String strError = '输入的邀请码错误,请重新输入';
  29. bool showError = false;
  30. int seconds = 60;
  31. FocusNode focusNode = FocusNode();
  32. bool showCountdown = true;
  33. Timer? timer;
  34. @override
  35. void initState() {
  36. // TODO: implement initState
  37. super.initState();
  38. beginCountDown();
  39. }
  40. @override
  41. void dispose() {
  42. super.dispose();
  43. if (timer != null) {
  44. timer!.cancel();
  45. }
  46. }
  47. beginCountDown() {
  48. setState(() {
  49. seconds = 60;
  50. showCountdown = true;
  51. });
  52. timer = Timer.periodic(const Duration(seconds: 1), (e) {
  53. setState(() {
  54. seconds = seconds - 1;
  55. });
  56. if (seconds == 0) {
  57. showCountdown = false;
  58. timer!.cancel();
  59. }
  60. });
  61. }
  62. Future resend() async {
  63. await HttpUtils.post(Api.sendCode, data: {'mobile': widget.phone});
  64. beginCountDown();
  65. }
  66. Future verify() async {
  67. if (widget.type == 2) {
  68. try {
  69. var data = await HttpUtils.post(Api.phoneBind, data: {
  70. "app_version": "1.0",
  71. "client_type": Platform.isAndroid ? "ANDROID" : "IOS",
  72. "client_version": "1.0",
  73. 'mobile': widget.phone,
  74. 'sms_code': strCode
  75. });
  76. Get.close(2);
  77. } on DioError catch (e) {
  78. setState(() {
  79. showError = true;
  80. strError = e.response?.data['error_message'];
  81. });
  82. }
  83. return;
  84. }
  85. try {
  86. Map<String, dynamic> data = await HttpUtils.post(Api.smsLogin, data: {
  87. "app_version": "1.0",
  88. "client_type": Platform.isAndroid ? "ANDROID" : "IOS",
  89. "client_version": "1.0",
  90. 'mobile': widget.phone,
  91. 'sms_code': strCode
  92. });
  93. UserBean user = UserBean.fromJson(data);
  94. Global().userBean = user;
  95. Global().token = data['token'];
  96. Global().balance = user.rjvBalance;
  97. if (user.inputInviteCode) {
  98. //没得验证码绑定,可以输入一波
  99. //首次注册登录,弹获得多少逆龄石
  100. showRegisterSuccessToast();
  101. Timer(const Duration(milliseconds: 1300), () {
  102. Get.to(() => const InviteCode());
  103. Global().showLogin = false;
  104. Global().mainPage!.login();
  105. StorageUtil().prefs!.setString("token", data['token']);
  106. });
  107. } else {
  108. Global().showLogin = false;
  109. // Global().mainPage!.login();
  110. StorageUtil().prefs!.setString("token", data['token']);
  111. // Get.until((route) => false);
  112. Get.offAll(const IndexScreen());
  113. }
  114. } on DioError catch (e) {
  115. setState(() {
  116. showError = true;
  117. strError = e.response?.data['error_message'];
  118. });
  119. }
  120. }
  121. showRegisterSuccessToast() {
  122. if (mounted) {
  123. showDialog(
  124. context: context,
  125. barrierDismissible: false,
  126. barrierColor: Colors.transparent,
  127. builder: (BuildContext context) {
  128. return Toast(
  129. title: '成功注册',
  130. content: Row(
  131. mainAxisAlignment: MainAxisAlignment.center,
  132. children: [
  133. Text(
  134. '+9',
  135. style: TextStyle(
  136. color: Colors.white,
  137. fontSize: 16.px,
  138. fontWeight: FontWeight.w800,
  139. fontFamily: 'Exo2',
  140. decoration: TextDecoration.none),
  141. ),
  142. SizedBox(
  143. width: 3.px,
  144. ),
  145. Image.asset(
  146. 'assets/images/stone.png',
  147. width: 24.px,
  148. height: 24.px,
  149. )
  150. ],
  151. ),
  152. );
  153. });
  154. }
  155. }
  156. @override
  157. Widget build(BuildContext context) {
  158. SizeFit.initialize(context);
  159. return Material(
  160. child: Container(
  161. color: kBgColor,
  162. child: Column(
  163. children: [
  164. Stack(
  165. children: [
  166. Header(
  167. isIndexPage: false,
  168. ),
  169. Positioned(
  170. left: 16.px,
  171. top:54.px,
  172. child: GestureDetector(onTap: () => Navigator.pop(context),child: Container(
  173. width: 32.px,
  174. height: 32.px,
  175. alignment: Alignment.center,
  176. decoration: BoxDecoration(
  177. borderRadius: BorderRadius.all(Radius.circular(16.px)),
  178. color: const Color(0x33000000)
  179. ),
  180. child: Image.asset(
  181. 'assets/images/naviback.png',
  182. width: 20.px,
  183. height: 20.px,
  184. fit: BoxFit.cover,
  185. )
  186. ),))
  187. ],
  188. ),
  189. SizedBox(
  190. height: 50.px,
  191. ),
  192. Opacity(
  193. opacity: showError ? 1 : 0,
  194. child: Text(
  195. strError,
  196. style: TextStyle(color: kThemeColor, fontSize: 12.px),
  197. ),
  198. ),
  199. SizedBox(
  200. height: 10.px,
  201. ),
  202. Stack(
  203. children: [
  204. Row(
  205. mainAxisAlignment: MainAxisAlignment.center,
  206. children: [
  207. item(strCode.isNotEmpty ? strCode.substring(0, 1) : ''),
  208. SizedBox(
  209. width: 18.px,
  210. ),
  211. item(strCode.length > 1 ? strCode.substring(1, 2) : ''),
  212. SizedBox(
  213. width: 18.px,
  214. ),
  215. item(strCode.length > 2 ? strCode.substring(2, 3) : ''),
  216. SizedBox(
  217. width: 18.px,
  218. ),
  219. item(strCode.length > 3 ? strCode.substring(3, 4) : '')
  220. ],
  221. ),
  222. Opacity(
  223. opacity: 0,
  224. child: TextField(
  225. focusNode: focusNode,
  226. autofocus: true,
  227. maxLength: 4,
  228. keyboardType: TextInputType.number,
  229. onChanged: (value) {
  230. setState(() {
  231. strCode = value;
  232. });
  233. },
  234. // keyboardType: TextInputType.number,
  235. // inputFormatters: [
  236. // FilteringTextInputFormatter(RegExp("[0-9.]"), allow: true),
  237. // ],
  238. ),
  239. )
  240. ],
  241. ),
  242. SizedBox(
  243. height: 20.px,
  244. ),
  245. Row(
  246. children: [
  247. SizedBox(
  248. width: 32.px,
  249. ),
  250. Expanded(
  251. child: Text(
  252. '验证码已发到 ${widget.phone}',
  253. style: TextStyle(color: Colors.white, fontSize: 14.px),
  254. )),
  255. if (showCountdown)
  256. Text(
  257. '${seconds}s',
  258. style: TextStyle(
  259. color: const Color(0x99FFFFFF), fontSize: 14.px),
  260. ),
  261. if (!showCountdown)
  262. GestureDetector(
  263. onTap: () {
  264. resend();
  265. },
  266. child: Text(
  267. '重新发送',
  268. style: TextStyle(
  269. color: kThemeColor,
  270. fontSize: 14.px,
  271. fontWeight: FontWeight.bold),
  272. ),
  273. ),
  274. SizedBox(
  275. width: 32.px,
  276. ),
  277. ],
  278. ),
  279. SizedBox(
  280. height: 28.px,
  281. ),
  282. FastBtn(
  283. title: '验证',
  284. disable: false,
  285. // color: const Color(0x80AAFF00),
  286. width: 311.px,
  287. height: 48.px,
  288. callback: () {
  289. verify();
  290. }),
  291. ],
  292. ),
  293. ));
  294. }
  295. Widget item(String code) {
  296. return GestureDetector(
  297. onTap: () {
  298. FocusScope.of(context).requestFocus(focusNode);
  299. },
  300. child: Container(
  301. width: 64.px,
  302. height: 64.px,
  303. alignment: Alignment.center,
  304. decoration: BoxDecoration(
  305. color: const Color(0x26C4CCDA),
  306. borderRadius: BorderRadius.all(Radius.circular(16.px))),
  307. child: Text(
  308. code,
  309. style: TextStyle(
  310. color: Colors.white,
  311. fontSize: 40.px,
  312. fontFamily: 'Exo2',
  313. fontWeight: FontWeight.w600),
  314. ),
  315. ),
  316. );
  317. }
  318. }