Commit 39e064868d2afb002d3e50ff011757fdfa078993
1 parent
6f836681
feat:获取验证码逻辑处理
Showing
4 changed files
with
156 additions
and
115 deletions
lib/common/request/dao/user_dao.dart
| @@ -16,4 +16,11 @@ class UserDao { | @@ -16,4 +16,11 @@ class UserDao { | ||
| 16 | } | 16 | } |
| 17 | return data; | 17 | return data; |
| 18 | } | 18 | } |
| 19 | + | ||
| 20 | + static Future sendCode(phoneNumber,{smsType ='login'}) async { | ||
| 21 | + final params = {'phoneNum':phoneNumber,'smsType':smsType}; | ||
| 22 | + await requestClient.post( | ||
| 23 | + Apis.sendSmsCode,data: params | ||
| 24 | + ); | ||
| 25 | + } | ||
| 19 | } | 26 | } |
lib/pages/login/loginpage/bloc/login_bloc.dart
| 1 | +import 'package:common_utils/common_utils.dart'; | ||
| 1 | import 'package:flutter/cupertino.dart'; | 2 | import 'package:flutter/cupertino.dart'; |
| 2 | import 'package:flutter_bloc/flutter_bloc.dart'; | 3 | import 'package:flutter_bloc/flutter_bloc.dart'; |
| 3 | import 'package:flutter_easyloading/flutter_easyloading.dart'; | 4 | import 'package:flutter_easyloading/flutter_easyloading.dart'; |
| @@ -82,7 +83,23 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> { | @@ -82,7 +83,23 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> { | ||
| 82 | } | 83 | } |
| 83 | 84 | ||
| 84 | ///请求验证码 | 85 | ///请求验证码 |
| 85 | - void _requestSmsCodeApi(RequestSmsCodeEvent event, Emitter<LoginState> emitter) async {} | 86 | + void _requestSmsCodeApi(RequestSmsCodeEvent event, Emitter<LoginState> emitter) async { |
| 87 | + final phoneNumber = phoneNumController.text; | ||
| 88 | + if (!RegexUtil.isMobileExact(phoneNumber)) { | ||
| 89 | + EasyLoading.showToast('请检查手机号'); | ||
| 90 | + return; | ||
| 91 | + } | ||
| 92 | + try { | ||
| 93 | + await loading(() async { | ||
| 94 | + await UserDao.sendCode(phoneNumber); | ||
| 95 | + }); | ||
| 96 | + emitter(SmsCodeRequestState()); | ||
| 97 | + } catch (e) { | ||
| 98 | + if (e is ApiException) { | ||
| 99 | + EasyLoading.showToast(e.message??'请检查网络连接'); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + } | ||
| 86 | 103 | ||
| 87 | ///切换登陆方式 | 104 | ///切换登陆方式 |
| 88 | void _changeLoginType(ChangeLoginTypeEvent event, Emitter<LoginState> emitter) async { | 105 | void _changeLoginType(ChangeLoginTypeEvent event, Emitter<LoginState> emitter) async { |
lib/pages/login/loginpage/login_page.dart
| @@ -41,116 +41,114 @@ class _LoginPageView extends StatelessWidget { | @@ -41,116 +41,114 @@ class _LoginPageView extends StatelessWidget { | ||
| 41 | final bloc = BlocProvider.of<LoginBloc>(context); | 41 | final bloc = BlocProvider.of<LoginBloc>(context); |
| 42 | return Scaffold( | 42 | return Scaffold( |
| 43 | body: SafeArea( | 43 | body: SafeArea( |
| 44 | - child: ListView( | ||
| 45 | - children: [ | ||
| 46 | - Container( | ||
| 47 | - padding: EdgeInsets.only(top: 25.h), | ||
| 48 | - child: Stack( | ||
| 49 | - children: [ | ||
| 50 | - Positioned( | ||
| 51 | - right: 29.w, | ||
| 52 | - child: GestureDetector( | ||
| 53 | - onTap: () => bloc.add(ChangeLoginTypeEvent()), | 44 | + child: SingleChildScrollView( |
| 45 | + child: Container( | ||
| 46 | + padding: EdgeInsets.only(top: 25.h), | ||
| 47 | + child: Stack( | ||
| 48 | + children: [ | ||
| 49 | + Positioned( | ||
| 50 | + right: 29.w, | ||
| 51 | + child: GestureDetector( | ||
| 52 | + onTap: () => bloc.add(ChangeLoginTypeEvent()), | ||
| 53 | + child: Container( | ||
| 54 | + decoration: BoxDecoration( | ||
| 55 | + image: DecorationImage(image: AssetImage('login_logo'.assetPng), fit: BoxFit.fill), | ||
| 56 | + ), | ||
| 57 | + padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 5.h), | ||
| 58 | + child: Text( | ||
| 59 | + bloc.isSmsLoginType ? '密码登陆' : '验证码密码', | ||
| 60 | + style: TextStyle(fontSize: 16.sp), | ||
| 61 | + ), | ||
| 62 | + ), | ||
| 63 | + )), | ||
| 64 | + Center( | ||
| 65 | + child: Column( | ||
| 66 | + children: [ | ||
| 67 | + Image.asset( | ||
| 68 | + 'wow_logo'.assetPng, | ||
| 69 | + height: 81.h, | ||
| 70 | + width: 131.w, | ||
| 71 | + ), | ||
| 72 | + Offstage( | ||
| 73 | + offstage: !bloc.isSmsLoginType, | ||
| 74 | + child: _buildSmsViewWidget(), | ||
| 75 | + ), | ||
| 76 | + Offstage( | ||
| 77 | + offstage: bloc.isSmsLoginType, | ||
| 78 | + child: _buildPwdViewWidget(), | ||
| 79 | + ), | ||
| 80 | + Row( | ||
| 81 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 82 | + children: [ | ||
| 83 | + GestureDetector( | ||
| 84 | + onTap: () => bloc.add(AgreementChangeEvent()), | ||
| 85 | + child: Icon(bloc.agreement ? Icons.check_circle_outlined : Icons.circle_outlined, | ||
| 86 | + color: bloc.agreement ? Colors.green : Colors.black), | ||
| 87 | + ), | ||
| 88 | + 6.horizontalSpace, | ||
| 89 | + RichText( | ||
| 90 | + text: TextSpan(children: [ | ||
| 91 | + TextSpan( | ||
| 92 | + text: '我已阅读并同意', | ||
| 93 | + style: TextStyle( | ||
| 94 | + fontSize: 12.sp, | ||
| 95 | + color: const Color(0xFF333333), | ||
| 96 | + )), | ||
| 97 | + TextSpan( | ||
| 98 | + text: '《用户隐私协议》', | ||
| 99 | + style: TextStyle( | ||
| 100 | + fontSize: 12.sp, | ||
| 101 | + color: const Color(0xFF333333), | ||
| 102 | + ), | ||
| 103 | + recognizer: TapGestureRecognizer() | ||
| 104 | + ..onTap = () { | ||
| 105 | + Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | ||
| 106 | + 'urlStr': 'https://www.zhihu.com', | ||
| 107 | + 'webViewTitle': '用户隐私协议' | ||
| 108 | + }); | ||
| 109 | + }), | ||
| 110 | + TextSpan( | ||
| 111 | + text: ',', style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333))), | ||
| 112 | + TextSpan( | ||
| 113 | + text: '《儿童隐私政策》', | ||
| 114 | + style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333)), | ||
| 115 | + recognizer: TapGestureRecognizer() | ||
| 116 | + ..onTap = () { | ||
| 117 | + Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | ||
| 118 | + 'urlStr': 'https://www.zhihu.com', | ||
| 119 | + 'webViewTitle': '儿童隐私协议' | ||
| 120 | + }); | ||
| 121 | + }) | ||
| 122 | + ]), | ||
| 123 | + ) | ||
| 124 | + ], | ||
| 125 | + ), | ||
| 126 | + GestureDetector( | ||
| 127 | + onTap: () { | ||
| 128 | + if (bloc.canLogin) { | ||
| 129 | + bloc.add(RequestLoginEvent()); | ||
| 130 | + } | ||
| 131 | + }, | ||
| 54 | child: Container( | 132 | child: Container( |
| 55 | decoration: BoxDecoration( | 133 | decoration: BoxDecoration( |
| 56 | - image: DecorationImage(image: AssetImage('login_logo'.assetPng), fit: BoxFit.fill), | 134 | + image: DecorationImage( |
| 135 | + image: AssetImage( | ||
| 136 | + bloc.canLogin ? 'login_enter'.assetPng : 'login_enter_dis'.assetPng), | ||
| 137 | + fit: BoxFit.fill), | ||
| 57 | ), | 138 | ), |
| 58 | - padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 5.h), | 139 | + padding: EdgeInsets.symmetric(horizontal: 28.w, vertical: 14.h), |
| 59 | child: Text( | 140 | child: Text( |
| 60 | - bloc.isSmsLoginType ? '密码登陆' : '验证码密码', | 141 | + '登录', |
| 61 | style: TextStyle(fontSize: 16.sp), | 142 | style: TextStyle(fontSize: 16.sp), |
| 62 | ), | 143 | ), |
| 63 | ), | 144 | ), |
| 64 | - )), | ||
| 65 | - Center( | ||
| 66 | - child: Column( | ||
| 67 | - children: [ | ||
| 68 | - Image.asset( | ||
| 69 | - 'wow_logo'.assetPng, | ||
| 70 | - height: 81.h, | ||
| 71 | - width: 131.w, | ||
| 72 | - ), | ||
| 73 | - Offstage( | ||
| 74 | - offstage: !bloc.isSmsLoginType, | ||
| 75 | - child: _buildSmsViewWidget(), | ||
| 76 | - ), | ||
| 77 | - Offstage( | ||
| 78 | - offstage: bloc.isSmsLoginType, | ||
| 79 | - child: _buildPwdViewWidget(), | ||
| 80 | - ), | ||
| 81 | - Row( | ||
| 82 | - mainAxisAlignment: MainAxisAlignment.center, | ||
| 83 | - children: [ | ||
| 84 | - GestureDetector( | ||
| 85 | - onTap: () => bloc.add(AgreementChangeEvent()), | ||
| 86 | - child: Icon(bloc.agreement ? Icons.check_circle_outlined : Icons.circle_outlined, | ||
| 87 | - color: bloc.agreement ? Colors.green : Colors.black), | ||
| 88 | - ), | ||
| 89 | - 6.horizontalSpace, | ||
| 90 | - RichText( | ||
| 91 | - text: TextSpan(children: [ | ||
| 92 | - TextSpan( | ||
| 93 | - text: '我已阅读并同意', | ||
| 94 | - style: TextStyle( | ||
| 95 | - fontSize: 12.sp, | ||
| 96 | - color: const Color(0xFF333333), | ||
| 97 | - )), | ||
| 98 | - TextSpan( | ||
| 99 | - text: '《用户隐私协议》', | ||
| 100 | - style: TextStyle( | ||
| 101 | - fontSize: 12.sp, | ||
| 102 | - color: const Color(0xFF333333), | ||
| 103 | - ), | ||
| 104 | - recognizer: TapGestureRecognizer() | ||
| 105 | - ..onTap = () { | ||
| 106 | - Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | ||
| 107 | - 'urlStr': 'https://www.zhihu.com', | ||
| 108 | - 'webViewTitle': '用户隐私协议' | ||
| 109 | - }); | ||
| 110 | - }), | ||
| 111 | - TextSpan( | ||
| 112 | - text: ',', style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333))), | ||
| 113 | - TextSpan( | ||
| 114 | - text: '《儿童隐私政策》', | ||
| 115 | - style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333)), | ||
| 116 | - recognizer: TapGestureRecognizer() | ||
| 117 | - ..onTap = () { | ||
| 118 | - Navigator.of(context).pushNamed(AppRouteName.webView, arguments: { | ||
| 119 | - 'urlStr': 'https://www.zhihu.com', | ||
| 120 | - 'webViewTitle': '儿童隐私协议' | ||
| 121 | - }); | ||
| 122 | - }) | ||
| 123 | - ]), | ||
| 124 | - ) | ||
| 125 | - ], | ||
| 126 | - ), | ||
| 127 | - GestureDetector( | ||
| 128 | - onTap: () { | ||
| 129 | - if (bloc.canLogin) { | ||
| 130 | - bloc.add(RequestLoginEvent()); | ||
| 131 | - } | ||
| 132 | - }, | ||
| 133 | - child: Container( | ||
| 134 | - decoration: BoxDecoration( | ||
| 135 | - image: DecorationImage( | ||
| 136 | - image: AssetImage( | ||
| 137 | - bloc.canLogin ? 'login_enter'.assetPng : 'login_enter_dis'.assetPng), | ||
| 138 | - fit: BoxFit.fill), | ||
| 139 | - ), | ||
| 140 | - padding: EdgeInsets.symmetric(horizontal: 28.w, vertical: 14.h), | ||
| 141 | - child: Text( | ||
| 142 | - '登录', | ||
| 143 | - style: TextStyle(fontSize: 16.sp), | ||
| 144 | - ), | ||
| 145 | - ), | ||
| 146 | - ) | ||
| 147 | - ], | ||
| 148 | - ), | ||
| 149 | - ) | ||
| 150 | - ], | ||
| 151 | - ), | ||
| 152 | - ) | ||
| 153 | - ], | 145 | + ) |
| 146 | + ], | ||
| 147 | + ), | ||
| 148 | + ) | ||
| 149 | + ], | ||
| 150 | + ), | ||
| 151 | + ), | ||
| 154 | ), | 152 | ), |
| 155 | ), | 153 | ), |
| 156 | ); | 154 | ); |
| @@ -194,7 +192,10 @@ class _LoginPageView extends StatelessWidget { | @@ -194,7 +192,10 @@ class _LoginPageView extends StatelessWidget { | ||
| 194 | }, | 192 | }, |
| 195 | controller: bloc.checkNumController, | 193 | controller: bloc.checkNumController, |
| 196 | )), | 194 | )), |
| 197 | - TimerWidget(canSendSms: bloc.canSendSms) | 195 | + TimerWidget( |
| 196 | + canSendSms: bloc.canSendSms, | ||
| 197 | + sendSmsEvent: () => bloc.add(RequestSmsCodeEvent()), | ||
| 198 | + ) | ||
| 198 | ], | 199 | ], |
| 199 | ) | 200 | ) |
| 200 | ], | 201 | ], |
lib/pages/login/loginpage/time_widget.dart
| @@ -5,17 +5,22 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; | @@ -5,17 +5,22 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; | ||
| 5 | import 'package:wow_english/common/blocs/timerbloc/timer_bloc.dart'; | 5 | import 'package:wow_english/common/blocs/timerbloc/timer_bloc.dart'; |
| 6 | import 'package:wow_english/common/extension/string_extension.dart'; | 6 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 7 | import 'package:wow_english/common/widgets/timer_ticker.dart'; | 7 | import 'package:wow_english/common/widgets/timer_ticker.dart'; |
| 8 | +import 'package:wow_english/pages/login/loginpage/bloc/login_bloc.dart'; | ||
| 8 | 9 | ||
| 9 | class TimerWidget extends StatelessWidget { | 10 | class TimerWidget extends StatelessWidget { |
| 10 | - const TimerWidget({super.key, required this.canSendSms}); | 11 | + const TimerWidget({super.key, required this.canSendSms,this.sendSmsEvent}); |
| 11 | 12 | ||
| 12 | final bool canSendSms; | 13 | final bool canSendSms; |
| 14 | + final Function()? sendSmsEvent; | ||
| 13 | 15 | ||
| 14 | @override | 16 | @override |
| 15 | Widget build(BuildContext context) { | 17 | Widget build(BuildContext context) { |
| 16 | return BlocProvider( | 18 | return BlocProvider( |
| 17 | create: (_) => TimerBloc(ticker: const TimerTicker()), | 19 | create: (_) => TimerBloc(ticker: const TimerTicker()), |
| 18 | - child: TimerWidgetView(canSendSms: canSendSms,), | 20 | + child: TimerWidgetView( |
| 21 | + canSendSms: canSendSms, | ||
| 22 | + sendSmsEvent: sendSmsEvent, | ||
| 23 | + ), | ||
| 19 | ); | 24 | ); |
| 20 | } | 25 | } |
| 21 | } | 26 | } |
| @@ -27,13 +32,24 @@ class TimerWidgetView extends StatelessWidget { | @@ -27,13 +32,24 @@ class TimerWidgetView extends StatelessWidget { | ||
| 27 | 32 | ||
| 28 | @override | 33 | @override |
| 29 | Widget build(BuildContext context) { | 34 | Widget build(BuildContext context) { |
| 30 | - return BlocListener<TimerBloc,TimerState>( | ||
| 31 | - listener: (context, s) { | ||
| 32 | - if (s is FinishedState) { | ||
| 33 | - ///重置计时器 | ||
| 34 | - context.read<TimerBloc>().add(ResetEvent()); | ||
| 35 | - } | ||
| 36 | - }, | 35 | + return MultiBlocListener( |
| 36 | + listeners: [ | ||
| 37 | + BlocListener<TimerBloc,TimerState>( | ||
| 38 | + listener: (context, s) { | ||
| 39 | + if (s is FinishedState) { | ||
| 40 | + ///重置计时器 | ||
| 41 | + context.read<TimerBloc>().add(ResetEvent()); | ||
| 42 | + } | ||
| 43 | + }), | ||
| 44 | + BlocListener<LoginBloc,LoginState>( | ||
| 45 | + listener: (context, s) { | ||
| 46 | + if (s is SmsCodeRequestState) { | ||
| 47 | + final bloc = BlocProvider.of<TimerBloc>(context); | ||
| 48 | + ///开始倒计时 | ||
| 49 | + bloc.add(StartEvent(duration: bloc.state.duration)); | ||
| 50 | + } | ||
| 51 | + }), | ||
| 52 | + ], | ||
| 37 | child: _buildCountdownWidget(), | 53 | child: _buildCountdownWidget(), |
| 38 | ); | 54 | ); |
| 39 | } | 55 | } |
| @@ -45,7 +61,7 @@ class TimerWidgetView extends StatelessWidget { | @@ -45,7 +61,7 @@ class TimerWidgetView extends StatelessWidget { | ||
| 45 | return GestureDetector( | 61 | return GestureDetector( |
| 46 | onTap: () { | 62 | onTap: () { |
| 47 | if (canSendSms && !bloc.isCountTimer ) { | 63 | if (canSendSms && !bloc.isCountTimer ) { |
| 48 | - bloc.add(StartEvent(duration: state.duration)); | 64 | + sendSmsEvent?.call(); |
| 49 | } | 65 | } |
| 50 | }, | 66 | }, |
| 51 | child: Container( | 67 | child: Container( |