Commit bfb40cd0bdeb57879c4cc8471a8d303b36b43e7f

Authored by liangchengyou
1 parent 1d5315dd

feat:忘记密码获取验证码

assets/images/steven_bride.png 0 → 100644

142 KB

lib/common/pages/wow_web_page.dart 0 → 100644
  1 +import 'dart:io';
  2 +
  3 +import 'package:flutter/material.dart';
  4 +import 'package:flutter/services.dart';
  5 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  6 +import 'package:limiting_direction_csx/limiting_direction_csx.dart';
  7 +import 'package:webview_flutter/webview_flutter.dart';
  8 +import 'package:wow_english/common/widgets/we_app_bar.dart';
  9 +
  10 +class WowWebViewPage extends StatefulWidget {
  11 + const WowWebViewPage({super.key, required this.urlStr, required this.webViewTitle});
  12 +
  13 + final String urlStr;
  14 + final String webViewTitle;
  15 +
  16 + @override
  17 + State<StatefulWidget> createState() {
  18 + return _WowWebViewPageState();
  19 + }
  20 +}
  21 +
  22 +class _WowWebViewPageState extends State<WowWebViewPage> {
  23 +
  24 + late final WebViewController _controller;
  25 +
  26 + @override
  27 + void initState() {
  28 + super.initState();
  29 +
  30 + if (Platform.isIOS) {
  31 + LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.PortraitUpsideDown);
  32 + } else {
  33 + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  34 + }
  35 +
  36 + final WebViewController controller =WebViewController()
  37 + ..setJavaScriptMode(JavaScriptMode.unrestricted)
  38 + ..setBackgroundColor(const Color(0x00000000))
  39 + ..setNavigationDelegate(
  40 + NavigationDelegate(
  41 + onProgress: (int progress) {
  42 + // Update loading bar.
  43 + },
  44 + onPageStarted: (String url) {
  45 + EasyLoading.show();
  46 + },
  47 + onPageFinished: (String url) {
  48 + EasyLoading.dismiss();
  49 + },
  50 + onWebResourceError: (WebResourceError error) {
  51 + EasyLoading.showError(error.description);
  52 + },
  53 + onNavigationRequest: (NavigationRequest request) {
  54 + return NavigationDecision.navigate;
  55 + },
  56 + ),
  57 + )
  58 + ..loadRequest(Uri.parse(widget.urlStr));
  59 + _controller = controller;
  60 + }
  61 +
  62 + @override
  63 + Widget build(BuildContext context) {
  64 + return Scaffold(
  65 + backgroundColor: Colors.white,
  66 + appBar: WEAppBar(
  67 + titleText: widget.webViewTitle,
  68 + ),
  69 + body: WebViewWidget(controller: _controller,),
  70 + );
  71 + }
  72 +
  73 + @override
  74 + void deactivate() {
  75 + super.deactivate();
  76 + if (Platform.isIOS) {
  77 + LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.Landscape);
  78 + } else {
  79 + SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,DeviceOrientation.landscapeRight]);
  80 + }
  81 + }
  82 +}
0 83 \ No newline at end of file
... ...
lib/widgets/we_app_bar.dart renamed to lib/common/widgets/we_app_bar.dart
lib/login/forgetpwd/bloc/forget_pwd_home_bloc.dart
1   -import 'dart:async';
2   -
3   -import 'package:bloc/bloc.dart';
4   -import 'package:meta/meta.dart';
  1 +import 'package:flutter/cupertino.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
5 3  
6 4 part 'forget_pwd_home_event.dart';
7 5 part 'forget_pwd_home_state.dart';
8 6  
9 7 class ForgetPwdHomeBloc extends Bloc<ForgetPwdHomeEvent, ForgetPwdHomeState> {
  8 +
  9 + ///是否可以发送验证码
  10 + bool _canSendSms = false;
  11 + bool _canSetPwd = false;
  12 +
  13 + bool get canSendSms => _canSendSms;
  14 + bool get canSetPwd => _canSetPwd;
  15 +
  16 + final TextEditingController phoneNumController = TextEditingController();
  17 + final TextEditingController checkNumController = TextEditingController();
  18 +
10 19 ForgetPwdHomeBloc() : super(ForgetPwdHomeInitial()) {
11   - on<ForgetPwdHomeEvent>((event, emit) {
12   - // TODO: implement event handler
13   - });
  20 + on<PhoneNumChangeEvent>(_changePhoneNumber);
  21 + on<CheckCodeChangeEvent>(_changeCodeNumber);
  22 + on<SetPassWordEvent>(_setPassWord);
  23 + on<SendSmsCodeEvent>(_sendSmsCode);
  24 + }
  25 +
  26 + void _changePhoneNumber(PhoneNumChangeEvent event, Emitter<ForgetPwdHomeState> emitter) async {
  27 + if (phoneNumController.text.isNotEmpty) {
  28 + if (!_canSendSms) {
  29 + _canSendSms = true;
  30 + emitter(SendSmsCodeTypeChangeState());
  31 + emitter(SetPwdTypeChangeState());
  32 + }
  33 + } else {
  34 + if (_canSendSms) {
  35 + _canSendSms = false;
  36 + emitter(SendSmsCodeTypeChangeState());
  37 + emitter(SetPwdTypeChangeState());
  38 + }
  39 + }
  40 + }
  41 +
  42 + void _changeCodeNumber(CheckCodeChangeEvent event, Emitter<ForgetPwdHomeState> emitter) async {
  43 + if (checkNumController.text.isNotEmpty) {
  44 + if (!_canSetPwd) {
  45 + _canSetPwd = true;
  46 + emitter(SendSmsCodeTypeChangeState());
  47 + emitter(SetPwdTypeChangeState());
  48 + }
  49 + } else {
  50 + if (_canSetPwd) {
  51 + _canSetPwd = false;
  52 + emitter(SendSmsCodeTypeChangeState());
  53 + emitter(SetPwdTypeChangeState());
  54 + }
  55 + }
  56 + }
  57 +
  58 + void _setPassWord(SetPassWordEvent event,Emitter<ForgetPwdHomeState> emitter) async {
  59 +
  60 + }
  61 +
  62 + void _sendSmsCode(SendSmsCodeEvent event,Emitter<ForgetPwdHomeState> emitter) async {
  63 +
14 64 }
15 65 }
... ...
lib/login/forgetpwd/bloc/forget_pwd_home_event.dart
... ... @@ -2,3 +2,11 @@ part of &#39;forget_pwd_home_bloc.dart&#39;;
2 2  
3 3 @immutable
4 4 abstract class ForgetPwdHomeEvent {}
  5 +
  6 +class PhoneNumChangeEvent extends ForgetPwdHomeEvent {}
  7 +
  8 +class CheckCodeChangeEvent extends ForgetPwdHomeEvent {}
  9 +
  10 +class SetPassWordEvent extends ForgetPwdHomeEvent {}
  11 +
  12 +class SendSmsCodeEvent extends ForgetPwdHomeEvent {}
... ...
lib/login/forgetpwd/bloc/forget_pwd_home_state.dart
... ... @@ -4,3 +4,7 @@ part of &#39;forget_pwd_home_bloc.dart&#39;;
4 4 abstract class ForgetPwdHomeState {}
5 5  
6 6 class ForgetPwdHomeInitial extends ForgetPwdHomeState {}
  7 +
  8 +class SendSmsCodeTypeChangeState extends ForgetPwdHomeState {}
  9 +
  10 +class SetPwdTypeChangeState extends ForgetPwdHomeState {}
... ...
lib/login/forgetpwd/forget_password_home_page.dart
... ... @@ -2,6 +2,7 @@ import &#39;package:flutter/material.dart&#39;;
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
3 3 import 'package:flutter_screenutil/flutter_screenutil.dart';
4 4 import 'package:wow_english/common/extension/string_extension.dart';
  5 +import 'package:wow_english/common/widgets/textfield_customer_widget.dart';
5 6 import 'package:wow_english/login/forgetpwd/bloc/forget_pwd_home_bloc.dart';
6 7  
7 8 class ForgetPasswordHomePage extends StatelessWidget {
... ... @@ -25,7 +26,7 @@ class ForgetPasswordHomePage extends StatelessWidget {
25 26 child: ListView(
26 27 children: [
27 28 Padding(
28   - padding: EdgeInsets.symmetric(horizontal: 40.w),
  29 + padding: EdgeInsets.only(left: 49.w,right: 10.w),
29 30 child: Column(
30 31 children: [
31 32 34.verticalSpace,
... ... @@ -45,6 +46,122 @@ class ForgetPasswordHomePage extends StatelessWidget {
45 46 ),
46 47 )
47 48 ],
  49 + ),
  50 + Row(
  51 + crossAxisAlignment: CrossAxisAlignment.start,
  52 + children: [
  53 + Expanded(
  54 + child: Column(
  55 + children: [
  56 + 44.5.verticalSpace,
  57 + Row(
  58 + children: [
  59 + Image.asset(
  60 + 'phone'.assetPng,
  61 + height: 45.h,
  62 + width: 35.w,
  63 + ),
  64 + 15.horizontalSpace,
  65 + Expanded(
  66 + child: TextFieldCustomerWidget(
  67 + height: 50.h,
  68 + hitText: '请输入当前手机号',
  69 + textInputType: TextInputType.phone,
  70 + bgImageName: 'Input_layer_up',
  71 + onChangeValue: (String value) {
  72 + bloc.add(PhoneNumChangeEvent());
  73 + },
  74 + controller: bloc.phoneNumController,
  75 + )
  76 + )
  77 + ],
  78 + ),
  79 + 11.5.verticalSpace,
  80 + Row(
  81 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  82 + children: [
  83 + Image.asset(
  84 + 'lock'.assetPng,
  85 + height: 34.h,
  86 + width: 31.w,
  87 + ),
  88 + 18.5.horizontalSpace,
  89 + Expanded(
  90 + child: TextFieldCustomerWidget(
  91 + hitText: '请输入验证码',
  92 + bgImageName: 'Input_layer_down',
  93 + onChangeValue: (String value) {
  94 + bloc.add(CheckCodeChangeEvent());
  95 + },
  96 + textInputType: TextInputType.emailAddress,
  97 + controller: bloc.checkNumController,
  98 + )
  99 + ),
  100 + 16.5.horizontalSpace,
  101 + GestureDetector(
  102 + onTap: () {
  103 + if (bloc.canSendSms) {
  104 + bloc.add(SendSmsCodeEvent());
  105 + }
  106 + },
  107 + child: Container(
  108 + decoration: BoxDecoration(
  109 + image: DecorationImage(
  110 + image: AssetImage(
  111 + bloc.canSendSms?'securitycode'.assetPng:'securitycode_dis'.assetPng
  112 + ),
  113 + fit: BoxFit.fill
  114 + ),
  115 + ),
  116 + padding: const EdgeInsets.symmetric(horizontal:12.0,vertical: 15.0),
  117 + child: const Text(
  118 + '获取验证码',
  119 + style: TextStyle(
  120 + fontSize: 16,
  121 + color: Colors.white
  122 + ),
  123 + ),
  124 + ),
  125 + )
  126 + ],
  127 + )
  128 + ],
  129 + )
  130 + ),
  131 + 2.verticalSpace,
  132 + Image.asset(
  133 + 'steven_bride'.assetPng,
  134 + height: 173.h,
  135 + width: 157.w,
  136 + )
  137 + ],
  138 + ),
  139 + GestureDetector(
  140 + onTap: () {
  141 + if (bloc.canSetPwd) {
  142 + bloc.add(SetPassWordEvent());
  143 + }
  144 + },
  145 + child: Container(
  146 + decoration: BoxDecoration(
  147 + image: DecorationImage(
  148 + image: AssetImage(
  149 + bloc.canSetPwd?'login_enter'.assetPng:'login_enter_dis'.assetPng
  150 + ),
  151 + fit: BoxFit.fill
  152 + ),
  153 + ),
  154 + padding: const EdgeInsets.symmetric(
  155 + horizontal: 28.0,
  156 + vertical: 14.0
  157 + ),
  158 + child:const Text(
  159 + '确定',
  160 + style: TextStyle(
  161 + fontSize: 16
  162 + ),
  163 + ),
  164 + ),
48 165 )
49 166 ],
50 167 ),
... ...
lib/login/loginpage/bloc/login_bloc.dart
  1 +import 'dart:async';
  2 +
1 3 import 'package:flutter/cupertino.dart';
  4 +import 'package:flutter/foundation.dart';
2 5 import 'package:flutter_bloc/flutter_bloc.dart';
3 6  
4 7 part 'login_event.dart';
... ... @@ -16,11 +19,15 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
16 19 bool _canLogin = false;
17 20 ///是否可以发送验证码
18 21 bool _canSendSms = false;
  22 + ///正在发送验证码
  23 + bool _sendSmsIng = false;
19 24 ///是否阅读协议
20 25 bool _agreement = false;
21 26 ///登陆方式
22 27 LoginType _loginType = LoginType.sms;
23 28  
  29 + int _countDown = 0;
  30 +
24 31 final TextEditingController phoneNumController = TextEditingController();
25 32 final TextEditingController checkNumController = TextEditingController();
26 33  
... ... @@ -28,6 +35,8 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
28 35 bool get agreement => _agreement;
29 36 LoginType get loginType => _loginType;
30 37 bool get canSendSms => _canSendSms;
  38 + int get countDown => _countDown;
  39 + bool get sendSmsIng => _sendSmsIng;
31 40  
32 41 LoginBloc() : super(LoginInitial()) {
33 42 on<RequestLoginEvent>(_requestLoginApi);
... ... @@ -36,6 +45,8 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
36 45 on<AgreementChangeEvent>(_agreementTypeChange);
37 46 on<ForgetPasswordEvent>(_forgetPassword);
38 47 on<CheckFieldChangeEvent>(_checkFiledChange);
  48 + on<CountDownEvent>(_countDownChange);
  49 + on<CancelCountDownEvent>(_cancelTimer);
39 50 }
40 51  
41 52  
... ... @@ -100,6 +111,17 @@ class LoginBloc extends Bloc&lt;LoginEvent, LoginState&gt; {
100 111  
101 112 }
102 113  
  114 + ///倒计时
  115 + void _countDownChange(CountDownEvent event, Emitter<LoginState> emitter) {
  116 + _sendSmsIng = !_sendSmsIng;
  117 + emitter(CountDownNumChangeState());
  118 + }
  119 +
  120 + void _cancelTimer(CancelCountDownEvent event,Emitter<LoginState> emitter) {
  121 +
  122 + }
  123 +
  124 + ///登陆状态判断
103 125 bool _loginStateChange() {
104 126 if (_agreement) {
105 127 if (phoneNumController.text.isNotEmpty && checkNumController.text.isNotEmpty) {
... ...
lib/login/loginpage/bloc/login_event.dart
... ... @@ -14,3 +14,7 @@ class CheckFieldChangeEvent extends LoginEvent {}
14 14 class AgreementChangeEvent extends LoginEvent {}
15 15  
16 16 class ForgetPasswordEvent extends LoginEvent {}
  17 +
  18 +class CountDownEvent extends LoginEvent {}
  19 +
  20 +class CancelCountDownEvent extends LoginEvent {}
... ...
lib/login/loginpage/bloc/login_state.dart
... ... @@ -12,3 +12,5 @@ class LoginTypeChangeState extends LoginState {}
12 12 class SmsSendTypeChangeState extends LoginState {}
13 13  
14 14 class AgreementTypeChangeState extends LoginState {}
  15 +
  16 +class CountDownNumChangeState extends LoginState {}
... ...
lib/login/loginpage/login_page.dart
1   -import 'package:common_utils/common_utils.dart';
  1 +import 'package:flutter/gestures.dart';
2 2 import 'package:flutter/material.dart';
3 3 import 'package:flutter_bloc/flutter_bloc.dart';
4 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
5   -import 'package:fluttertoast/fluttertoast.dart';
6 5 import 'package:wow_english/common/extension/string_extension.dart';
7 6 import 'package:wow_english/common/widgets/textfield_customer_widget.dart';
8 7 import 'package:wow_english/login/loginpage/bloc/login_bloc.dart';
9 8 import 'package:wow_english/route/route.dart';
10 9  
11   -
12 10 class LoginPage extends StatelessWidget {
13 11 const LoginPage({super.key});
14 12  
... ... @@ -77,7 +75,54 @@ class LoginPage extends StatelessWidget {
77 75 color:bloc.agreement ? Colors.green:Colors.black),
78 76 ),
79 77 6.horizontalSpace,
80   - const Text('我已阅读并同意《用户隐私协议》,《儿童隐私策略》')
  78 + RichText(
  79 + text: TextSpan(
  80 + children:[
  81 + const TextSpan(
  82 + text: '我已阅读并同意',
  83 + style: TextStyle(
  84 + fontSize: 12,
  85 + color: Color(0xFF333333),
  86 + )
  87 + ),
  88 + TextSpan(
  89 + text: '《用户隐私协议》',
  90 + style: const TextStyle(
  91 + fontSize: 12,
  92 + color: Color(0xFF333333),
  93 + ),
  94 + recognizer: TapGestureRecognizer()..onTap = (){
  95 + Navigator.of(context).pushNamed(
  96 + AppRouteName.webView,
  97 + arguments: {
  98 + 'urlStr':'https://www.zhihu.com',
  99 + 'webViewTitle':'用户隐私协议'
  100 + });
  101 + }),
  102 + const TextSpan(
  103 + text: ',',
  104 + style: TextStyle(
  105 + fontSize: 12,
  106 + color: Color(0xFF333333)
  107 + )
  108 + ),
  109 + TextSpan(
  110 + text: '《儿童隐私政策》',
  111 + style: const TextStyle(
  112 + fontSize: 12,
  113 + color: Color(0xFF333333)
  114 + ),
  115 + recognizer: TapGestureRecognizer()..onTap = (){
  116 + Navigator.of(context).pushNamed(
  117 + AppRouteName.webView,
  118 + arguments: {
  119 + 'urlStr':'https://www.zhihu.com',
  120 + 'webViewTitle':'儿童隐私协议'
  121 + });
  122 + })
  123 + ]
  124 + ),
  125 + )
81 126 ],
82 127 ),
83 128 GestureDetector(
... ... @@ -142,21 +187,21 @@ class LoginPage extends StatelessWidget {
142 187 mainAxisAlignment: MainAxisAlignment.spaceBetween,
143 188 children: [
144 189 Expanded(
145   - child: TextFieldCustomerWidget(
146   - height: 50.h,
147   - hitText: '请输入验证码',
148   - textInputType: TextInputType.number,
149   - bgImageName: 'Input_layer_down',
150   - onChangeValue: (String value) {
151   - bloc.add(CheckFieldChangeEvent());
152   - },
153   - controller: bloc.checkNumController,
154   - )
  190 + child: TextFieldCustomerWidget(
  191 + height: 50.h,
  192 + hitText: '请输入验证码',
  193 + textInputType: TextInputType.number,
  194 + bgImageName: 'Input_layer_down',
  195 + onChangeValue: (String value) {
  196 + bloc.add(CheckFieldChangeEvent());
  197 + },
  198 + controller: bloc.checkNumController,
  199 + )
155 200 ),
156 201 GestureDetector(
157 202 onTap: () {
158 203 if (bloc.canSendSms) {
159   - bloc.add(ChangeLoginTypeEvent());
  204 + bloc.add(CountDownEvent());
160 205 }
161 206 },
162 207 child: Container(
... ... @@ -169,8 +214,8 @@ class LoginPage extends StatelessWidget {
169 214 ),
170 215 ),
171 216 padding: const EdgeInsets.symmetric(horizontal:12.0,vertical: 15.0),
172   - child: const Text(
173   - '获取验证码'
  217 + child: Text(
  218 + !bloc.sendSmsIng ? '获取验证码':'${bloc.countDown}s后在次获取'
174 219 ),
175 220 ),
176 221 )
... ... @@ -228,22 +273,18 @@ class LoginPage extends StatelessWidget {
228 273 ),
229 274 10.5.horizontalSpace,
230 275 Expanded(
231   - child: TextFieldCustomerWidget(
232   - hitText: '请输入密码',
233   - bgImageName: 'Input_layer_down',
234   - onChangeValue: (String value) {
235   - bloc.add(CheckFieldChangeEvent());
236   - },
237   - controller: bloc.checkNumController,
238   - )
  276 + child: TextFieldCustomerWidget(
  277 + hitText: '请输入密码',
  278 + bgImageName: 'Input_layer_down',
  279 + onChangeValue: (String value) {
  280 + bloc.add(CheckFieldChangeEvent());
  281 + },
  282 + controller: bloc.checkNumController,
  283 + )
239 284 ),
240 285 5.horizontalSpace,
241 286 GestureDetector(
242 287 onTap: () {
243   - if(!RegexUtil.isMobileExact(bloc.phoneNumController.text)) {
244   - Fluttertoast.showToast(msg: '手机号不正确!');
245   - return;
246   - }
247 288 Navigator.of(context).pushNamed(AppRouteName.fogPwd);
248 289 },
249 290 child: Container(
... ... @@ -261,5 +302,338 @@ class LoginPage extends StatelessWidget {
261 302 ),
262 303 );
263 304 });
264   -
265 305 }
  306 +
  307 +// class LoginPage extends StatefulWidget {
  308 +// const LoginPage({super.key});
  309 +//
  310 +// @override
  311 +// State<StatefulWidget> createState() {
  312 +// return _LoginPageState();
  313 +// }
  314 +//
  315 +// }
  316 +//
  317 +// class _LoginPageState extends State<LoginPage> {
  318 +// late Timer _timer;
  319 +// int _countdownTime = 0;
  320 +//
  321 +// void startCountdownTimer(BuildContext context) {
  322 +// final bloc = BlocProvider.of<LoginBloc>(context);
  323 +// if (bloc.sendSmsIng) {
  324 +// return;
  325 +// }
  326 +// bloc.add(CancelCountDownEvent());
  327 +// const oneSec = Duration(seconds: 1);
  328 +// _countdownTime = 60;
  329 +// _timer = Timer.periodic(oneSec,(timer) {
  330 +// setState(() {
  331 +// if (_countdownTime < 1) {
  332 +// bloc.add(CancelCountDownEvent());
  333 +// _timer.cancel();
  334 +// } else {
  335 +// _countdownTime = _countdownTime - 1;
  336 +// }
  337 +// });
  338 +// if (kDebugMode) {
  339 +// print(_countdownTime);
  340 +// }
  341 +// });
  342 +// }
  343 +//
  344 +//
  345 +//
  346 +// @override
  347 +// Widget build(BuildContext context) {
  348 +// return BlocProvider(
  349 +// create: (context) => LoginBloc(),
  350 +// child: _buildLoginViewWidget(),
  351 +// );
  352 +// }
  353 +//
  354 +// Widget _buildLoginViewWidget() => BlocBuilder<LoginBloc,LoginState> (
  355 +// builder: (context, state) {
  356 +// final bloc = BlocProvider.of<LoginBloc>(context);
  357 +// return Scaffold(
  358 +// body: SafeArea(
  359 +// child: ListView(
  360 +// children: [
  361 +// Container(
  362 +// padding: EdgeInsets.only(top: 25.h),
  363 +// child: Stack(
  364 +// children: [
  365 +// Positioned(
  366 +// right: 29.w,
  367 +// child: GestureDetector(
  368 +// onTap: () => bloc.add(ChangeLoginTypeEvent()),
  369 +// child: Container(
  370 +// decoration: BoxDecoration(
  371 +// image: DecorationImage(
  372 +// image: AssetImage(
  373 +// 'login_logo'.assetPng
  374 +// ),
  375 +// fit: BoxFit.fill
  376 +// ),
  377 +// ),
  378 +// padding: const EdgeInsets.symmetric(horizontal: 18.0),
  379 +// child: Text(
  380 +// bloc.loginType == LoginType.sms?'密码登陆':'验证码密码'
  381 +// ),
  382 +// ),
  383 +// )
  384 +// ),
  385 +// Center(
  386 +// child: Column(
  387 +// children: [
  388 +// Image.asset(
  389 +// 'wow_logo'.assetPng,
  390 +// height: 81.h,
  391 +// width: 131.w,
  392 +// ),
  393 +// Offstage(
  394 +// offstage: bloc.loginType == LoginType.pwd,
  395 +// child: _buildSmsViewWidget(),
  396 +// ),
  397 +// Offstage(
  398 +// offstage: bloc.loginType == LoginType.sms,
  399 +// child: _buildPwdViewWidget(),
  400 +// ),
  401 +// Row(
  402 +// mainAxisAlignment: MainAxisAlignment.center,
  403 +// children: [
  404 +// GestureDetector(
  405 +// onTap: () => bloc.add(AgreementChangeEvent()),
  406 +// child: Icon(
  407 +// bloc.agreement ? Icons.check_circle_outlined:Icons.circle_outlined,
  408 +// color:bloc.agreement ? Colors.green:Colors.black),
  409 +// ),
  410 +// 6.horizontalSpace,
  411 +// RichText(
  412 +// text: TextSpan(
  413 +// children:[
  414 +// const TextSpan(
  415 +// text: '我已阅读并同意',
  416 +// style: TextStyle(
  417 +// fontSize: 12,
  418 +// color: Color(0xFF333333),
  419 +// )
  420 +// ),
  421 +// TextSpan(
  422 +// text: '《用户隐私协议》',
  423 +// style: const TextStyle(
  424 +// fontSize: 12,
  425 +// color: Color(0xFF333333),
  426 +// ),
  427 +// recognizer: TapGestureRecognizer()..onTap = (){
  428 +// Navigator.of(context).pushNamed(
  429 +// AppRouteName.webView,
  430 +// arguments: {
  431 +// 'urlStr':'https://www.zhihu.com',
  432 +// 'webViewTitle':'用户隐私协议'
  433 +// });
  434 +// }),
  435 +// const TextSpan(
  436 +// text: ',',
  437 +// style: TextStyle(
  438 +// fontSize: 12,
  439 +// color: Color(0xFF333333)
  440 +// )
  441 +// ),
  442 +// TextSpan(
  443 +// text: '《儿童隐私政策》',
  444 +// style: const TextStyle(
  445 +// fontSize: 12,
  446 +// color: Color(0xFF333333)
  447 +// ),
  448 +// recognizer: TapGestureRecognizer()..onTap = (){
  449 +// Navigator.of(context).pushNamed(
  450 +// AppRouteName.webView,
  451 +// arguments: {
  452 +// 'urlStr':'https://www.zhihu.com',
  453 +// 'webViewTitle':'儿童隐私协议'
  454 +// });
  455 +// })
  456 +// ]
  457 +// ),
  458 +// )
  459 +// ],
  460 +// ),
  461 +// GestureDetector(
  462 +// onTap: () {
  463 +// if (bloc.canLogin) {
  464 +// bloc.add(RequestLoginEvent());
  465 +// }
  466 +// },
  467 +// child: Container(
  468 +// decoration: BoxDecoration(
  469 +// image: DecorationImage(
  470 +// image: AssetImage(
  471 +// bloc.canLogin?'login_enter'.assetPng:'login_enter_dis'.assetPng
  472 +// ),
  473 +// fit: BoxFit.fill
  474 +// ),
  475 +// ),
  476 +// padding: const EdgeInsets.symmetric(
  477 +// horizontal: 28.0,
  478 +// vertical: 14.0
  479 +// ),
  480 +// child: const Text(
  481 +// '登录'
  482 +// ),
  483 +// ),
  484 +// )
  485 +// ],
  486 +// ),
  487 +// )
  488 +// ],
  489 +// ),
  490 +// )
  491 +// ],
  492 +// ),
  493 +// ),
  494 +// );
  495 +// },
  496 +// );
  497 +//
  498 +// Widget _buildSmsViewWidget()=> BlocBuilder<LoginBloc,LoginState>(
  499 +// builder: (context,state){
  500 +// final bloc = BlocProvider.of<LoginBloc>(context);
  501 +// return Padding(
  502 +// padding: EdgeInsets.symmetric(horizontal: 135.w),
  503 +// child: Column(
  504 +// children: [
  505 +// 15.verticalSpace,
  506 +// TextFieldCustomerWidget(
  507 +// height: 55.h,
  508 +// hitText: '请输入手机号',
  509 +// textInputType: TextInputType.phone,
  510 +// bgImageName: 'Input_layer_up',
  511 +// onChangeValue: (String value) {
  512 +// bloc.add(PhoneNumChangeEvent());
  513 +// },
  514 +// controller: bloc.phoneNumController,
  515 +// ),
  516 +// 6.5.verticalSpace,
  517 +// const Text('未注册用户登录默认注册'),
  518 +// 4.5.verticalSpace,
  519 +// Row(
  520 +// mainAxisAlignment: MainAxisAlignment.spaceBetween,
  521 +// children: [
  522 +// Expanded(
  523 +// child: TextFieldCustomerWidget(
  524 +// height: 50.h,
  525 +// hitText: '请输入验证码',
  526 +// textInputType: TextInputType.number,
  527 +// bgImageName: 'Input_layer_down',
  528 +// onChangeValue: (String value) {
  529 +// bloc.add(CheckFieldChangeEvent());
  530 +// },
  531 +// controller: bloc.checkNumController,
  532 +// )
  533 +// ),
  534 +// GestureDetector(
  535 +// onTap: () {
  536 +// if (bloc.canSendSms) {
  537 +//
  538 +// }
  539 +// },
  540 +// child: Container(
  541 +// decoration: BoxDecoration(
  542 +// image: DecorationImage(
  543 +// image: AssetImage(
  544 +// bloc.canSendSms?'securitycode'.assetPng:'securitycode_dis'.assetPng
  545 +// ),
  546 +// fit: BoxFit.fill
  547 +// ),
  548 +// ),
  549 +// padding: const EdgeInsets.symmetric(horizontal:12.0,vertical: 15.0),
  550 +// child: Text(
  551 +// !bloc.sendSmsIng ? '获取验证码':'${bloc.countDown}s后在次获取'
  552 +// ),
  553 +// ),
  554 +// )
  555 +// ],
  556 +// )
  557 +// ],
  558 +// ),
  559 +// );
  560 +// });
  561 +
  562 + // Widget _buildPwdViewWidget()=> BlocBuilder<LoginBloc,LoginState>(
  563 + // builder: (context,state){
  564 + // final bloc = BlocProvider.of<LoginBloc>(context);
  565 + // return Padding(
  566 + // padding: EdgeInsets.symmetric(horizontal: 90.w),
  567 + // child: Column(
  568 + // children: [
  569 + // 15.verticalSpace,
  570 + // Row(
  571 + // mainAxisAlignment: MainAxisAlignment.center,
  572 + // children: [
  573 + // Image.asset(
  574 + // 'phone'.assetPng,
  575 + // height: 45.h,
  576 + // width: 35.w,
  577 + // ),
  578 + // 10.5.horizontalSpace,
  579 + // Expanded(
  580 + // child: TextFieldCustomerWidget(
  581 + // height: 50.h,
  582 + // hitText: '请输入手机号',
  583 + // textInputType: TextInputType.phone,
  584 + // bgImageName: 'Input_layer_up',
  585 + // onChangeValue: (String value) {
  586 + // bloc.add(PhoneNumChangeEvent());
  587 + // },
  588 + // controller: bloc.phoneNumController,
  589 + // )
  590 + // ),
  591 + // 5.horizontalSpace,
  592 + // SizedBox(
  593 + // width: 100.w,
  594 + // height: 55.h,
  595 + // )
  596 + // ],
  597 + // ),
  598 + // 12.verticalSpace,
  599 + // Row(
  600 + // mainAxisAlignment: MainAxisAlignment.center,
  601 + // children: [
  602 + // Image.asset(
  603 + // 'lock'.assetPng,
  604 + // height: 34.h,
  605 + // width: 31.w,
  606 + // ),
  607 + // 10.5.horizontalSpace,
  608 + // Expanded(
  609 + // child: TextFieldCustomerWidget(
  610 + // hitText: '请输入密码',
  611 + // bgImageName: 'Input_layer_down',
  612 + // onChangeValue: (String value) {
  613 + // bloc.add(CheckFieldChangeEvent());
  614 + // },
  615 + // controller: bloc.checkNumController,
  616 + // )
  617 + // ),
  618 + // 5.horizontalSpace,
  619 + // GestureDetector(
  620 + // onTap: () {
  621 + // Navigator.of(context).pushNamed(AppRouteName.fogPwd);
  622 + // },
  623 + // child: Container(
  624 + // width: 100.w,
  625 + // height: 55.h,
  626 + // alignment: Alignment.centerLeft,
  627 + // child: const Text(
  628 + // '忘记密码 ?'
  629 + // ),
  630 + // ),
  631 + // )
  632 + // ],
  633 + // )
  634 + // ],
  635 + // ),
  636 + // );
  637 + // });
  638 +
  639 +
... ...
lib/pages/page1.dart
1 1 import 'package:flutter/material.dart';
2   -import 'package:wow_english/widgets/we_app_bar.dart';
  2 +import 'package:wow_english/common/widgets/we_app_bar.dart';
3 3  
4 4 class Page1 extends StatelessWidget {
5 5 const Page1({super.key});
... ...
lib/pages/page2.dart
1 1 import 'package:flutter/material.dart';
2   -import 'package:wow_english/widgets/we_app_bar.dart';
  2 +import 'package:wow_english/common/widgets/we_app_bar.dart';
3 3  
4 4 class Page2 extends StatelessWidget {
5 5 const Page2({super.key});
... ...
lib/route/route.dart
1 1 import 'package:flutter/cupertino.dart';
2 2 import 'package:flutter/material.dart';
3 3 import 'package:wow_english/app/splash_page.dart';
  4 +import 'package:wow_english/common/pages/wow_web_page.dart';
4 5 import 'package:wow_english/home/home_page.dart';
5 6 import 'package:wow_english/login/forgetpwd/forget_password_home_page.dart';
6 7 import 'package:wow_english/login/loginpage/login_page.dart';
... ... @@ -14,6 +15,7 @@ class AppRouteName {
14 15 static const String home = 'home';
15 16 static const String fogPwd = 'fogPwd';
16 17 static const String setPwd = 'setPwd';
  18 + static const String webView = 'webView';
17 19 static const String tab = '/';
18 20 }
19 21  
... ... @@ -39,6 +41,10 @@ class AppRouter {
39 41 case AppRouteName.setPwd:
40 42 final phoneNum = (settings.arguments as Map)['phoneNumber'] as String;
41 43 return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum));
  44 + case AppRouteName.webView:
  45 + final urlStr = (settings.arguments as Map)['urlStr'] as String;
  46 + final webViewTitle = (settings.arguments as Map)['webViewTitle'] as String;
  47 + return CupertinoPageRoute(builder: (_) => WowWebViewPage(urlStr: urlStr,webViewTitle: webViewTitle,));
42 48 case AppRouteName.tab:
43 49 return PageRouteBuilder(
44 50 opaque: false,
... ...
pubspec.yaml
... ... @@ -46,7 +46,7 @@ dependencies:
46 46 #Url跳转 https://pub.dev/packages/url_launcher
47 47 url_launcher: ^6.1.11
48 48 #网页加载 https://pub.dev/packages/webview_flutter
49   - webview_flutter: ^4.2.0
  49 + webview_flutter: ^4.2.2
50 50 #下拉刷新 https://pub.dev/packages/pull_to_refresh
51 51 pull_to_refresh: ^2.0.0
52 52 # 数据持久化 https://pub.dev/packages/shared_preferences
... ... @@ -83,6 +83,8 @@ dependencies:
83 83 connectivity_plus: ^4.0.1
84 84 # iOS设备方向控制 https://pub.dev/packages/limiting_direction_csx
85 85 limiting_direction_csx: ^0.2.0
  86 + # 富文本插件 https://pub.dev/packages/extended_text
  87 + extended_text: ^11.0.1
86 88  
87 89 dev_dependencies:
88 90 build_runner: ^2.4.4
... ...