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 2 import 'package:flutter_bloc/flutter_bloc.dart';
3 3 import 'package:flutter_easyloading/flutter_easyloading.dart';
4 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:wow_english/common/widgets/hide_keyboard_widget.dart';
5 6 import 'package:wow_english/route/route.dart';
6 7 import 'package:wow_english/tab/blocs/tab_bloc.dart';
7 8  
... ... @@ -16,16 +17,18 @@ class App extends StatelessWidget {
16 17 providers: [
17 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 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 7 @override
8 8 Widget build(BuildContext context) {
9 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 14 padding: EdgeInsets.symmetric(horizontal: 9.5.w),
15 15 child: Row(
16 16 children: [
  17 + ScreenUtil().bottomBarHeight.horizontalSpace,
17 18 ClipRRect(
18 19 borderRadius:BorderRadius.circular(21),
19 20 child: Image.network(
... ... @@ -55,7 +56,8 @@ class HomeTabHeaderWidget extends StatelessWidget {
55 56 IconButton(
56 57 onPressed: (){},
57 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 160 \ No newline at end of file
... ...
lib/login/login_page.dart
  1 +import 'package:common_utils/common_utils.dart';
1 2 import 'package:flutter/material.dart';
2 3 import 'package:flutter_bloc/flutter_bloc.dart';
3 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:fluttertoast/fluttertoast.dart';
4 6 import 'package:wow_english/common/extension/string_extension.dart';
  7 +import 'package:wow_english/common/widgets/textfiled_customer_widget.dart';
5 8 import 'package:wow_english/login/blocs/login_bloc.dart';
6 9 import 'package:wow_english/route/route.dart';
7 10  
... ... @@ -121,31 +124,15 @@ class LoginPage extends StatelessWidget {
121 124 child: Column(
122 125 children: [
123 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 137 6.5.verticalSpace,
151 138 const Text('未注册用户登录默认注册'),
... ... @@ -154,31 +141,16 @@ class LoginPage extends StatelessWidget {
154 141 mainAxisAlignment: MainAxisAlignment.spaceBetween,
155 142 children: [
156 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 155 GestureDetector(
184 156 onTap: () {
... ... @@ -226,29 +198,17 @@ class LoginPage extends StatelessWidget {
226 198 ),
227 199 10.5.horizontalSpace,
228 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 212 5.horizontalSpace,
253 213 SizedBox(
254 214 width: 100.w,
... ... @@ -267,36 +227,23 @@ class LoginPage extends StatelessWidget {
267 227 ),
268 228 10.5.horizontalSpace,
269 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 239 5.horizontalSpace,
297 240 GestureDetector(
298 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 248 child: Container(
302 249 width: 100.w,
... ...
lib/route/route.dart
... ... @@ -2,6 +2,7 @@ import &#39;package:flutter/cupertino.dart&#39;;
2 2 import 'package:flutter/material.dart';
3 3 import 'package:wow_english/app/splash_page.dart';
4 4 import 'package:wow_english/home/home_page.dart';
  5 +import 'package:wow_english/login/forget_password_page.dart';
5 6 import 'package:wow_english/login/login_page.dart';
6 7 import 'package:wow_english/tab/tab_page.dart';
7 8  
... ... @@ -10,6 +11,7 @@ class AppRouteName {
10 11 static const String splash = 'splash';
11 12 static const String login = 'login';
12 13 static const String home = 'home';
  14 + static const String fogPwd = 'fogPwd';
13 15 static const String tab = '/';
14 16 }
15 17  
... ... @@ -30,6 +32,9 @@ class AppRouter {
30 32 return CupertinoPageRoute(builder: (_) => const LoginPage());
31 33 case AppRouteName.home:
32 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 38 case AppRouteName.tab:
34 39 return PageRouteBuilder(
35 40 opaque: false,
... ...