From da82bd70e6b3907583c46519e8e7c34aa8d15514 Mon Sep 17 00:00:00 2001 From: Key Date: Thu, 29 Jun 2023 16:33:42 +0800 Subject: [PATCH] feat: user_information_page.dart fixed: appbar style --- assets/images/bg_user_information_text.png | Bin 0 -> 32641 bytes assets/images/ic_next.png | Bin 0 -> 4086 bytes lib/app/app.dart | 2 ++ lib/common/blocs/cachebloc/cache_bloc.dart | 1 + lib/common/blocs/cachebloc/cache_event.dart | 2 ++ lib/common/blocs/cachebloc/cache_state.dart | 2 ++ lib/common/core/assets_const.dart | 2 ++ lib/common/request/apis.dart | 5 ++++- lib/common/request/dao/user_dao.dart | 18 ++++++++++++++++-- lib/common/widgets/we_app_bar.dart | 61 +++++++++++++++++++++++++++++++++++-------------------------- lib/models/user_entity.dart | 2 +- lib/pages/home/widgets/home_tab_header_widget.dart | 2 +- lib/pages/login/forgetpwd/forget_password_home_page.dart | 3 ++- lib/pages/login/setpwd/bloc/set_pwd_bloc.dart | 7 ++++--- lib/pages/login/setpwd/set_pwd_page.dart | 4 ++-- lib/pages/practice/topic_picture_page.dart | 2 +- lib/pages/user/information/user_information_bloc.dart | 13 +++++++++++++ lib/pages/user/information/user_information_event.dart | 4 ++++ lib/pages/user/information/user_information_page.dart | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/user/information/user_information_state.dart | 6 ++++++ lib/pages/user/user_page.dart | 9 +++++---- lib/route/route.dart | 8 ++++++++ 22 files changed, 257 insertions(+), 42 deletions(-) create mode 100644 assets/images/bg_user_information_text.png create mode 100644 assets/images/ic_next.png create mode 100644 lib/pages/user/information/user_information_bloc.dart create mode 100644 lib/pages/user/information/user_information_event.dart create mode 100644 lib/pages/user/information/user_information_page.dart create mode 100644 lib/pages/user/information/user_information_state.dart diff --git a/assets/images/bg_user_information_text.png b/assets/images/bg_user_information_text.png new file mode 100644 index 0000000..7b9c848 Binary files /dev/null and b/assets/images/bg_user_information_text.png differ diff --git a/assets/images/ic_next.png b/assets/images/ic_next.png new file mode 100644 index 0000000..11a23a5 Binary files /dev/null and b/assets/images/ic_next.png differ diff --git a/lib/app/app.dart b/lib/app/app.dart index 28cfa2c..6e425b2 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -4,6 +4,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:responsive_framework/breakpoint.dart'; import 'package:responsive_framework/responsive_breakpoints.dart'; +import 'package:wow_english/common/blocs/cachebloc/cache_bloc.dart'; import 'package:wow_english/common/widgets/hide_keyboard_widget.dart'; import 'package:wow_english/pages/tab/blocs/tab_bloc.dart'; import 'package:wow_english/route/route.dart'; @@ -18,6 +19,7 @@ class App extends StatelessWidget { builder: (_, __) => MultiBlocProvider( providers: [ BlocProvider(create: (_) => TabBloc()), + BlocProvider(create: (_) => CacheBloc()), ], child: HideKeyboard( child: MaterialApp( diff --git a/lib/common/blocs/cachebloc/cache_bloc.dart b/lib/common/blocs/cachebloc/cache_bloc.dart index db5bb2f..149ed82 100644 --- a/lib/common/blocs/cachebloc/cache_bloc.dart +++ b/lib/common/blocs/cachebloc/cache_bloc.dart @@ -4,5 +4,6 @@ part 'cache_event.dart'; part 'cache_state.dart'; class CacheBloc extends Bloc { + /// app配置信息 CacheBloc() : super(CacheInitial()); } diff --git a/lib/common/blocs/cachebloc/cache_event.dart b/lib/common/blocs/cachebloc/cache_event.dart index cc9d2ef..a34ccf9 100644 --- a/lib/common/blocs/cachebloc/cache_event.dart +++ b/lib/common/blocs/cachebloc/cache_event.dart @@ -1,3 +1,5 @@ part of 'cache_bloc.dart'; sealed class CacheEvent {} + +class CacheUserInfoUpdate extends CacheEvent {} diff --git a/lib/common/blocs/cachebloc/cache_state.dart b/lib/common/blocs/cachebloc/cache_state.dart index f4ad7bc..781add3 100644 --- a/lib/common/blocs/cachebloc/cache_state.dart +++ b/lib/common/blocs/cachebloc/cache_state.dart @@ -3,3 +3,5 @@ part of 'cache_bloc.dart'; sealed class CacheState {} class CacheInitial extends CacheState {} + +class CacheUserInfoUpdated extends CacheState {} diff --git a/lib/common/core/assets_const.dart b/lib/common/core/assets_const.dart index 622a1c9..8766f54 100644 --- a/lib/common/core/assets_const.dart +++ b/lib/common/core/assets_const.dart @@ -2,5 +2,7 @@ class AssetsConst { static const String _assetImagePrefix = 'assets/images/'; static const String wowLogo = '${_assetImagePrefix}wow_logo.png'; static const String icVip = '${_assetImagePrefix}ic_vip.png'; + static const String icNext = '${_assetImagePrefix}ic_next.png'; + static const String bgUserInformationText = '${_assetImagePrefix}bg_user_information_text.png'; //static String get icVip2 =>'ic_vip.png'.assetImg; } diff --git a/lib/common/request/apis.dart b/lib/common/request/apis.dart index 3917e32..70b3217 100644 --- a/lib/common/request/apis.dart +++ b/lib/common/request/apis.dart @@ -25,11 +25,14 @@ class Apis { static const String initPassword = 'student/init/password'; /// 修改密码 - static const String changePassword = 'student/init/password'; + static const String changePassword = 'student/change/password'; /// 忘记密码 static const String resetPassword = 'student/change/password'; + /// 校验验证码,用于修改密码或忘记密码,验证码有效期2分钟 + static const String checkSmsCode = 'student/check/code'; + /// 课程模块 // GET /home/courseModule // 接口地址:https://app.apifox.com/link/project/2684751/apis/api-89897663 diff --git a/lib/common/request/dao/user_dao.dart b/lib/common/request/dao/user_dao.dart index e80e559..3e4c77a 100644 --- a/lib/common/request/dao/user_dao.dart +++ b/lib/common/request/dao/user_dao.dart @@ -3,6 +3,8 @@ import 'package:wow_english/models/user_entity.dart'; import '../request_client.dart'; +enum SmsType { login, change_passWord, stdDestroy } + class UserDao { /// 登录 static Future login(phoneNumber, type, checkKey, checkNumber) async { @@ -26,6 +28,7 @@ class UserDao { } /// 发送验证码 + /// [msgType] 消息类型 登录:login, 更改密码:change_passWord, 账号注销:stdDestroy static Future sendCode(phoneNumber, {smsType = 'login'}) async { final params = {'phoneNum': phoneNumber, 'smsType': smsType}; await requestClient.post(Apis.sendSmsCode, data: params); @@ -39,19 +42,30 @@ class UserDao { } /// 修改密码 + /// [phoneNum] 手机号 /// [password] 密码 - static Future changePassword(String password) async { - final params = {'password': password}; + /// [smsCode] 短信验证码 + static Future changePassword(String phoneNum, String password, String smsCode) async { + final params = {'phoneNum': phoneNum, 'password': password, 'code': smsCode}; await requestClient.post(Apis.changePassword, data: params); } /// 忘记密码 + /// [phoneNum] 手机号 /// [password] 密码 + /// [smsCode] 短信验证码 static Future resetPassword(String phoneNum, String password, String smsCode) async { final params = {'phoneNum': phoneNum, 'password': password, 'code': smsCode}; await requestClient.post(Apis.resetPassword, data: params); } + /// 验证短信验证码 + /// [msgType] 消息类型 登录:login, 更改密码:change_passWord, 账号注销:stdDestroy + static Future checkSmsCode(String phoneNum, String smsCode, String msgType) async { + final params = {'phoneNum': phoneNum, 'code': smsCode, 'msgType': msgType}; + await requestClient.post(Apis.checkSmsCode, data: params); + } + /// 获取用户信息 static Future getUserInfo() async { return await requestClient.post(Apis.getUserInfo); diff --git a/lib/common/widgets/we_app_bar.dart b/lib/common/widgets/we_app_bar.dart index 4b5f43b..55f1608 100644 --- a/lib/common/widgets/we_app_bar.dart +++ b/lib/common/widgets/we_app_bar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wow_english/common/extension/string_extension.dart'; class WEAppBar extends StatelessWidget implements PreferredSizeWidget { @@ -9,41 +10,49 @@ class WEAppBar extends StatelessWidget implements PreferredSizeWidget { final PreferredSizeWidget? bottom; final Widget? leading; final List? actions; - const WEAppBar({ - this.titleText, - this.centerTitle = true, - this.onBack, - this.backgroundColor, - this.bottom, - this.leading, - this.actions, - super.key}); + + const WEAppBar( + {this.titleText, + this.centerTitle = true, + this.onBack, + this.backgroundColor, + this.bottom, + this.leading, + this.actions, + super.key}); @override Widget build(BuildContext context) { return AppBar( centerTitle: centerTitle, - title: Text(titleText??''), - leading: leading??GestureDetector( - onTap: () { - Navigator.pop(context); - }, - child: Container( - alignment: Alignment.center, - child: Image.asset( - 'back_around'.assetPng, - height: 40, - width: 40, - ), + title: Text( + titleText ?? '', + style: TextStyle( + fontSize: 25.sp, + color: const Color(0xFF333333), + fontWeight: FontWeight.w700, ), ), - backgroundColor: backgroundColor??Colors.white, - actions: actions??[], + leading: leading ?? + GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Container( + alignment: Alignment.center, + child: Image.asset( + 'back_around'.assetPng, + height: 40.h, + width: 40.w, + ), + ), + ), + backgroundColor: backgroundColor ?? Colors.white, + actions: actions ?? [], ); } @override // TODO: implement preferredSize - Size get preferredSize => Size.fromHeight( - kToolbarHeight + (bottom == null ? 0.0 : bottom!.preferredSize.height)); -} \ No newline at end of file + Size get preferredSize => Size.fromHeight(kToolbarHeight + (bottom == null ? 0.0 : bottom!.preferredSize.height)); +} diff --git a/lib/models/user_entity.dart b/lib/models/user_entity.dart index 09cf1fd..e165c25 100644 --- a/lib/models/user_entity.dart +++ b/lib/models/user_entity.dart @@ -18,7 +18,7 @@ class UserEntity { /// 性别:0, 1 int? gender; String? avatarUrl; - String? phoneNum; + late String phoneNum; /// 用户信息是否填写 0.未填写 1.已经填写 int? fillUserInfo; diff --git a/lib/pages/home/widgets/home_tab_header_widget.dart b/lib/pages/home/widgets/home_tab_header_widget.dart index 07ce4ac..824e390 100644 --- a/lib/pages/home/widgets/home_tab_header_widget.dart +++ b/lib/pages/home/widgets/home_tab_header_widget.dart @@ -63,7 +63,7 @@ class HomeTabHeaderWidget extends StatelessWidget { border: Border.all(width: 1.0, color: const Color(0xFF140C10), style: BorderStyle.solid), ), child: Text( - UserUtil.getUser()?.name ?? '姓名丢了', + UserUtil.getUser()?.name ?? '未登录', style: TextStyle(color: const Color(0xFF333333), fontSize: 16.sp), ), ), diff --git a/lib/pages/login/forgetpwd/forget_password_home_page.dart b/lib/pages/login/forgetpwd/forget_password_home_page.dart index a3d80ef..a92c11b 100644 --- a/lib/pages/login/forgetpwd/forget_password_home_page.dart +++ b/lib/pages/login/forgetpwd/forget_password_home_page.dart @@ -39,7 +39,8 @@ class _ForgetPasswordHomePageView extends StatelessWidget { return; } // todo 后续需要改成在当前页面,验证过验证码后,再跳转到设置密码页面 - SetPassWordPage.push(context, SetPwdPageType.changePwd, phoneNum: phoneNum, smsCode: smsCode); + // change_passWord + SetPassWordPage.push(context, SetPwdPageType.resetPwd, phoneNum: phoneNum, smsCode: smsCode); } }, child: _buildForgetPwdView(), diff --git a/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart b/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart index c649bff..ede2b78 100644 --- a/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart +++ b/lib/pages/login/setpwd/bloc/set_pwd_bloc.dart @@ -131,12 +131,13 @@ class SetPwdBloc extends Bloc { try { await loading(() async { switch (pageType) { - case SetPwdPageType.changePwd: - await UserDao.changePassword(passwordText); - break; case SetPwdPageType.initPwd: await UserDao.initPassword(passwordText); break; + case SetPwdPageType.changePwd: + // 现在走同一个流程和接口 + /*await UserDao.changePassword(passwordText); + break;*/ case SetPwdPageType.resetPwd: if (phoneNumber == null || phoneNumber!.isEmpty) { throw ApiException(ApiException.customErrorCode, '手机号为空'); diff --git a/lib/pages/login/setpwd/set_pwd_page.dart b/lib/pages/login/setpwd/set_pwd_page.dart index 6c95065..34df466 100644 --- a/lib/pages/login/setpwd/set_pwd_page.dart +++ b/lib/pages/login/setpwd/set_pwd_page.dart @@ -15,7 +15,7 @@ enum SetPwdPageType { /// 忘记重设密码,必传手机号和验证码 resetPwd, - /// 修改密码 + /// 修改密码,必传手机号和验证码,现在和忘记密码走一样的流程 changePwd, } @@ -67,7 +67,7 @@ class _SetPassWordPageView extends StatelessWidget { } String _getTipsText() { - String text = ''; + String text = '接下来请设置一下您的新密码吧!'; switch (bloc.pageType) { case SetPwdPageType.initPwd: diff --git a/lib/pages/practice/topic_picture_page.dart b/lib/pages/practice/topic_picture_page.dart index 39910db..415767d 100644 --- a/lib/pages/practice/topic_picture_page.dart +++ b/lib/pages/practice/topic_picture_page.dart @@ -458,4 +458,4 @@ class _TopicPicturePage extends StatelessWidget { ], ); }); -} \ No newline at end of file +} diff --git a/lib/pages/user/information/user_information_bloc.dart b/lib/pages/user/information/user_information_bloc.dart new file mode 100644 index 0000000..1094019 --- /dev/null +++ b/lib/pages/user/information/user_information_bloc.dart @@ -0,0 +1,13 @@ +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'user_information_event.dart'; +part 'user_information_state.dart'; + +class UserInformationBloc extends Bloc { + UserInformationBloc() : super(UserInformationInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/user/information/user_information_event.dart b/lib/pages/user/information/user_information_event.dart new file mode 100644 index 0000000..05f8a67 --- /dev/null +++ b/lib/pages/user/information/user_information_event.dart @@ -0,0 +1,4 @@ +part of 'user_information_bloc.dart'; + +@immutable +abstract class UserInformationEvent {} diff --git a/lib/pages/user/information/user_information_page.dart b/lib/pages/user/information/user_information_page.dart new file mode 100644 index 0000000..0b8b447 --- /dev/null +++ b/lib/pages/user/information/user_information_page.dart @@ -0,0 +1,146 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/core/assets_const.dart'; +import 'package:wow_english/common/core/user_util.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; +import 'package:wow_english/models/user_entity.dart'; +import 'package:wow_english/utils/image_util.dart'; + +import 'user_information_bloc.dart'; + +class UserInformationPage extends StatelessWidget { + const UserInformationPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => UserInformationBloc(), + child: const _UserInformationView(), + ); + } +} + +class _UserInformationView extends StatelessWidget { + const _UserInformationView({super.key}); + + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) {}, + child: BlocBuilder(builder: (context, state) { + return const _UserInformationContentView(); + }), + ); + } +} + +class _UserInformationContentView extends StatelessWidget { + const _UserInformationContentView({super.key}); + + @override + Widget build(BuildContext context) { + UserEntity user = UserUtil.getUser()!; + return Scaffold( + backgroundColor: Colors.white, + appBar: const WEAppBar(titleText: "个人信息",), + body: SingleChildScrollView( + padding: EdgeInsets.only(left: 17.w, right: 17.w, top: 10.h, bottom: 22.h), + child: Column( + children: [ + buildContentRow( + '头像', + CircleAvatar( + radius: 22.5.r, + backgroundColor: Color(0xFF140C10), + child: CircleAvatar( + radius: 21.r, + backgroundImage: ImageUtil.getImageProviderOnDefault(user.avatarUrl), + ), + /*child: ClipOval( + child: OwImageWidget(name: user.avatarUrl ?? AssetsConst.wowLogo, fit: BoxFit.contain,), + )*/ + )), + 11.verticalSpace, + buildContentRow( + '名字', + Text( + user.name, + style: TextStyle( + fontWeight: FontWeight.w500, + color: const Color(0xFF333333), + fontSize: 21.sp, + ), + )), + 11.verticalSpace, + buildContentRow( + '年龄', + Text( + user.age.toString(), + style: TextStyle( + fontWeight: FontWeight.w500, + color: const Color(0xFF333333), + fontSize: 21.sp, + ), + )), + 11.verticalSpace, + buildContentRow( + '性别', + Text( + user.getGenderString(), + style: TextStyle( + fontWeight: FontWeight.w500, + color: const Color(0xFF333333), + fontSize: 21.sp, + ), + )), + 11.verticalSpace, + buildContentRow( + '账号', + Text( + user.phoneNum, + style: TextStyle( + fontWeight: FontWeight.w500, + color: const Color(0xFF999999), + fontSize: 21.sp, + ), + ), + isHideEndIcon: true, + ), + ], + ), + ), + ); + } + + Widget buildContentRow(String filedName, Widget contentWidget, {bool isHideEndIcon = false, Function()? onTap}) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: EdgeInsets.only(left: 16.w, right: 16.w, top: 18.h, bottom: 18.h), + decoration: BoxDecoration( + image: DecorationImage( + image: ImageUtil.getImageProviderOnDefault(AssetsConst.bgUserInformationText), fit: BoxFit.fill)), + child: Row(children: [ + Text( + filedName, + style: TextStyle( + fontWeight: FontWeight.w700, + color: const Color(0xFF999999), + fontSize: 21.sp, + ), + ), + 32.horizontalSpace, + Expanded( + child: Container( + alignment: Alignment.centerLeft, + child: contentWidget, + )), + Offstage( + offstage: isHideEndIcon, + child: Image.asset(AssetsConst.icNext, width: 20.w, height: 25.h), + ) + ]), + )); + } +} diff --git a/lib/pages/user/information/user_information_state.dart b/lib/pages/user/information/user_information_state.dart new file mode 100644 index 0000000..98389bf --- /dev/null +++ b/lib/pages/user/information/user_information_state.dart @@ -0,0 +1,6 @@ +part of 'user_information_bloc.dart'; + +@immutable +abstract class UserInformationState {} + +class UserInformationInitial extends UserInformationState {} diff --git a/lib/pages/user/user_page.dart b/lib/pages/user/user_page.dart index 431f626..4eac233 100644 --- a/lib/pages/user/user_page.dart +++ b/lib/pages/user/user_page.dart @@ -6,7 +6,6 @@ import 'package:wow_english/common/core/assets_const.dart'; import 'package:wow_english/common/core/user_util.dart'; import 'package:wow_english/common/widgets/we_app_bar.dart'; import 'package:wow_english/models/user_entity.dart'; -import 'package:wow_english/pages/login/setpwd/set_pwd_page.dart'; import 'package:wow_english/pages/user/bloc/user_bloc.dart'; import 'package:wow_english/route/route.dart'; import 'package:wow_english/utils/image_util.dart'; @@ -55,7 +54,7 @@ class _UserView extends StatelessWidget { ); return Scaffold( - backgroundColor: Colors.white, + //backgroundColor: Colors.white, appBar: const WEAppBar(), body: SingleChildScrollView( padding: EdgeInsets.only(left: 17.w, right: 17.w, top: 10.h, bottom: 22.h), @@ -130,13 +129,15 @@ class _UserView extends StatelessWidget { "修改个人信息>", style: textStyle21sp, ), - onPressed: () {}, + onPressed: () { + Navigator.of(AppRouter.context).pushNamed(AppRouteName.userInformation); + }, ) ], ), 30.verticalSpace, OutlinedButton( - onPressed: () => SetPassWordPage.push(context, SetPwdPageType.changePwd), + onPressed: () => Navigator.of(context).pushNamed(AppRouteName.fogPwd), style: normalButtonStyle, child: Text( "修改密码", diff --git a/lib/route/route.dart b/lib/route/route.dart index b95a971..db7bfa7 100644 --- a/lib/route/route.dart +++ b/lib/route/route.dart @@ -14,6 +14,7 @@ import 'package:wow_english/pages/shop/exchane/exchange_lesson_page.dart'; import 'package:wow_english/pages/shop/exchangelist/exchange_lesson_list_page.dart'; import 'package:wow_english/pages/shop/home/shop_home_page.dart'; import 'package:wow_english/pages/tab/tab_page.dart'; +import 'package:wow_english/pages/user/information/user_information_page.dart'; import 'package:wow_english/pages/user/user_page.dart'; import 'package:wow_english/pages/video/lookvideo/look_video_page.dart'; @@ -39,7 +40,12 @@ class AppRouteName { static const String voicePic = 'voicePic'; static const String voiceWord = 'voiceWord'; static const String voiceAnswer = 'voiceAnswer'; + + /// 用户个人主页 static const String user = 'user'; + + /// 用户详细信息页 + static const String userInformation = 'userInformation'; static const String lookVideo = 'lookVideo'; static const String reading = 'reading'; @@ -88,6 +94,8 @@ class AppRouter { return CupertinoPageRoute(builder: (_) => const RepeatAfterPage()); case AppRouteName.user: return CupertinoPageRoute(builder: (_) => const UserPage()); + case AppRouteName.userInformation: + return CupertinoPageRoute(builder: (_) => const UserInformationPage()); case AppRouteName.topicPic: return CupertinoPageRoute(builder: (_) => const TopicPicturePage()); case AppRouteName.lookVideo: -- libgit2 0.22.2