registered_page.dart 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'package:bbyyy/beans/login_information_bean_entity.dart';
  5. import 'package:bbyyy/beans/upload_image_bean_entity.dart';
  6. import 'package:bbyyy/https/MyDio.dart';
  7. import 'package:bbyyy/https/my_request.dart';
  8. import 'package:bbyyy/my_tools/my_apis.dart';
  9. import 'package:bbyyy/my_tools/my_colors.dart';
  10. import 'package:bbyyy/my_tools/my_cookie.dart';
  11. import 'package:bbyyy/my_tools/my_tools.dart';
  12. import 'package:bbyyy/my_tools/my_views.dart';
  13. import 'package:bbyyy/my_tools/protocol.dart';
  14. import 'package:bbyyy/paegs/login_page/login_page.dart';
  15. import 'package:bbyyy/paegs/root_page/root_page.dart';
  16. import 'package:flutter/cupertino.dart';
  17. import 'package:flutter/gestures.dart';
  18. import 'package:flutter/material.dart';
  19. import 'package:flutter/services.dart';
  20. import 'package:flutter_svg/svg.dart';
  21. import 'package:image_cropper/image_cropper.dart';
  22. import 'package:image_picker/image_picker.dart';
  23. class RegisteredPage extends StatefulWidget {
  24. @override
  25. _RegisteredPageState createState() => _RegisteredPageState();
  26. }
  27. class _RegisteredPageState extends State<RegisteredPage> {
  28. TextEditingController _phoneNum = TextEditingController(text: '');
  29. TextEditingController _verificationCode = TextEditingController(text: '');
  30. TextEditingController _nickname = TextEditingController(text: '');
  31. TextEditingController _pw = TextEditingController(text: '');
  32. bool showPW = true;
  33. int focus = -1;
  34. bool haveRead = false;
  35. String verificationCodeText = '发送验证码';
  36. File _image;
  37. final picker = ImagePicker();
  38. Timer _timer;
  39. @override
  40. Widget build(BuildContext context) {
  41. return GestureDetector(
  42. onTap: () {
  43. MyTools().hideKeyboard(context);
  44. setState(() {
  45. focus = -1;
  46. });
  47. },
  48. child: Scaffold(
  49. body: SingleChildScrollView(
  50. child: Column(
  51. children: [
  52. Column(
  53. children: [
  54. Container(
  55. height: MediaQuery.of(context).size.width * (506 / 750),
  56. child: Stack(
  57. children: [
  58. Image.asset(
  59. 'images/bg_1.png',
  60. width: MediaQuery.of(context).size.width,
  61. height:
  62. MediaQuery.of(context).size.width * (506 / 750),
  63. ),
  64. Positioned(
  65. top: 67,
  66. child: Column(
  67. children: [
  68. Stack(
  69. children: [
  70. Image.asset(
  71. 'images/yuan_bg.png',
  72. height: 147,
  73. width: 147,
  74. ),
  75. GestureDetector(
  76. child: _image == null
  77. ? SvgPicture.asset(
  78. 'images/svg/头像上传.svg',
  79. height: 75,
  80. width: 75,
  81. )
  82. : ClipRRect(
  83. child: Image.file(
  84. _image,
  85. height: 75,
  86. width: 75,
  87. ),
  88. borderRadius: BorderRadius.all(
  89. Radius.circular(75 / 2)),
  90. ),
  91. onTap: () async {
  92. final pickedFile = await picker.getImage(
  93. source: ImageSource.gallery);
  94. print('pickedFile---${pickedFile.path}');
  95. if (pickedFile != null) {
  96. File cropperImg =
  97. await ImageCropper.cropImage(
  98. sourcePath: pickedFile.path,
  99. cropStyle: CropStyle.rectangle,
  100. aspectRatio: CropAspectRatio(
  101. ratioX: 1, ratioY: 1),
  102. aspectRatioPresets: [
  103. CropAspectRatioPreset.square,
  104. ],
  105. androidUiSettings:
  106. AndroidUiSettings(
  107. toolbarTitle: '图片剪裁',
  108. toolbarColor:
  109. MyColors.cFF4233,
  110. toolbarWidgetColor:
  111. Colors.white,
  112. initAspectRatio:
  113. CropAspectRatioPreset
  114. .square,
  115. lockAspectRatio: true),
  116. iosUiSettings: IOSUiSettings(
  117. minimumAspectRatio: 1.0,
  118. resetAspectRatioEnabled:
  119. false,
  120. rotateButtonsHidden: true));
  121. if (cropperImg != null) {
  122. setState(() {
  123. print(
  124. 'cropperImg---${cropperImg.path}');
  125. _image = cropperImg;
  126. print('_image---${_image.path}');
  127. });
  128. }
  129. }
  130. },
  131. behavior: HitTestBehavior.translucent,
  132. )
  133. ],
  134. alignment: Alignment.center,
  135. ),
  136. Container(
  137. child: Text(
  138. '头像上传',
  139. style: TextStyle(
  140. color: Colors.white, fontSize: 14),
  141. ),
  142. margin: EdgeInsets.only(top: 6),
  143. )
  144. ],
  145. ),
  146. )
  147. ],
  148. alignment: Alignment.topCenter,
  149. ),
  150. ),
  151. Container(
  152. padding: EdgeInsets.only(left: 47, right: 47, top: 26),
  153. child: Column(
  154. children: [
  155. // Container(
  156. // child: Text(
  157. // 'Hello Welcome !',
  158. // style: TextStyle(
  159. // color: MyColors.cFF4233, fontSize: 24),
  160. // ),
  161. // margin: EdgeInsets.only(bottom: 25),
  162. // ),
  163. Row(
  164. children: [
  165. Container(
  166. child: SvgPicture.asset(
  167. 'images/svg/手机.svg',
  168. height: 22,
  169. width: 22,
  170. ),
  171. height: 22,
  172. width: 22,
  173. ),
  174. Expanded(
  175. child: TextField(
  176. controller: _phoneNum,
  177. inputFormatters: [
  178. onlyInputNumberAndWorkFormatter(),
  179. LengthLimitingTextInputFormatter(11)
  180. ],
  181. cursorColor: MyColors.cFF4233,
  182. cursorWidth: 1.0,
  183. onTap: () {
  184. setState(() {
  185. focus = 0;
  186. });
  187. },
  188. decoration: InputDecoration(
  189. border: InputBorder.none,
  190. disabledBorder: InputBorder.none,
  191. enabledBorder: InputBorder.none,
  192. focusedBorder: InputBorder.none,
  193. isDense: true,
  194. hintText: '请输入手机号',
  195. hintStyle: TextStyle(
  196. color: MyColors.c999999, fontSize: 16),
  197. contentPadding: const EdgeInsets.fromLTRB(
  198. 14, 4.5, 8, 4.5),
  199. ),
  200. maxLines: 1,
  201. style: TextStyle(
  202. color: MyColors.c333333,
  203. fontSize: 16,
  204. height: 1.3,
  205. letterSpacing: 0.2),
  206. keyboardType: TextInputType.number,
  207. onChanged: (t) {},
  208. ),
  209. )
  210. ],
  211. ),
  212. Container(
  213. height: 1,
  214. color:
  215. focus == 0 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  216. margin: EdgeInsets.only(top: 8, bottom: 39),
  217. ),
  218. Row(
  219. children: [
  220. Container(
  221. child: SvgPicture.asset(
  222. 'images/svg/昵称.svg',
  223. height: 22,
  224. width: 22,
  225. ),
  226. height: 22,
  227. width: 22,
  228. ),
  229. Expanded(
  230. child: TextField(
  231. inputFormatters: [
  232. LengthLimitingTextInputFormatter(12)
  233. ],
  234. controller: _nickname,
  235. cursorColor: MyColors.cFF4233,
  236. cursorWidth: 1.0,
  237. onTap: () {
  238. setState(() {
  239. focus = 2;
  240. });
  241. },
  242. decoration: InputDecoration(
  243. border: InputBorder.none,
  244. disabledBorder: InputBorder.none,
  245. enabledBorder: InputBorder.none,
  246. focusedBorder: InputBorder.none,
  247. hintText: '请输入昵称',
  248. hintStyle: TextStyle(
  249. color: MyColors.c999999, fontSize: 16),
  250. isDense: true,
  251. contentPadding: const EdgeInsets.fromLTRB(
  252. 14, 4.5, 8, 4.5)),
  253. maxLines: 1,
  254. style: TextStyle(
  255. color: MyColors.c333333,
  256. fontSize: 16,
  257. height: 1.3,
  258. letterSpacing: 0.2),
  259. keyboardType: TextInputType.text,
  260. onChanged: (t) {},
  261. ),
  262. ),
  263. ],
  264. ),
  265. Container(
  266. height: 1,
  267. color:
  268. focus == 2 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  269. margin: EdgeInsets.only(top: 8, bottom: 39),
  270. ),
  271. Row(
  272. children: [
  273. Container(
  274. child: SvgPicture.asset(
  275. 'images/svg/验证码.svg',
  276. height: 22,
  277. width: 22,
  278. ),
  279. height: 22,
  280. width: 22,
  281. ),
  282. Expanded(
  283. child: TextField(
  284. controller: _verificationCode,
  285. cursorColor: MyColors.cFF4233,
  286. cursorWidth: 1.0,
  287. inputFormatters: [
  288. onlyInputNumberAndWorkFormatter(),
  289. LengthLimitingTextInputFormatter(6)
  290. ],
  291. onTap: () {
  292. setState(() {
  293. focus = 1;
  294. });
  295. },
  296. decoration: InputDecoration(
  297. border: InputBorder.none,
  298. disabledBorder: InputBorder.none,
  299. enabledBorder: InputBorder.none,
  300. focusedBorder: InputBorder.none,
  301. hintText: '请输入验证码',
  302. hintStyle: TextStyle(
  303. color: MyColors.c999999, fontSize: 16),
  304. isDense: true,
  305. contentPadding:
  306. const EdgeInsets.fromLTRB(14, 4.5, 8, 4.5)),
  307. maxLines: 1,
  308. style: TextStyle(
  309. color: MyColors.c333333,
  310. fontSize: 16,
  311. height: 1.3,
  312. letterSpacing: 0.2),
  313. keyboardType: TextInputType.number,
  314. onChanged: (t) {},
  315. ),
  316. ),
  317. GestureDetector(
  318. onTap: (){
  319. if(verificationCodeText!='发送验证码'){
  320. showToast('验证码发送中');
  321. return;
  322. }
  323. sendTheVerificationCode();
  324. },
  325. behavior: HitTestBehavior.translucent,
  326. child: Container(
  327. decoration: BoxDecoration(
  328. color: MyColors.c19FF4233,
  329. borderRadius:
  330. BorderRadius.all(Radius.circular(4))),
  331. child: Text(verificationCodeText,style: TextStyle(color: MyColors.cFF4233,fontSize: 14),),
  332. alignment: Alignment.center,
  333. height: 34,
  334. width: 90,
  335. ),
  336. )
  337. ],
  338. ),
  339. Container(
  340. height: 1,
  341. color:
  342. focus == 1 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  343. margin: EdgeInsets.only(top: 8, bottom: 39),
  344. ),
  345. Row(
  346. children: [
  347. Container(
  348. child: SvgPicture.asset(
  349. 'images/svg/密码.svg',
  350. height: 22,
  351. width: 22,
  352. ),
  353. height: 22,
  354. width: 22,
  355. ),
  356. Expanded(
  357. child: TextField(
  358. controller: _pw,
  359. inputFormatters: [
  360. onlyInputNumberAndWorkFormatter(),
  361. LengthLimitingTextInputFormatter(8)
  362. ],
  363. cursorColor: MyColors.cFF4233,
  364. cursorWidth: 1.0,
  365. onTap: () {
  366. setState(() {
  367. focus = 3;
  368. });
  369. },
  370. decoration: InputDecoration(
  371. border: InputBorder.none,
  372. disabledBorder: InputBorder.none,
  373. enabledBorder: InputBorder.none,
  374. focusedBorder: InputBorder.none,
  375. hintText: '请输入密码(6到8位)',
  376. hintStyle: TextStyle(
  377. color: MyColors.c999999, fontSize: 16),
  378. isDense: true,
  379. contentPadding: const EdgeInsets.fromLTRB(
  380. 14, 4.5, 8, 4.5)),
  381. maxLines: 1,
  382. style: TextStyle(
  383. color: MyColors.c333333,
  384. fontSize: 16,
  385. height: 1.3,
  386. letterSpacing: 0.2),
  387. keyboardType: TextInputType.visiblePassword,
  388. obscureText: !showPW,
  389. onChanged: (t) {},
  390. ),
  391. ),
  392. GestureDetector(
  393. onTap: () {
  394. setState(() {
  395. showPW = !showPW;
  396. });
  397. },
  398. behavior: HitTestBehavior.translucent,
  399. child: Container(
  400. height: 30,width: 30,
  401. padding: EdgeInsets.all(4),
  402. child: SvgPicture.asset(showPW
  403. ? 'images/svg/不显示.svg'
  404. : 'images/svg/显示.svg'))),
  405. ],
  406. ),
  407. Container(
  408. height: 1,
  409. color:
  410. focus == 3 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  411. margin: EdgeInsets.only(top: 8, bottom: 20),
  412. ),
  413. Row(
  414. children: [
  415. Checkbox(
  416. value: haveRead,
  417. onChanged: (v) {
  418. setState(() {
  419. haveRead = v;
  420. });
  421. },
  422. activeColor: MyColors.cFF4233,
  423. ),
  424. RichText(
  425. text: TextSpan(
  426. text: '我已阅读并同意',
  427. style: TextStyle(
  428. color: MyColors.c999999, fontSize: 12),
  429. children: [
  430. TextSpan(
  431. text: '《使用协议》',
  432. style: TextStyle(
  433. color: MyColors.cFF4233,
  434. fontSize: 12),
  435. recognizer: TapGestureRecognizer()
  436. ..onTap = () {
  437. MyTools().toPage(
  438. context,
  439. PrivacyPolicyPage('使用协议'),
  440. (then) {});
  441. }),
  442. TextSpan(
  443. text: '和',
  444. style: TextStyle(
  445. color: MyColors.c999999,
  446. fontSize: 12),
  447. ),
  448. TextSpan(
  449. text: '《隐私政策》',
  450. style: TextStyle(
  451. color: MyColors.cFF4233,
  452. fontSize: 12),
  453. recognizer: TapGestureRecognizer()
  454. ..onTap = () {
  455. MyTools().toPage(
  456. context,
  457. PrivacyPolicyPage('隐私政策'),
  458. (then) {});
  459. }),
  460. ]),
  461. ),
  462. ],
  463. mainAxisAlignment: MainAxisAlignment.end,
  464. ),
  465. GestureDetector(
  466. onTap: () {
  467. if (_phoneNum.text.isEmpty ||
  468. _phoneNum.text.length != 11) {
  469. showToast('请填写正确的手机号');
  470. return;
  471. }
  472. if (_pw.text.isEmpty || _pw.text.length < 6) {
  473. showToast('请填写正确的密码(由数字和字母组合的至少6位的组合)');
  474. return;
  475. }
  476. if (_nickname.text.isEmpty) {
  477. showToast('请填写昵称');
  478. return;
  479. }
  480. if (_verificationCode.text.isEmpty) {
  481. showToast('请填写验证码');
  482. return;
  483. }
  484. if (_image == null) {
  485. showToast('请设置头像');
  486. return;
  487. }
  488. if (!haveRead) {
  489. showToast('请阅读并同意《隐私政策》');
  490. return;
  491. }
  492. verificationCode();
  493. },
  494. behavior: HitTestBehavior.translucent,
  495. child: Container(
  496. margin: EdgeInsets.only(top: 20),
  497. decoration: BoxDecoration(
  498. borderRadius: BorderRadius.all(
  499. Radius.circular(20),
  500. ),
  501. gradient: LinearGradient(
  502. colors: MyColors.lg,
  503. ),
  504. ),
  505. height: 44,
  506. child: Text(
  507. '注 册',
  508. style:
  509. TextStyle(color: Colors.white, fontSize: 17),
  510. ),
  511. alignment: Alignment.center,
  512. padding: EdgeInsets.only(bottom: 2),
  513. ),
  514. ),
  515. Container(
  516. margin: EdgeInsets.only(top: 20),
  517. alignment: Alignment.centerRight,
  518. child: GestureDetector(
  519. onTap: () {
  520. MyTools().toPage(context, LoginPage(), (then) {},
  521. noBack: true);
  522. },
  523. behavior: HitTestBehavior.translucent,
  524. child: Container(
  525. child: Text(
  526. '已有账号,去登录',
  527. style: TextStyle(
  528. color: MyColors.cFF4233, fontSize: 13),
  529. ),
  530. padding: EdgeInsets.all(8),
  531. ),
  532. ),
  533. ),
  534. ],
  535. crossAxisAlignment: CrossAxisAlignment.start,
  536. ),
  537. ),
  538. ],
  539. ),
  540. ],
  541. ),
  542. ),
  543. ),
  544. );
  545. }
  546. void uploadAvatar() {
  547. upload(_image, (r, hasError) {
  548. if (!hasError) {
  549. UploadImageBeanEntity data =
  550. UploadImageBeanEntity().fromJson(json.decode(r.data.toString()));
  551. registered(data);
  552. }
  553. }, (error) {});
  554. }
  555. void registered(UploadImageBeanEntity data) {
  556. registeredAccountNumber({
  557. 'mobile': _phoneNum.text,
  558. 'name': _nickname.text,
  559. 'password': MyTools.base64Encode(_pw.text),
  560. 'picture': data.data[0].path,
  561. }, (re, hasError) {
  562. if (!hasError) {
  563. // showToast('注册成功');
  564. // MyTools().toPage(
  565. // context, LoginPage(), (then) {},
  566. // noBack: true);
  567. _timer.cancel();
  568. loginAccount({
  569. 'user': _phoneNum.text,
  570. 'password': MyTools.base64Encode(_pw.text),
  571. 'version': MyCookie().packageInfo.version,
  572. 'phone': Platform.isAndroid ? 'Android' : 'IOS'
  573. }, (r, hE) {
  574. if (!hE) {
  575. LoginInformationBeanEntity entity = LoginInformationBeanEntity()
  576. .fromJson(json.decode(r.data.toString()));
  577. MyCookie().saveLoginInformationBeanEntity(entity);
  578. MyDio().initDio();
  579. MyTools().toPage(context, RootPage(), (then) {}, noBack: true);
  580. }
  581. }, (e) {});
  582. }
  583. }, (error) {});
  584. }
  585. int countdown = 60;
  586. void sendTheVerificationCode() {
  587. if(_phoneNum.text.isEmpty||_phoneNum.text.length!=11){
  588. showToast('请输入正确的手机号');
  589. return;
  590. }
  591. MyDio().post(MyApis.getApi('sendCode'), {
  592. 'mobile':_phoneNum.text
  593. }, (response, hasError) {
  594. if(!hasError){
  595. }
  596. }, (error) {
  597. showToast('发送失败');
  598. countdown = 2;
  599. });
  600. setState(() {
  601. setState(() {
  602. verificationCodeText = '$countdown s';
  603. countdown--;
  604. });
  605. });
  606. _timer = Timer.periodic(Duration(seconds: 1), (timer) {
  607. if(countdown==0){
  608. timer.cancel();
  609. setState(() {
  610. countdown = 60;
  611. verificationCodeText = '发送验证码';
  612. });
  613. return;
  614. }
  615. setState(() {
  616. verificationCodeText = '$countdown s';
  617. countdown--;
  618. });
  619. });
  620. }
  621. void verificationCode() {
  622. MyDio().post(MyApis.getApi('verifyCode'), {
  623. 'mobile':_phoneNum.text,
  624. 'code':int.parse(_verificationCode.text),
  625. }, (response, hasError) {
  626. if(!hasError){
  627. uploadAvatar();
  628. }
  629. }, (error) {
  630. showToast('验证码错误');
  631. return;
  632. });
  633. }
  634. }
  635. class PrivacyPolicyPage extends StatefulWidget {
  636. String type;
  637. PrivacyPolicyPage(this.type);
  638. @override
  639. _PrivacyPolicyPageState createState() => _PrivacyPolicyPageState();
  640. }
  641. class _PrivacyPolicyPageState extends State<PrivacyPolicyPage> {
  642. @override
  643. Widget build(BuildContext context) {
  644. return Scaffold(
  645. body: Column(
  646. children: [
  647. MyViews().myAppBar(widget.type, context, []),
  648. Expanded(
  649. child: SingleChildScrollView(
  650. child: Padding(
  651. padding: const EdgeInsets.all(8.0),
  652. child: Text(
  653. widget.type == '使用协议' ? serviceAgreement : privacyPolicy),
  654. ),
  655. ))
  656. ],
  657. ),
  658. );
  659. }
  660. }