login.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. import 'dart:async';
  2. import 'package:dio/dio.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter/services.dart';
  5. import 'package:get/get.dart';
  6. import '../constants.dart';
  7. import '../utils/api.dart';
  8. import '../utils/http_utils.dart';
  9. import '../utils/size_fit.dart';
  10. import 'component/link_btn.dart';
  11. import 'component/toast.dart';
  12. import 'component/top_container.dart';
  13. class Login extends StatefulWidget {
  14. bool _isBind = false;
  15. Login({Key? key,bool? isBind}) : super(key: key){
  16. if (isBind!=null){
  17. _isBind = isBind;
  18. }
  19. }
  20. @override
  21. State<Login> createState() => _LoginState();
  22. }
  23. class _LoginState extends State<Login> {
  24. String strContent = '';
  25. bool isPhoneSignup = true;
  26. TextEditingController controller = TextEditingController();
  27. FocusNode focusNode = FocusNode();
  28. FocusNode blankNode = FocusNode();
  29. bool checked = true;
  30. @override
  31. void initState() {
  32. // TODO: implement initState
  33. Map<String, dynamic> data = Get.parameters;
  34. if (data.isNotEmpty) {
  35. strContent = data['content']??'';
  36. isPhoneSignup = data['type'] == 'sms';
  37. controller.text = strContent;
  38. }
  39. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  40. focusNode.requestFocus();
  41. });
  42. super.initState();
  43. }
  44. @override
  45. void dispose() {
  46. // TODO: implement dispose
  47. focusNode.dispose();
  48. blankNode.dispose();
  49. super.dispose();
  50. }
  51. showSignupAlert() {
  52. FocusScope.of(context).requestFocus(blankNode);
  53. Toast().showCustomHud(
  54. Container(
  55. alignment: Alignment.center,
  56. padding: EdgeInsets.only(top: 32.px, bottom: 32.px),
  57. child: Column(
  58. children: [
  59. Text(
  60. '该${isPhoneSignup ? '手机号' : '邮箱'}尚未注册!\n不可直接登录,请前往注册',
  61. textAlign: TextAlign.center,
  62. style: TextStyle(
  63. color: Colors.white,
  64. fontSize: 16.px,
  65. fontWeight: FontWeight.bold),
  66. ),
  67. SizedBox(
  68. height: 16.px,
  69. ),
  70. AlertButton(
  71. title: '前往注册',
  72. isCancel: false,
  73. width: 220.px,
  74. height: 40.px,
  75. callback: () {
  76. Toast().hideHud();
  77. Get.toNamed('/invite_code');
  78. }),
  79. SizedBox(
  80. height: 24.px,
  81. ),
  82. AlertButton(
  83. title: '返回重新输入',
  84. isCancel: true,
  85. width: 220.px,
  86. height: 40.px,
  87. callback: () {
  88. Toast().hideHud();
  89. }),
  90. ],
  91. ),
  92. ),
  93. context: context);
  94. }
  95. Future sendCode() async {
  96. if (!checked){
  97. Toast().showInfoText('请阅读并同意协议', context: context);
  98. return;
  99. }
  100. Toast().showHud(context: context);
  101. try {
  102. if (isPhoneSignup) {
  103. Map<String, dynamic> data = await HttpUtils.get(Api.phoneCanRegister,
  104. params: {'mobile': strContent});
  105. if (data['success'] == true) {
  106. Toast().hideHud();
  107. showSignupAlert();
  108. return;
  109. }
  110. Map<String, dynamic> data2 = await HttpUtils.post(Api.phoneSendCode,
  111. data: {'mobile': strContent});
  112. print(data2.toString());
  113. } else {
  114. Map<String, dynamic> data = await HttpUtils.get(Api.emailCanRegister,
  115. params: {'email': strContent});
  116. if (data['success'] == true) {
  117. Toast().hideHud();
  118. showSignupAlert();
  119. return;
  120. }
  121. Map<String, dynamic> data2 = await HttpUtils.post(Api.emailSendCode,
  122. data: {'email': strContent});
  123. print(data2.toString());
  124. }
  125. } on DioError catch (e) {
  126. Toast().hideHud();
  127. Toast().showInfoText(e.response?.data['error_message'], context: context);
  128. return;
  129. }
  130. // ignore: nullable_type_in_catch_clause
  131. Toast().hideHud();
  132. Get.toNamed('/verify_code', parameters: {
  133. "code": '',
  134. "type": isPhoneSignup ? 'sms' : 'email',
  135. "content": strContent
  136. });
  137. }
  138. @override
  139. Widget build(BuildContext context) {
  140. SizeFit.initialize(context);
  141. return Material(
  142. color: kBgColor,
  143. child: TopContainer(
  144. child: Stack(children: [
  145. Container(
  146. padding: EdgeInsets.only(top: 71.px),
  147. child: Column(
  148. crossAxisAlignment: CrossAxisAlignment.center,
  149. children: [
  150. Image.asset(
  151. 'assets/images/logo.png',
  152. width: 167.px,
  153. height: 64.px,
  154. ),
  155. SizedBox(
  156. height: 36.px,
  157. ),
  158. Container(
  159. width: 315.px,
  160. height: 68.px,
  161. padding: EdgeInsets.only(left: 16.px, right: 16.px),
  162. decoration: BoxDecoration(
  163. borderRadius: BorderRadius.circular(16.px),
  164. color: const Color(0xFF2C2C2E)),
  165. child: Row(
  166. children: [
  167. if (isPhoneSignup)
  168. GestureDetector(
  169. onTap: () {
  170. Get.toNamed('/choose_country');
  171. },
  172. child: Row(
  173. children: [
  174. Text(
  175. '+86',
  176. style: TextStyle(
  177. fontFamily: 'Link1',
  178. color: Colors.white,
  179. fontSize: 28.px),
  180. ),
  181. SizedBox(
  182. width: 4.px,
  183. ),
  184. Image.asset(
  185. 'assets/images/arrow.png',
  186. width: 24.px,
  187. height: 24.px,
  188. )
  189. ],
  190. ),
  191. ),
  192. if (isPhoneSignup)
  193. SizedBox(
  194. width: 8.px,
  195. ),
  196. Expanded(
  197. child: TextField(
  198. autofocus: true,
  199. focusNode: focusNode,
  200. controller: controller,
  201. maxLength: isPhoneSignup ? 11 : 50,
  202. cursorColor: kBtnColor,
  203. keyboardType: isPhoneSignup
  204. ? TextInputType.number
  205. : TextInputType.emailAddress,
  206. onChanged: (value) {
  207. setState(() {
  208. strContent = value;
  209. });
  210. },
  211. onEditingComplete: (() {
  212. FocusScope.of(context).requestFocus(focusNode);
  213. }),
  214. style: TextStyle(
  215. color: Colors.white,
  216. fontSize: 28.px,
  217. fontFamily: 'Link1'),
  218. decoration: InputDecoration(
  219. border: InputBorder.none,
  220. hintText: isPhoneSignup ? '输入我的手机号' : '输入我的邮箱',
  221. hintStyle: TextStyle(
  222. fontSize: 20.px,
  223. color: const Color(0xFF74747A)),
  224. counterText: "",
  225. ),
  226. // keyboardType: TextInputType.number,
  227. inputFormatters: isPhoneSignup
  228. ? [
  229. FilteringTextInputFormatter(
  230. RegExp("[0-9.]"),
  231. allow: true),
  232. ]
  233. : [
  234. // FilteringTextInputFormatter(RegExp("[0-9.]"),
  235. // allow: true),
  236. ],
  237. )),
  238. Opacity(
  239. opacity: strContent.isNotEmpty ? 1 : 0,
  240. child: GestureDetector(
  241. onTap: () {
  242. setState(() {
  243. strContent = '';
  244. controller.clear();
  245. });
  246. },
  247. child: Image.asset(
  248. 'assets/images/clear.png',
  249. width: 24.px,
  250. height: 24.px,
  251. ),
  252. ),
  253. )
  254. ],
  255. ),
  256. ),
  257. SizedBox(
  258. height: 36.px,
  259. ),
  260. LinkButton(
  261. title: isPhoneSignup ? '发送短信验证码' : '发送邮箱验证码',
  262. disable: false,
  263. isBlack: false,
  264. callback: () {
  265. sendCode();
  266. // Get.toNamed('/signup_code');
  267. }),
  268. SizedBox(
  269. height: 37.px,
  270. ),
  271. if (!widget._isBind)
  272. Row(
  273. mainAxisAlignment: MainAxisAlignment.center,
  274. children: [
  275. GestureDetector(
  276. onTap: (){
  277. setState(() {
  278. checked = !checked;
  279. });
  280. },
  281. child: Image.asset(
  282. checked?'assets/images/checked.png':'assets/images/check.png',
  283. width: 18.px,
  284. height: 18.px,
  285. ),
  286. ),
  287. SizedBox(
  288. width: 7.px,
  289. ),
  290. Text(
  291. '已阅读并同意',
  292. style: TextStyle(
  293. color: const Color(0xFF74747A), fontSize: 12.px),
  294. ),
  295. GestureDetector(
  296. child: Text(
  297. '《用户服务协议》',
  298. style: TextStyle(color: kBtnColor, fontSize: 12.px),
  299. ),
  300. ),
  301. GestureDetector(
  302. child: Text(
  303. '《隐私权政策》',
  304. style: TextStyle(color: kBtnColor, fontSize: 12.px),
  305. ),
  306. )
  307. ],
  308. ),
  309. Expanded(
  310. child: Container(),
  311. ),
  312. if (!widget._isBind)
  313. GestureDetector(
  314. onTap: () {
  315. setState(() {
  316. strContent = '';
  317. controller.clear();
  318. isPhoneSignup = !isPhoneSignup;
  319. });
  320. },
  321. child: Text(
  322. isPhoneSignup ? '使用邮箱登录' : '使用手机登录',
  323. style: TextStyle(
  324. color: const Color(0xFF808080), fontSize: 14.px),
  325. ),
  326. ),
  327. SizedBox(
  328. height: 50.px,
  329. )
  330. ]))
  331. ])));
  332. }
  333. }