Commit 4bf67b9199cffc25939f5acd923b7fee8386e9f9

Authored by liangchengyou
1 parent 95edef4f

feat:设置密码

assets/images/login_error.png 0 → 100644

4.49 KB

assets/images/login_pass.png 0 → 100644

4.88 KB

assets/images/steven.png 0 → 100644

187 KB

lib/app/app.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
2 import 'package:flutter_bloc/flutter_bloc.dart'; 2 import 'package:flutter_bloc/flutter_bloc.dart';
3 import 'package:flutter_easyloading/flutter_easyloading.dart'; 3 import 'package:flutter_easyloading/flutter_easyloading.dart';
4 import 'package:flutter_screenutil/flutter_screenutil.dart'; 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:wow_english/common/widgets/hide_keyboard_widget.dart';
5 import 'package:wow_english/route/route.dart'; 6 import 'package:wow_english/route/route.dart';
6 import 'package:wow_english/tab/blocs/tab_bloc.dart'; 7 import 'package:wow_english/tab/blocs/tab_bloc.dart';
7 8
@@ -16,16 +17,18 @@ class App extends StatelessWidget { @@ -16,16 +17,18 @@ class App extends StatelessWidget {
16 providers: [ 17 providers: [
17 BlocProvider<TabBloc>(create: (_)=> TabBloc()) 18 BlocProvider<TabBloc>(create: (_)=> TabBloc())
18 ], 19 ],
19 - child: MaterialApp(  
20 - title: 'WowEnglish',  
21 - theme: ThemeData(  
22 - colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),  
23 - useMaterial3: true, 20 + child: HideKeyboard(
  21 + child: MaterialApp(
  22 + title: 'WowEnglish',
  23 + theme: ThemeData(
  24 + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
  25 + useMaterial3: true,
  26 + ),
  27 + builder: EasyLoading.init(),
  28 + initialRoute: AppRouteName.splash,
  29 + navigatorKey: AppRouter.navigatorKey,
  30 + onGenerateRoute: AppRouter.generateRoute,
24 ), 31 ),
25 - builder: EasyLoading.init(),  
26 - initialRoute: AppRouteName.splash,  
27 - navigatorKey: AppRouter.navigatorKey,  
28 - onGenerateRoute: AppRouter.generateRoute,  
29 )), 32 )),
30 ); 33 );
31 } 34 }
lib/common/widgets/hide_keyboard_widget.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +
  3 +class HideKeyboard extends StatelessWidget {
  4 +
  5 + const HideKeyboard({super.key,required this.child});
  6 +
  7 + final Widget child;
  8 +
  9 + @override
  10 + Widget build(BuildContext context) {
  11 + return GestureDetector(
  12 + onTap: (){
  13 + FocusScopeNode currentFocus = FocusScope.of(context);
  14 + if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
  15 + FocusManager.instance.primaryFocus?.unfocus();
  16 + }
  17 + },
  18 + child: child,
  19 + );
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
lib/common/widgets/textfiled_customer_widget.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +import 'package:wow_english/common/extension/string_extension.dart';
  4 +
  5 +class TextFiledCustomerWidget extends StatefulWidget {
  6 + const TextFiledCustomerWidget({super.key,
  7 + this.controller,
  8 + this.hitStyle,
  9 + this.textStyle,
  10 + this.bgImageName,
  11 + this.hitText,
  12 + this.width,
  13 + this.height,
  14 + this.textAlign,
  15 + this.textInputType,
  16 + this.onChangeValue
  17 + });
  18 +
  19 + final TextEditingController? controller;
  20 + final TextStyle? hitStyle;
  21 + final TextStyle? textStyle;
  22 + final String? bgImageName;
  23 + final String? hitText;
  24 + final double? width;
  25 + final double? height;
  26 + final TextAlign? textAlign;
  27 + final TextInputType? textInputType;
  28 + final Function(String value)? onChangeValue;
  29 +
  30 + @override
  31 + State<StatefulWidget> createState() {
  32 + return _TextFiledCustomerWidgetState();
  33 + }
  34 +}
  35 +
  36 +class _TextFiledCustomerWidgetState extends State<TextFiledCustomerWidget> {
  37 + @override
  38 + Widget build(BuildContext context) {
  39 + return Container(
  40 + height: widget.height??45.h,
  41 + width: widget.width??double.infinity,
  42 + alignment: Alignment.center,
  43 + decoration: BoxDecoration(
  44 + image: DecorationImage(
  45 + image: AssetImage(
  46 + '${widget.bgImageName}'.assetPng
  47 + ),
  48 + fit: BoxFit.fill,
  49 + )
  50 + ),
  51 + child: TextField(
  52 + controller: widget.controller,
  53 + textAlign: widget.textAlign??TextAlign.center,
  54 + textInputAction: TextInputAction.done,
  55 + keyboardType: widget.textInputType,
  56 + decoration: InputDecoration(
  57 + hintText: widget.hitText??'',
  58 + border: InputBorder.none,
  59 + hintStyle: widget.hitStyle?? TextStyle(
  60 + fontSize: 16.sp,
  61 + color:const Color(0xFF999999)
  62 + )
  63 + ),
  64 + style: widget.textStyle?? TextStyle(
  65 + color: const Color(0xFF333333),
  66 + fontSize: 16.sp,
  67 + ),
  68 + onChanged: widget.onChangeValue,
  69 + ),
  70 + );
  71 + }
  72 +}
  73 +
lib/home/home_page.dart
@@ -7,15 +7,13 @@ class HomePage extends StatelessWidget { @@ -7,15 +7,13 @@ class HomePage extends StatelessWidget {
7 @override 7 @override
8 Widget build(BuildContext context) { 8 Widget build(BuildContext context) {
9 return Scaffold( 9 return Scaffold(
10 - body: SafeArea(  
11 - child: Container(  
12 - color: Colors.white,  
13 - child: const Center(  
14 - child: Column(  
15 - children: [  
16 - HomeTabHeaderWidget(),  
17 - ],  
18 - ), 10 + body: Container(
  11 + color: Colors.white,
  12 + child: const Center(
  13 + child: Column(
  14 + children: [
  15 + HomeTabHeaderWidget(),
  16 + ],
19 ), 17 ),
20 ), 18 ),
21 ), 19 ),
lib/home/widgets/home_tab_header_widget.dart
@@ -14,6 +14,7 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -14,6 +14,7 @@ class HomeTabHeaderWidget extends StatelessWidget {
14 padding: EdgeInsets.symmetric(horizontal: 9.5.w), 14 padding: EdgeInsets.symmetric(horizontal: 9.5.w),
15 child: Row( 15 child: Row(
16 children: [ 16 children: [
  17 + ScreenUtil().bottomBarHeight.horizontalSpace,
17 ClipRRect( 18 ClipRRect(
18 borderRadius:BorderRadius.circular(21), 19 borderRadius:BorderRadius.circular(21),
19 child: Image.network( 20 child: Image.network(
@@ -55,7 +56,8 @@ class HomeTabHeaderWidget extends StatelessWidget { @@ -55,7 +56,8 @@ class HomeTabHeaderWidget extends StatelessWidget {
55 IconButton( 56 IconButton(
56 onPressed: (){}, 57 onPressed: (){},
57 icon: Image.asset('shop'.assetPng) 58 icon: Image.asset('shop'.assetPng)
58 - ) 59 + ),
  60 + ScreenUtil().bottomBarHeight.horizontalSpace,
59 ], 61 ],
60 ), 62 ),
61 ); 63 );
lib/login/blocs/forget_pwd_bloc.dart 0 → 100644
  1 +import 'dart:async';
  2 +
  3 +import 'package:bloc/bloc.dart';
  4 +import 'package:meta/meta.dart';
  5 +
  6 +part 'forget_pwd_event.dart';
  7 +part 'forget_pwd_state.dart';
  8 +
  9 +class ForgetPwdBloc extends Bloc<ForgetPwdEvent, ForgetPwdState> {
  10 + ForgetPwdBloc() : super(ForgetPwdInitial()) {
  11 + on<ForgetPwdEvent>((event, emit) {
  12 + // TODO: implement event handler
  13 + });
  14 + }
  15 +}
lib/login/blocs/forget_pwd_event.dart 0 → 100644
  1 +part of 'forget_pwd_bloc.dart';
  2 +
  3 +@immutable
  4 +abstract class ForgetPwdEvent {}
lib/login/blocs/forget_pwd_state.dart 0 → 100644
  1 +part of 'forget_pwd_bloc.dart';
  2 +
  3 +@immutable
  4 +abstract class ForgetPwdState {}
  5 +
  6 +class ForgetPwdInitial extends ForgetPwdState {}
lib/login/forget_password_page.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/common/extension/string_extension.dart';
  5 +import 'package:wow_english/common/widgets/textfiled_customer_widget.dart';
  6 +
  7 +import 'blocs/forget_pwd_bloc.dart';
  8 +
  9 +class ForgetPassWordPage extends StatelessWidget {
  10 + const ForgetPassWordPage({super.key, this.phoneNum});
  11 + final String? phoneNum;
  12 +
  13 + @override
  14 + Widget build(BuildContext context) {
  15 + // TODO: implement build
  16 + return BlocProvider(
  17 + create: (context) => ForgetPwdBloc(),
  18 + child: Scaffold(
  19 + body: Container(
  20 + color: Colors.white,
  21 + child: SafeArea(
  22 + child: Padding(
  23 + padding: EdgeInsets.symmetric(horizontal: 40.w),
  24 + child: Column(
  25 + children: [
  26 + 34.verticalSpace,
  27 + Row(
  28 + children: [
  29 + Image.asset(
  30 + 'wow_logo'.assetPng,
  31 + height: 49.w,
  32 + width: 83.5.h,
  33 + ),
  34 + 12.5.horizontalSpace,
  35 + Text(
  36 + '欢迎登录wow english\n接下来请设置一下您的密码吧!',
  37 + style: TextStyle(
  38 + fontSize: 16.sp,
  39 + color: const Color(0xFF666666)
  40 + ),
  41 + )
  42 + ],
  43 + ),
  44 + Row(
  45 + crossAxisAlignment: CrossAxisAlignment.start,
  46 + children: [
  47 + Expanded(
  48 + child: Column(
  49 + mainAxisAlignment: MainAxisAlignment.start,
  50 + children: [
  51 + 43.verticalSpace,
  52 + Row(
  53 + children: [
  54 + Expanded(
  55 + child: TextFiledCustomerWidget(
  56 + height: 55.h,
  57 + hitText: '请输入八位以上密码',
  58 + bgImageName: 'Input_layer_up',
  59 + onChangeValue: (String value) {
  60 +
  61 + },
  62 + )
  63 + ),
  64 + 10.horizontalSpace,
  65 + Offstage(
  66 + offstage: false,
  67 + child: Image.asset(
  68 + 'login_pass'.assetPng,
  69 + height: 30,
  70 + width: 30,
  71 + ),
  72 + )
  73 + ],
  74 + ),
  75 + 9.verticalSpace,
  76 + const Offstage(
  77 + offstage: false,
  78 + child: Text('您已达到密码最大输入数,请妥善调整密码'),
  79 + ),
  80 + 9.verticalSpace,
  81 + Row(
  82 + children: [
  83 + Expanded(
  84 + child: TextFiledCustomerWidget(
  85 + height: 55.h,
  86 + hitText: '请再次输入相同密码',
  87 + bgImageName: 'Input_layer_up',
  88 + onChangeValue: (String value) {
  89 +
  90 + },
  91 + )
  92 + ),
  93 + 10.horizontalSpace,
  94 + Offstage(
  95 + offstage: false,
  96 + child: Image.asset(
  97 + 'login_error'.assetPng,
  98 + height: 30,
  99 + width: 30,
  100 + ),
  101 + )
  102 + ],
  103 + ),
  104 + 9.verticalSpace,
  105 + const Offstage(
  106 + offstage: false,
  107 + child: Text('请确认两次输入的密码是否一致'),
  108 + ),
  109 + Row(
  110 + mainAxisAlignment: MainAxisAlignment.end,
  111 + children: [
  112 + GestureDetector(
  113 + onTap: () {
  114 +
  115 + },
  116 + child: Container(
  117 + decoration: BoxDecoration(
  118 + image: DecorationImage(
  119 + image: AssetImage(
  120 + 'login_enter'.assetPng
  121 + ),
  122 + fit: BoxFit.fill
  123 + ),
  124 + ),
  125 + padding: const EdgeInsets.symmetric(
  126 + horizontal: 28.0,
  127 + vertical: 14.0
  128 + ),
  129 + child: const Text(
  130 + '确定',
  131 + style: TextStyle(
  132 + color: Colors.white
  133 + ),
  134 + ),
  135 + ),
  136 + ),
  137 + 50.horizontalSpace
  138 + ],
  139 + )
  140 + ],
  141 + ),
  142 + ),
  143 + 30.horizontalSpace,
  144 + Image.asset(
  145 + 'steven'.assetPng,
  146 + height: 254.h,
  147 + width: 100.w,
  148 + )
  149 + ],
  150 + ),
  151 + ],
  152 + ),
  153 + ),
  154 + ),
  155 + ),
  156 + ),
  157 + );;
  158 + }
  159 +}
0 \ No newline at end of file 160 \ No newline at end of file
lib/login/login_page.dart
  1 +import 'package:common_utils/common_utils.dart';
1 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
2 import 'package:flutter_bloc/flutter_bloc.dart'; 3 import 'package:flutter_bloc/flutter_bloc.dart';
3 import 'package:flutter_screenutil/flutter_screenutil.dart'; 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:fluttertoast/fluttertoast.dart';
4 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/textfiled_customer_widget.dart';
5 import 'package:wow_english/login/blocs/login_bloc.dart'; 8 import 'package:wow_english/login/blocs/login_bloc.dart';
6 import 'package:wow_english/route/route.dart'; 9 import 'package:wow_english/route/route.dart';
7 10
@@ -121,31 +124,15 @@ class LoginPage extends StatelessWidget { @@ -121,31 +124,15 @@ class LoginPage extends StatelessWidget {
121 child: Column( 124 child: Column(
122 children: [ 125 children: [
123 15.verticalSpace, 126 15.verticalSpace,
124 - Container(  
125 - height: 55.h,  
126 - width: double.infinity,  
127 - alignment: Alignment.center,  
128 - decoration: BoxDecoration(  
129 - image: DecorationImage(  
130 - image: AssetImage(  
131 - 'Input_layer_up'.assetPng  
132 - ),  
133 - fit: BoxFit.fitWidth  
134 - ),  
135 - ),  
136 - child: TextField(  
137 - controller: bloc.phoneNumController,  
138 - textAlign: TextAlign.center,  
139 - textInputAction: TextInputAction.done,  
140 - keyboardType: TextInputType.phone,  
141 - decoration: const InputDecoration(  
142 - hintText: '请输入手机号',  
143 - border: InputBorder.none,  
144 - ),  
145 - onChanged: (String value) {  
146 - bloc.add(PhoneNumChangeEvent());  
147 - },  
148 - ) 127 + TextFiledCustomerWidget(
  128 + height: 55.h,
  129 + hitText: '请输入手机号',
  130 + textInputType: TextInputType.phone,
  131 + bgImageName: 'Input_layer_up',
  132 + onChangeValue: (String value) {
  133 + bloc.add(PhoneNumChangeEvent());
  134 + },
  135 + controller: bloc.phoneNumController,
149 ), 136 ),
150 6.5.verticalSpace, 137 6.5.verticalSpace,
151 const Text('未注册用户登录默认注册'), 138 const Text('未注册用户登录默认注册'),
@@ -154,31 +141,16 @@ class LoginPage extends StatelessWidget { @@ -154,31 +141,16 @@ class LoginPage extends StatelessWidget {
154 mainAxisAlignment: MainAxisAlignment.spaceBetween, 141 mainAxisAlignment: MainAxisAlignment.spaceBetween,
155 children: [ 142 children: [
156 Expanded( 143 Expanded(
157 - child: Container(  
158 - height: 50.h,  
159 - width: double.infinity,  
160 - alignment: Alignment.center,  
161 - decoration: BoxDecoration(  
162 - image: DecorationImage(  
163 - image: AssetImage(  
164 - 'Input_layer_down'.assetPng,  
165 - ),  
166 - )  
167 - ),  
168 - child: TextField(  
169 - controller: bloc.checkNumController,  
170 - textAlign: TextAlign.center,  
171 - textInputAction: TextInputAction.done,  
172 - keyboardType: TextInputType.number,  
173 - decoration: const InputDecoration(  
174 - hintText: '请输入验证码',  
175 - border: InputBorder.none,  
176 - ),  
177 - onChanged: (String value) {  
178 - bloc.add(CheckFieldChangeEvent());  
179 - },  
180 - )  
181 - ), 144 + child: TextFiledCustomerWidget(
  145 + height: 50.h,
  146 + hitText: '请输入验证码',
  147 + textInputType: TextInputType.number,
  148 + bgImageName: 'Input_layer_down',
  149 + onChangeValue: (String value) {
  150 + bloc.add(CheckFieldChangeEvent());
  151 + },
  152 + controller: bloc.checkNumController,
  153 + )
182 ), 154 ),
183 GestureDetector( 155 GestureDetector(
184 onTap: () { 156 onTap: () {
@@ -226,29 +198,17 @@ class LoginPage extends StatelessWidget { @@ -226,29 +198,17 @@ class LoginPage extends StatelessWidget {
226 ), 198 ),
227 10.5.horizontalSpace, 199 10.5.horizontalSpace,
228 Expanded( 200 Expanded(
229 - child: Container(  
230 - height: 55.h,  
231 - width: double.infinity,  
232 - alignment: Alignment.center,  
233 - decoration: BoxDecoration(  
234 - image: DecorationImage(  
235 - image: AssetImage(  
236 - 'Input_layer_up'.assetPng  
237 - ),  
238 - fit: BoxFit.fitWidth,  
239 - )  
240 - ),  
241 - child: TextField(  
242 - controller: bloc.phoneNumController,  
243 - textAlign: TextAlign.center,  
244 - textInputAction: TextInputAction.done,  
245 - decoration: const InputDecoration(  
246 - hintText: '请输入手机号',  
247 - border: InputBorder.none,  
248 - ),  
249 - keyboardType: TextInputType.phone,  
250 - onChanged: (String value) {bloc.add(PhoneNumChangeEvent());},)  
251 - )), 201 + child: TextFiledCustomerWidget(
  202 + height: 50.h,
  203 + hitText: '请输入手机号',
  204 + textInputType: TextInputType.phone,
  205 + bgImageName: 'Input_layer_up',
  206 + onChangeValue: (String value) {
  207 + bloc.add(PhoneNumChangeEvent());
  208 + },
  209 + controller: bloc.phoneNumController,
  210 + )
  211 + ),
252 5.horizontalSpace, 212 5.horizontalSpace,
253 SizedBox( 213 SizedBox(
254 width: 100.w, 214 width: 100.w,
@@ -267,36 +227,23 @@ class LoginPage extends StatelessWidget { @@ -267,36 +227,23 @@ class LoginPage extends StatelessWidget {
267 ), 227 ),
268 10.5.horizontalSpace, 228 10.5.horizontalSpace,
269 Expanded( 229 Expanded(
270 - child: Container(  
271 - width: 397.5,  
272 - height: 55,  
273 - alignment: Alignment.center,  
274 - decoration: BoxDecoration(  
275 - image: DecorationImage(  
276 - image: AssetImage(  
277 - 'Input_layer_down'.assetPng  
278 - ),  
279 - fit: BoxFit.fill,  
280 - )  
281 - ),  
282 - child: TextField(  
283 - controller: bloc.checkNumController,  
284 - textAlign: TextAlign.center,  
285 - textInputAction: TextInputAction.done,  
286 - decoration: const InputDecoration(  
287 - hintText: '请输入密码',  
288 - border: InputBorder.none,  
289 - ),  
290 - onChanged: (String value) {  
291 - bloc.add(CheckFieldChangeEvent());  
292 - },  
293 - )  
294 - ), 230 + child: TextFiledCustomerWidget(
  231 + hitText: '请输入密码',
  232 + bgImageName: 'Input_layer_down',
  233 + onChangeValue: (String value) {
  234 + bloc.add(CheckFieldChangeEvent());
  235 + },
  236 + controller: bloc.checkNumController,
  237 + )
295 ), 238 ),
296 5.horizontalSpace, 239 5.horizontalSpace,
297 GestureDetector( 240 GestureDetector(
298 onTap: () { 241 onTap: () {
299 - Navigator.of(context).pushNamed(AppRouteName.home); 242 + if(!RegexUtil.isMobileExact(bloc.phoneNumController.text)) {
  243 + Fluttertoast.showToast(msg: '手机号不正确!');
  244 + return;
  245 + }
  246 + Navigator.of(context).pushNamed(AppRouteName.fogPwd,arguments: {'phoneNumber':bloc.phoneNumController.text});
300 }, 247 },
301 child: Container( 248 child: Container(
302 width: 100.w, 249 width: 100.w,
lib/route/route.dart
@@ -2,6 +2,7 @@ import &#39;package:flutter/cupertino.dart&#39;; @@ -2,6 +2,7 @@ import &#39;package:flutter/cupertino.dart&#39;;
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 import 'package:wow_english/app/splash_page.dart'; 3 import 'package:wow_english/app/splash_page.dart';
4 import 'package:wow_english/home/home_page.dart'; 4 import 'package:wow_english/home/home_page.dart';
  5 +import 'package:wow_english/login/forget_password_page.dart';
5 import 'package:wow_english/login/login_page.dart'; 6 import 'package:wow_english/login/login_page.dart';
6 import 'package:wow_english/tab/tab_page.dart'; 7 import 'package:wow_english/tab/tab_page.dart';
7 8
@@ -10,6 +11,7 @@ class AppRouteName { @@ -10,6 +11,7 @@ class AppRouteName {
10 static const String splash = 'splash'; 11 static const String splash = 'splash';
11 static const String login = 'login'; 12 static const String login = 'login';
12 static const String home = 'home'; 13 static const String home = 'home';
  14 + static const String fogPwd = 'fogPwd';
13 static const String tab = '/'; 15 static const String tab = '/';
14 } 16 }
15 17
@@ -30,6 +32,9 @@ class AppRouter { @@ -30,6 +32,9 @@ class AppRouter {
30 return CupertinoPageRoute(builder: (_) => const LoginPage()); 32 return CupertinoPageRoute(builder: (_) => const LoginPage());
31 case AppRouteName.home: 33 case AppRouteName.home:
32 return CupertinoPageRoute(builder: (_) => const HomePage()); 34 return CupertinoPageRoute(builder: (_) => const HomePage());
  35 + case AppRouteName.fogPwd:
  36 + final phoneNum = (settings.arguments as Map)['phoneNumber'] as String;
  37 + return CupertinoPageRoute(builder: (_) => ForgetPassWordPage(phoneNum: phoneNum));
33 case AppRouteName.tab: 38 case AppRouteName.tab:
34 return PageRouteBuilder( 39 return PageRouteBuilder(
35 opaque: false, 40 opaque: false,