registered_page.dart 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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. Positioned(
  148. child: GestureDetector(
  149. onTap: (){
  150. MyTools().toPage(context, LoginPage(), (then) {},
  151. noBack: true);
  152. },
  153. behavior: HitTestBehavior.translucent,
  154. child: Container(
  155. height: 30,
  156. width: 60,
  157. decoration: BoxDecoration(
  158. color: Colors.white,
  159. borderRadius: BorderRadius.circular(15),
  160. ),
  161. child: Text('去登录',style: TextStyle(color: MyColors.cFF4233,fontSize: 12),),
  162. alignment: Alignment.center,
  163. ),
  164. ),
  165. top: 67,
  166. right: 10,
  167. ),
  168. ],
  169. alignment: Alignment.topCenter,
  170. ),
  171. ),
  172. Container(
  173. padding: EdgeInsets.only(left: 47, right: 47, top: 26),
  174. child: Column(
  175. children: [
  176. // Container(
  177. // child: Text(
  178. // 'Hello Welcome !',
  179. // style: TextStyle(
  180. // color: MyColors.cFF4233, fontSize: 24),
  181. // ),
  182. // margin: EdgeInsets.only(bottom: 25),
  183. // ),
  184. Row(
  185. children: [
  186. Container(
  187. child: SvgPicture.asset(
  188. 'images/svg/手机.svg',
  189. height: 22,
  190. width: 22,
  191. ),
  192. height: 22,
  193. width: 22,
  194. ),
  195. Expanded(
  196. child: TextField(
  197. controller: _phoneNum,
  198. inputFormatters: [
  199. onlyInputNumberAndWorkFormatter(),
  200. LengthLimitingTextInputFormatter(11)
  201. ],
  202. cursorColor: MyColors.cFF4233,
  203. cursorWidth: 1.0,
  204. onTap: () {
  205. setState(() {
  206. focus = 0;
  207. });
  208. },
  209. decoration: InputDecoration(
  210. border: InputBorder.none,
  211. disabledBorder: InputBorder.none,
  212. enabledBorder: InputBorder.none,
  213. focusedBorder: InputBorder.none,
  214. isDense: true,
  215. hintText: '请输入手机号',
  216. hintStyle: TextStyle(
  217. color: MyColors.c999999, fontSize: 16),
  218. contentPadding: const EdgeInsets.fromLTRB(
  219. 14, 4.5, 8, 4.5),
  220. ),
  221. maxLines: 1,
  222. style: TextStyle(
  223. color: MyColors.c333333,
  224. fontSize: 16,
  225. height: 1.3,
  226. letterSpacing: 0.2),
  227. keyboardType: TextInputType.number,
  228. onChanged: (t) {},
  229. ),
  230. )
  231. ],
  232. ),
  233. Container(
  234. height: 1,
  235. color:
  236. focus == 0 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  237. margin: EdgeInsets.only(top: 8, bottom: 39),
  238. ),
  239. Row(
  240. children: [
  241. Container(
  242. child: SvgPicture.asset(
  243. 'images/svg/昵称.svg',
  244. height: 22,
  245. width: 22,
  246. ),
  247. height: 22,
  248. width: 22,
  249. ),
  250. Expanded(
  251. child: TextField(
  252. inputFormatters: [
  253. LengthLimitingTextInputFormatter(12)
  254. ],
  255. controller: _nickname,
  256. cursorColor: MyColors.cFF4233,
  257. cursorWidth: 1.0,
  258. onTap: () {
  259. setState(() {
  260. focus = 2;
  261. });
  262. },
  263. decoration: InputDecoration(
  264. border: InputBorder.none,
  265. disabledBorder: InputBorder.none,
  266. enabledBorder: InputBorder.none,
  267. focusedBorder: InputBorder.none,
  268. hintText: '请输入昵称',
  269. hintStyle: TextStyle(
  270. color: MyColors.c999999, fontSize: 16),
  271. isDense: true,
  272. contentPadding: const EdgeInsets.fromLTRB(
  273. 14, 4.5, 8, 4.5)),
  274. maxLines: 1,
  275. style: TextStyle(
  276. color: MyColors.c333333,
  277. fontSize: 16,
  278. height: 1.3,
  279. letterSpacing: 0.2),
  280. keyboardType: TextInputType.text,
  281. onChanged: (t) {},
  282. ),
  283. ),
  284. ],
  285. ),
  286. Container(
  287. height: 1,
  288. color:
  289. focus == 2 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  290. margin: EdgeInsets.only(top: 8, bottom: 39),
  291. ),
  292. Row(
  293. children: [
  294. Container(
  295. child: SvgPicture.asset(
  296. 'images/svg/验证码.svg',
  297. height: 22,
  298. width: 22,
  299. ),
  300. height: 22,
  301. width: 22,
  302. ),
  303. Expanded(
  304. child: TextField(
  305. controller: _verificationCode,
  306. cursorColor: MyColors.cFF4233,
  307. cursorWidth: 1.0,
  308. inputFormatters: [
  309. onlyInputNumberAndWorkFormatter(),
  310. LengthLimitingTextInputFormatter(6)
  311. ],
  312. onTap: () {
  313. setState(() {
  314. focus = 1;
  315. });
  316. },
  317. decoration: InputDecoration(
  318. border: InputBorder.none,
  319. disabledBorder: InputBorder.none,
  320. enabledBorder: InputBorder.none,
  321. focusedBorder: InputBorder.none,
  322. hintText: '请输入验证码',
  323. hintStyle: TextStyle(
  324. color: MyColors.c999999, fontSize: 16),
  325. isDense: true,
  326. contentPadding: const EdgeInsets.fromLTRB(
  327. 14, 4.5, 8, 4.5)),
  328. maxLines: 1,
  329. style: TextStyle(
  330. color: MyColors.c333333,
  331. fontSize: 16,
  332. height: 1.3,
  333. letterSpacing: 0.2),
  334. keyboardType: TextInputType.number,
  335. onChanged: (t) {},
  336. ),
  337. ),
  338. GestureDetector(
  339. onTap: () {
  340. if (verificationCodeText != '发送验证码') {
  341. showToast('验证码发送中');
  342. return;
  343. }
  344. sendTheVerificationCode();
  345. },
  346. behavior: HitTestBehavior.translucent,
  347. child: Container(
  348. decoration: BoxDecoration(
  349. color: MyColors.c19FF4233,
  350. borderRadius:
  351. BorderRadius.all(Radius.circular(4))),
  352. child: Text(
  353. verificationCodeText,
  354. style: TextStyle(
  355. color: MyColors.cFF4233, fontSize: 14),
  356. ),
  357. alignment: Alignment.center,
  358. height: 34,
  359. width: 90,
  360. ),
  361. )
  362. ],
  363. ),
  364. Container(
  365. height: 1,
  366. color:
  367. focus == 1 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  368. margin: EdgeInsets.only(top: 8, bottom: 39),
  369. ),
  370. Row(
  371. children: [
  372. Container(
  373. child: SvgPicture.asset(
  374. 'images/svg/密码.svg',
  375. height: 22,
  376. width: 22,
  377. ),
  378. height: 22,
  379. width: 22,
  380. ),
  381. Expanded(
  382. child: TextField(
  383. controller: _pw,
  384. inputFormatters: [
  385. onlyInputNumberAndWorkFormatter(),
  386. LengthLimitingTextInputFormatter(8)
  387. ],
  388. cursorColor: MyColors.cFF4233,
  389. cursorWidth: 1.0,
  390. onTap: () {
  391. setState(() {
  392. focus = 3;
  393. });
  394. },
  395. decoration: InputDecoration(
  396. border: InputBorder.none,
  397. disabledBorder: InputBorder.none,
  398. enabledBorder: InputBorder.none,
  399. focusedBorder: InputBorder.none,
  400. hintText: '请输入密码(6到8位)',
  401. hintStyle: TextStyle(
  402. color: MyColors.c999999, fontSize: 16),
  403. isDense: true,
  404. contentPadding: const EdgeInsets.fromLTRB(
  405. 14, 4.5, 8, 4.5)),
  406. maxLines: 1,
  407. style: TextStyle(
  408. color: MyColors.c333333,
  409. fontSize: 16,
  410. height: 1.3,
  411. letterSpacing: 0.2),
  412. keyboardType: TextInputType.visiblePassword,
  413. obscureText: !showPW,
  414. onChanged: (t) {},
  415. ),
  416. ),
  417. GestureDetector(
  418. onTap: () {
  419. setState(() {
  420. showPW = !showPW;
  421. });
  422. },
  423. behavior: HitTestBehavior.translucent,
  424. child: Container(
  425. height: 30,
  426. width: 30,
  427. padding: EdgeInsets.all(4),
  428. child: SvgPicture.asset(showPW
  429. ? 'images/svg/不显示.svg'
  430. : 'images/svg/显示.svg'))),
  431. ],
  432. ),
  433. Container(
  434. height: 1,
  435. color:
  436. focus == 3 ? MyColors.cFF4233 : MyColors.cD7D7D7,
  437. margin: EdgeInsets.only(top: 8, bottom: 20),
  438. ),
  439. Row(
  440. children: [
  441. Checkbox(
  442. value: haveRead,
  443. onChanged: (v) {
  444. setState(() {
  445. haveRead = v;
  446. });
  447. },
  448. activeColor: MyColors.cFF4233,
  449. ),
  450. RichText(
  451. text: TextSpan(
  452. text: '我已阅读并同意',
  453. style: TextStyle(
  454. color: MyColors.c999999, fontSize: 12),
  455. children: [
  456. TextSpan(
  457. text: '《使用协议》',
  458. style: TextStyle(
  459. color: MyColors.cFF4233,
  460. fontSize: 12),
  461. recognizer: TapGestureRecognizer()
  462. ..onTap = () {
  463. MyTools().toPage(
  464. context,
  465. PrivacyPolicyPage('使用协议'),
  466. (then) {});
  467. }),
  468. TextSpan(
  469. text: '和',
  470. style: TextStyle(
  471. color: MyColors.c999999,
  472. fontSize: 12),
  473. ),
  474. TextSpan(
  475. text: '《隐私政策》',
  476. style: TextStyle(
  477. color: MyColors.cFF4233,
  478. fontSize: 12),
  479. recognizer: TapGestureRecognizer()
  480. ..onTap = () {
  481. MyTools().toPage(
  482. context,
  483. PrivacyPolicyPage('隐私政策'),
  484. (then) {});
  485. }),
  486. ]),
  487. ),
  488. ],
  489. mainAxisAlignment: MainAxisAlignment.end,
  490. ),
  491. GestureDetector(
  492. onTap: () {
  493. if (_phoneNum.text.isEmpty ||
  494. _phoneNum.text.length != 11) {
  495. showToast('请填写正确的手机号');
  496. return;
  497. }
  498. if (_pw.text.isEmpty || _pw.text.length < 6) {
  499. showToast('请填写正确的密码(由数字和字母组合的至少6位的组合)');
  500. return;
  501. }
  502. if (_nickname.text.isEmpty) {
  503. showToast('请填写昵称');
  504. return;
  505. }
  506. if (_verificationCode.text.isEmpty) {
  507. showToast('请填写验证码');
  508. return;
  509. }
  510. if (_image == null) {
  511. showToast('请设置头像');
  512. return;
  513. }
  514. if (!haveRead) {
  515. showToast('请阅读并同意《隐私政策》');
  516. return;
  517. }
  518. verificationCode();
  519. },
  520. behavior: HitTestBehavior.translucent,
  521. child: Container(
  522. margin: EdgeInsets.only(top: 20),
  523. decoration: BoxDecoration(
  524. borderRadius: BorderRadius.all(
  525. Radius.circular(20),
  526. ),
  527. gradient: LinearGradient(
  528. colors: MyColors.lg,
  529. ),
  530. ),
  531. height: 44,
  532. child: Text(
  533. '注 册',
  534. style:
  535. TextStyle(color: Colors.white, fontSize: 17),
  536. ),
  537. alignment: Alignment.center,
  538. padding: EdgeInsets.only(bottom: 2),
  539. ),
  540. ),
  541. // Container(
  542. // margin: EdgeInsets.only(top: 20),
  543. // alignment: Alignment.centerRight,
  544. // child: GestureDetector(
  545. // onTap: () {
  546. // MyTools().toPage(context, LoginPage(), (then) {},
  547. // noBack: true);
  548. // },
  549. // behavior: HitTestBehavior.translucent,
  550. // child: Container(
  551. // child: Text(
  552. // '已有账号,去登录',
  553. // style: TextStyle(
  554. // color: MyColors.cFF4233, fontSize: 13),
  555. // ),
  556. // padding: EdgeInsets.all(8),
  557. // ),
  558. // ),
  559. // ),
  560. ],
  561. crossAxisAlignment: CrossAxisAlignment.start,
  562. ),
  563. ),
  564. ],
  565. ),
  566. ],
  567. ),
  568. ),
  569. ),
  570. );
  571. }
  572. void uploadAvatar() {
  573. upload(_image, (r, hasError) {
  574. if (!hasError) {
  575. UploadImageBeanEntity data =
  576. UploadImageBeanEntity().fromJson(json.decode(r.data.toString()));
  577. registered(data);
  578. }
  579. }, (error) {});
  580. }
  581. void registered(UploadImageBeanEntity data) {
  582. registeredAccountNumber({
  583. 'mobile': _phoneNum.text,
  584. 'name': _nickname.text,
  585. 'password': MyTools.base64Encode(_pw.text),
  586. 'picture': data.data[0].path,
  587. }, (re, hasError) {
  588. if (!hasError) {
  589. // showToast('注册成功');
  590. // MyTools().toPage(
  591. // context, LoginPage(), (then) {},
  592. // noBack: true);
  593. _timer.cancel();
  594. loginAccount({
  595. 'user': _phoneNum.text,
  596. 'password': MyTools.base64Encode(_pw.text),
  597. 'version': MyCookie().packageInfo.version,
  598. 'phone': Platform.isAndroid ? 'Android' : 'IOS'
  599. }, (r, hE) {
  600. if (!hE) {
  601. LoginInformationBeanEntity entity = LoginInformationBeanEntity()
  602. .fromJson(json.decode(r.data.toString()));
  603. MyCookie().saveLoginInformationBeanEntity(entity);
  604. MyDio().initDio();
  605. MyTools().toPage(context, RootPage(), (then) {}, noBack: true);
  606. }
  607. }, (e) {});
  608. }
  609. }, (error) {});
  610. }
  611. int countdown = 60;
  612. void sendTheVerificationCode() {
  613. if (_phoneNum.text.isEmpty || _phoneNum.text.length != 11) {
  614. showToast('请输入正确的手机号');
  615. return;
  616. }
  617. MyDio().post(MyApis.getApi('sendCode'), {'mobile': _phoneNum.text},
  618. (response, hasError) {
  619. if (!hasError) {}
  620. }, (error) {
  621. showToast('发送失败');
  622. countdown = 2;
  623. });
  624. setState(() {
  625. setState(() {
  626. verificationCodeText = '$countdown s';
  627. countdown--;
  628. });
  629. });
  630. _timer = Timer.periodic(Duration(seconds: 1), (timer) {
  631. if (countdown == 0) {
  632. timer.cancel();
  633. setState(() {
  634. countdown = 60;
  635. verificationCodeText = '发送验证码';
  636. });
  637. return;
  638. }
  639. setState(() {
  640. verificationCodeText = '$countdown s';
  641. countdown--;
  642. });
  643. });
  644. }
  645. void verificationCode() {
  646. MyDio().post(MyApis.getApi('verifyCode'), {
  647. 'mobile': _phoneNum.text,
  648. 'code': int.parse(_verificationCode.text),
  649. }, (response, hasError) {
  650. if (!hasError) {
  651. uploadAvatar();
  652. }
  653. }, (error) {
  654. showToast('验证码错误');
  655. return;
  656. });
  657. }
  658. }
  659. class PrivacyPolicyPage extends StatefulWidget {
  660. String type;
  661. PrivacyPolicyPage(this.type);
  662. @override
  663. _PrivacyPolicyPageState createState() => _PrivacyPolicyPageState();
  664. }
  665. class _PrivacyPolicyPageState extends State<PrivacyPolicyPage> {
  666. @override
  667. Widget build(BuildContext context) {
  668. return Scaffold(
  669. body: Column(
  670. children: [
  671. MyViews().myAppBar(widget.type, context, []),
  672. Expanded(
  673. child: SingleChildScrollView(
  674. child: Padding(
  675. padding: const EdgeInsets.all(8.0),
  676. child: Text(
  677. widget.type == '使用协议' ? serviceAgreement : privacyPolicy),
  678. ),
  679. ))
  680. ],
  681. ),
  682. );
  683. }
  684. }