diff --git a/assets/images/back_study.png b/assets/images/back_study.png new file mode 100644 index 0000000..3b103ea --- /dev/null +++ b/assets/images/back_study.png diff --git a/assets/images/bacun.png b/assets/images/bacun.png new file mode 100644 index 0000000..a159dad --- /dev/null +++ b/assets/images/bacun.png diff --git a/assets/images/blue_positive.png b/assets/images/blue_positive.png new file mode 100755 index 0000000..0d22bd9 --- /dev/null +++ b/assets/images/blue_positive.png diff --git a/assets/images/bronze_positive.png b/assets/images/bronze_positive.png new file mode 100755 index 0000000..239575f --- /dev/null +++ b/assets/images/bronze_positive.png diff --git a/assets/images/green_positive.png b/assets/images/green_positive.png new file mode 100755 index 0000000..1bfce87 --- /dev/null +++ b/assets/images/green_positive.png diff --git a/assets/images/orange_positive.png b/assets/images/orange_positive.png new file mode 100755 index 0000000..41bf78b --- /dev/null +++ b/assets/images/orange_positive.png diff --git a/assets/images/photo_pause.png b/assets/images/photo_pause.png new file mode 100644 index 0000000..a339e26 --- /dev/null +++ b/assets/images/photo_pause.png diff --git a/assets/images/red_positive.png b/assets/images/red_positive.png new file mode 100755 index 0000000..e1ef3b9 --- /dev/null +++ b/assets/images/red_positive.png diff --git a/assets/images/silver_positive.png b/assets/images/silver_positive.png new file mode 100755 index 0000000..f3cbb51 --- /dev/null +++ b/assets/images/silver_positive.png diff --git a/assets/images/yellow_positive.png b/assets/images/yellow_positive.png new file mode 100755 index 0000000..b10c42a --- /dev/null +++ b/assets/images/yellow_positive.png diff --git a/lib/common/dialogs/customer_dialog.dart b/lib/common/dialogs/customer_dialog.dart index 8cb53cf..74324b4 100644 --- a/lib/common/dialogs/customer_dialog.dart +++ b/lib/common/dialogs/customer_dialog.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/route/route.dart'; class CustomerTwoActionDialog extends Dialog { const CustomerTwoActionDialog( @@ -25,7 +26,7 @@ class CustomerTwoActionDialog extends Dialog { child: ConstrainedBox( constraints: BoxConstraints( maxHeight: 208.h, - maxWidth: 247.w + maxWidth: 307.w ), child: Container( padding: EdgeInsets.symmetric(horizontal: 24.w,vertical: 15.h), diff --git a/lib/common/dialogs/show_dialog.dart b/lib/common/dialogs/show_dialog.dart index 8251d60..632c570 100644 --- a/lib/common/dialogs/show_dialog.dart +++ b/lib/common/dialogs/show_dialog.dart @@ -18,6 +18,7 @@ void showTwoActionDialog(String title, String leftTitle, String rightTitle, Stri {bool? barrierDismissible}) { showDialog( context: AppRouter.context, + barrierDismissible: barrierDismissible ?? true, builder: (BuildContext context) { return CustomerTwoActionDialog(title, leftTitle, rightTitle, content, leftTap, rightTap); }); diff --git a/lib/common/request/apis.dart b/lib/common/request/apis.dart index 6744c20..f994eab 100644 --- a/lib/common/request/apis.dart +++ b/lib/common/request/apis.dart @@ -49,30 +49,30 @@ class Apis { /// 磨耳朵 /// GET - static const String ears = '/course/grinding/ears'; + static const String ears = 'course/grinding/ears'; /// 视频跟读 /// GET - static const String followRead = '/course/video/follow/read'; + static const String followRead = 'course/video/follow/read'; /// 视频跟读内容 /// GET - static const String readContent = '/course/video/follow/read/content'; + static const String readContent = 'course/video/follow/read/content'; /// 视频跟读提交结果 /// POST - static const String followResult = '/course/submit/follow/result'; + static const String followResult = 'course/submit/follow/result'; /// 获取课程内容 /// GET - static const String process = '/course/process'; + static const String process = 'course/process'; /// 首页弹窗 /// get static const String homePopup = 'home/popup'; /// 兑换 - static const String exchange = '/exchange'; + static const String exchange = 'exchange'; /// 获取阿里云oss鉴权信息 static const String aliyunOssSts = 'oss/sts/upload'; diff --git a/lib/common/request/dao/listen_dao.dart b/lib/common/request/dao/listen_dao.dart index 88305ca..318f1d5 100644 --- a/lib/common/request/dao/listen_dao.dart +++ b/lib/common/request/dao/listen_dao.dart @@ -32,7 +32,7 @@ class ListenDao { ///视频跟读提交结果 static Future followResult(frequency,videoFollowReadId) async { - var data = await requestClient.post(Apis.followResult,data: {'frequency':frequency,'videoFollowReadId':videoFollowReadId}); + var data = await requestClient.post(Apis.followResult,data: {'frequency':frequency,'videoFollowReadContentId':videoFollowReadId}); return data; } diff --git a/lib/common/widgets/we_app_bar.dart b/lib/common/widgets/we_app_bar.dart index f28b685..95e9b76 100644 --- a/lib/common/widgets/we_app_bar.dart +++ b/lib/common/widgets/we_app_bar.dart @@ -35,7 +35,13 @@ class WEAppBar extends StatelessWidget implements PreferredSizeWidget { ), leading: leading ?? GestureDetector( - onTap: () => onBack??Navigator.pop(context), + onTap: () { + if (onBack == null) { + Navigator.pop(context); + } else { + onBack!(); + } + }, child: Container( alignment: Alignment.center, child: Image.asset( diff --git a/lib/generated/json/course_entity.g.dart b/lib/generated/json/course_entity.g.dart index 8ec0d62..1b95459 100644 --- a/lib/generated/json/course_entity.g.dart +++ b/lib/generated/json/course_entity.g.dart @@ -27,6 +27,10 @@ CourseEntity $CourseEntityFromJson(Map json) { if (courseModuleThemeColor != null) { courseEntity.courseModuleThemeColor = courseModuleThemeColor; } + final String? courseModuleCode = jsonConvert.convert(json['courseModuleCode']); + if (courseModuleCode != null) { + courseEntity.courseModuleCode = courseModuleCode; + } return courseEntity; } @@ -38,6 +42,7 @@ Map $CourseEntityToJson(CourseEntity entity) { data['nowCourseModuleName'] = entity.nowCourseModuleName; data['totalCourseLesson'] = entity.totalCourseLesson; data['courseModuleThemeColor'] = entity.courseModuleThemeColor; + data['courseModuleCode'] = entity.courseModuleCode; return data; } diff --git a/lib/models/course_entity.dart b/lib/models/course_entity.dart index a0b3be0..5fe33bd 100644 --- a/lib/models/course_entity.dart +++ b/lib/models/course_entity.dart @@ -10,6 +10,7 @@ class CourseEntity { String? nowCourseModuleName; int? totalCourseLesson; String? courseModuleThemeColor; + String? courseModuleCode; CourseEntity(); diff --git a/lib/pages/home/bloc/home_bloc.dart b/lib/pages/home/bloc/home_bloc.dart index aa31d7a..44e94f3 100644 --- a/lib/pages/home/bloc/home_bloc.dart +++ b/lib/pages/home/bloc/home_bloc.dart @@ -6,7 +6,6 @@ import 'package:wow_english/common/request/exception.dart'; import 'package:wow_english/models/course_entity.dart'; import 'package:wow_english/common/request/dao/listen_dao.dart'; import 'package:wow_english/models/course_process_entity.dart'; -// import 'package:wow_english/models/course_lesson_entity.dart'; import 'package:wow_english/utils/loading.dart'; import 'package:wow_english/utils/toast_util.dart'; diff --git a/lib/pages/home/courese_module_model.dart b/lib/pages/home/courese_module_model.dart new file mode 100644 index 0000000..fb3e36c --- /dev/null +++ b/lib/pages/home/courese_module_model.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; + +class CourseModuleModel { + Color get color => getCourseColor(); + String get courseModuleTitle => getCourseModuleTitle(); + String get courseModuleLogo => getCoureseImageName(); + + + String course; + + CourseModuleModel(this.course); + + Color getCourseColor() { + if (course == 'Phase-1') { + return Colors.yellow; + } + if (course == 'Phase-2') { + return Colors.red; + } + if (course == 'Phase-3') { + return Colors.blue; + } + if (course == 'Phase-4') { + return Colors.green; + } + if (course == 'Phase-5') { + return Colors.orange; + } + if (course == 'Phase-6') { + return const Color(0XFFC07347); + } + if (course == 'Phase-7') { + return const Color(0xFFA3A2A2); + } + return Colors.red; + } + + String getCourseModuleTitle() { + if (course == 'Phase-1') { + return 'learn wow! yellow'; + } + if (course == 'Phase-2') { + return 'learn wow! red'; + } + if (course == 'Phase-3') { + return 'learn wow! blue'; + } + if (course == 'Phase-4') { + return 'learn wow! green'; + } + if (course == 'Phase-5') { + return 'learn wow! orange'; + } + if (course == 'Phase-6') { + return 'learn wow! bronze'; + } + if (course == 'Phase-7') { + return 'learn wow! silver'; + } + return 'learn wow! red'; + } + + String getCoureseImageName() { + if (course == 'Phase-1') { + return 'yellow_positive'; + } + if (course == 'Phase-2') { + return 'red_positive'; + } + if (course == 'Phase-3') { + return 'blue_positive'; + } + if (course == 'Phase-4') { + return 'learn wow! green'; + } + if (course == 'Phase-5') { + return 'orange_positive'; + } + if (course == 'Phase-6') { + return 'bronze_positive'; + } + if (course == 'Phase-7') { + return 'silver_positive'; + } + return 'red_positive'; + } +} \ No newline at end of file diff --git a/lib/pages/home/home_page.dart b/lib/pages/home/home_page.dart index 3775ca0..7a1629a 100644 --- a/lib/pages/home/home_page.dart +++ b/lib/pages/home/home_page.dart @@ -8,10 +8,10 @@ import 'package:wow_english/pages/home/widgets/home_bouns_item.dart'; import 'package:wow_english/pages/home/widgets/home_tab_header_widget.dart'; import 'package:wow_english/pages/home/widgets/home_vidoe_item.dart'; import 'package:wow_english/route/route.dart'; -import 'package:wow_english/utils/color_util.dart'; import 'package:wow_english/utils/toast_util.dart'; import 'bloc/home_bloc.dart'; +import 'courese_module_model.dart'; class HomePage extends StatelessWidget { const HomePage({super.key, this.moduleId}); @@ -129,102 +129,103 @@ class _HomePageView extends StatelessWidget { ); } - Widget _homeView() => BlocBuilder(builder: (context, state) { - final bloc = BlocProvider.of(context); - return Scaffold( - body: Container( - color: Colors.white, - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - HomeTabHeaderWidget( - themColor: bloc.modelData?.courseModuleThemeColor, - actionTap: (HeaderActionType type) { - _headerActionEvent(type); - }, - ), - Expanded( - child: ListView.builder( - itemCount: bloc.modelData?.totalCourseLesson??0, - scrollDirection: Axis.horizontal, - itemBuilder: (BuildContext context, int index) { - CourseCourseLessons? data = bloc.modelData?.courseLessons?[index]; - if (data?.courseType == 5) { - //彩蛋 - return GestureDetector( - onTap: () { - if(UserUtil.token.isEmpty) { - pushNamed(AppRouteName.login); - return; - } - if (data!.lock!) { - showToast('当前课程暂未解锁'); - return; - } - ///进入课堂 - bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); - }, - child: HomeBoundsItem( - imageUrl: data?.coverUrl, + Widget _homeView() => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Scaffold( + body: Container( + color: Colors.white, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + HomeTabHeaderWidget( + entity: bloc.modelData, + actionTap: (HeaderActionType type) { + _headerActionEvent(type); + }, + ), + Expanded( + child: ListView.builder( + itemCount: bloc.modelData?.totalCourseLesson??0, + scrollDirection: Axis.horizontal, + itemBuilder: (BuildContext context, int index) { + CourseCourseLessons? data = bloc.modelData?.courseLessons?[index]; + if (data?.courseType == 5) { + //彩蛋 + return GestureDetector( + onTap: () { + if(UserUtil.token.isEmpty) { + pushNamed(AppRouteName.login); + return; + } + if (data!.lock!) { + showToast('当前课程暂未解锁'); + return; + } + ///进入课堂 + bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); + }, + child: HomeBoundsItem( + imageUrl: data?.coverUrl, + ), + ); + } else { + return GestureDetector( + onTap: () { + if(UserUtil.token.isEmpty) { + pushNamed(AppRouteName.login); + return; + } + if (data!.lock!) { + showToast('当前课程暂未解锁'); + return; + } + ///进入课堂 + bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); + }, + child: HomeVideoItem( + entity: bloc.modelData, + lessons: data, + ), + ); + } + })), + SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 13.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 47.h, + width: 80.w, + ), + Container( + decoration: BoxDecoration( + color: CourseModuleModel(bloc.modelData?.courseModuleCode??'Phase-1').color, + borderRadius: BorderRadius.circular(14.5.r), ), - ); - } else { - return GestureDetector( - onTap: () { - if(UserUtil.token.isEmpty) { - pushNamed(AppRouteName.login); - return; - } - if (data!.lock!) { - showToast('当前课程暂未解锁'); - return; - } - ///进入课堂 - bloc.add(RequestEnterClassEvent(data.id!,data.courseType!)); - }, - child: HomeVideoItem( - themColor: bloc.modelData?.courseModuleThemeColor, - lessons: data, + padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 24.w), + child: Text( + '${(bloc.modelData?.nowCourseLesson??0)}/${bloc.modelData?.totalCourseLesson??0}', + style: TextStyle(color: Colors.white, fontSize: 12.sp), ), - ); - } - })), - SafeArea( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 13.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SizedBox( - height: 47.h, - width: 80.w, - ), - Container( - decoration: BoxDecoration( - color: HexColor(bloc.modelData?.courseModuleThemeColor??''), - borderRadius: BorderRadius.circular(14.5.r), - ), - padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 24.w), - child: Text( - '${(bloc.modelData?.nowCourseLesson??0)}/${bloc.modelData?.totalCourseLesson??0}', - style: TextStyle(color: Colors.white, fontSize: 12.sp), - ), + ), + Image.asset( + CourseModuleModel(bloc.modelData?.courseModuleCode??'Phase-1').courseModuleLogo.assetPng, + height: 47.h, + width: 80.w, + // color: Colors.red, + ), + ], ), - Image.asset( - 'blue-positive'.assetPng, - height: 47.h, - width: 80.w, - // color: Colors.red, - ), - ], - ), - ), - ) - ], + ), + ) + ], + ), + ), ), - ), - ), - ); - }); + ); + }); } diff --git a/lib/pages/home/widgets/home_tab_header_widget.dart b/lib/pages/home/widgets/home_tab_header_widget.dart index f65798f..d732942 100644 --- a/lib/pages/home/widgets/home_tab_header_widget.dart +++ b/lib/pages/home/widgets/home_tab_header_widget.dart @@ -4,9 +4,11 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wow_english/common/core/user_util.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/pages/user/bloc/user_bloc.dart'; -import 'package:wow_english/utils/color_util.dart'; import 'package:wow_english/utils/image_util.dart'; +import '../../../models/course_entity.dart'; +import '../courese_module_model.dart'; + enum HeaderActionType { //视频跟读 video, @@ -21,9 +23,9 @@ enum HeaderActionType { } class HomeTabHeaderWidget extends StatelessWidget { - const HomeTabHeaderWidget({super.key, this.actionTap, this.themColor}); + const HomeTabHeaderWidget({super.key,this.entity, this.actionTap}); - final String? themColor; + final CourseEntity? entity; final Function(HeaderActionType type)? actionTap; @override @@ -33,7 +35,7 @@ class HomeTabHeaderWidget extends StatelessWidget { return Container( height: 45, width: double.infinity, - color: HexColor(themColor??''), + color: CourseModuleModel(entity?.courseModuleCode??'Phase-1').color, padding: EdgeInsets.symmetric(horizontal: 9.5.w), child: Row( children: [ @@ -75,11 +77,11 @@ class HomeTabHeaderWidget extends StatelessWidget { ), ), 20.horizontalSpace, - const Expanded( + Expanded( child: Text( - 'learn wow', + CourseModuleModel(entity?.courseModuleCode??'Phase-1').courseModuleTitle, textAlign: TextAlign.left, - style: TextStyle(color: Colors.white, fontSize: 30.0), + style: const TextStyle(color: Colors.white, fontSize: 30.0), )), IconButton( onPressed: () { diff --git a/lib/pages/home/widgets/home_vidoe_item.dart b/lib/pages/home/widgets/home_vidoe_item.dart index 10769d1..e502104 100644 --- a/lib/pages/home/widgets/home_vidoe_item.dart +++ b/lib/pages/home/widgets/home_vidoe_item.dart @@ -3,12 +3,13 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/common/widgets/ow_image_widget.dart'; import 'package:wow_english/models/course_entity.dart'; -import 'package:wow_english/utils/color_util.dart'; + +import '../courese_module_model.dart'; class HomeVideoItem extends StatelessWidget { - const HomeVideoItem({super.key, this.lessons, this.themColor}); + const HomeVideoItem({super.key, this.lessons, this.entity}); - final String? themColor; + final CourseEntity? entity; final CourseCourseLessons? lessons; @override @@ -20,8 +21,8 @@ class HomeVideoItem extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 24.h), decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('gendubeij'.assetPng), - fit: BoxFit.fill + image: AssetImage('gendubeij'.assetPng), + fit: BoxFit.fill ), ), child: Column( @@ -40,7 +41,8 @@ class HomeVideoItem extends StatelessWidget { name: lessons?.coverUrl??'', fit: BoxFit.fitHeight, ), - )), + ) + ), 24.verticalSpace, Container( decoration: BoxDecoration( @@ -48,7 +50,7 @@ class HomeVideoItem extends StatelessWidget { width: 2, color: const Color(0xFF140C10), ), - color: HexColor(themColor??''), + color: CourseModuleModel(entity?.courseModuleCode??'Phase-1').color, borderRadius: BorderRadius.circular(6) ), padding: EdgeInsets.symmetric(horizontal: 10.w), diff --git a/lib/pages/lessons/widgets/lesson_item_widget.dart b/lib/pages/lessons/widgets/lesson_item_widget.dart index 640cca6..774427f 100644 --- a/lib/pages/lessons/widgets/lesson_item_widget.dart +++ b/lib/pages/lessons/widgets/lesson_item_widget.dart @@ -5,6 +5,8 @@ import 'package:wow_english/common/widgets/ow_image_widget.dart'; import 'package:wow_english/models/course_module_entity.dart'; import 'package:wow_english/utils/color_util.dart'; +import '../../home/courese_module_model.dart'; + class LessonItemWidget extends StatelessWidget { const LessonItemWidget({super.key, required this.isSelected, this.model, this.onClickEvent}); ///是否被选中 @@ -61,7 +63,7 @@ class LessonItemWidget extends StatelessWidget { 10.verticalSpace, Container( decoration: BoxDecoration( - color: HexColor(model?.courseModuleThemeColor??'#FFC0C3E7'), + color: CourseModuleModel(model?.code??'Phase-1').color, borderRadius: BorderRadius.circular(6.r), border: Border.all( color: const Color(0xFF333333), diff --git a/lib/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart b/lib/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart index 752b5a1..c1fe85a 100644 --- a/lib/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart +++ b/lib/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart @@ -171,10 +171,11 @@ class RepeatAfterContentBloc extends Bloc emitter) async { try { - await ListenDao.followResult(_recordNumber.toString(),courseLessonId); + ReadContentEntity entity = _entityList![_currentPlayIndex]!; + await ListenDao.followResult(_recordNumber.toString(),entity.id); } catch (e) { if (e is ApiException) { diff --git a/lib/pages/repeataftercontent/repeat_after_content_page.dart b/lib/pages/repeataftercontent/repeat_after_content_page.dart index a425a76..0108d61 100644 --- a/lib/pages/repeataftercontent/repeat_after_content_page.dart +++ b/lib/pages/repeataftercontent/repeat_after_content_page.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart'; +import 'package:wow_english/pages/repeataftercontent/widgets/repeat_after_content_dialog.dart'; import 'package:wow_english/route/route.dart'; import '../../common/core/app_consts.dart'; @@ -64,7 +65,16 @@ class _RepeatAfterContentPage extends StatelessWidget { ///返回 Positioned( child: GestureDetector( - onTap: () => popPage(), + onTap: () { + showDialog( + context: context, + builder: (context){ + return RepeatAfterContentDialog( (){ + popPage(); + }); + }); + // popPage(); + }, child: Image.asset( 'back_around'.assetPng, height: 40.h, @@ -326,11 +336,11 @@ class _RepeatAfterContentPage extends StatelessWidget { child: Container( color: Colors.grey, padding: EdgeInsets.symmetric( - vertical: 50.h, - horizontal: 50.w + vertical: 50.h, + horizontal: 50.w ), child: Text( - bloc.voiceRecordState == VoiceRecordState.voiceRecording?'正在录音':'录音结束' + bloc.voiceRecordState == VoiceRecordState.voiceRecording?'正在录音':'录音结束' ), ), ), diff --git a/lib/pages/repeataftercontent/widgets/repeat_after_content_dialog.dart b/lib/pages/repeataftercontent/widgets/repeat_after_content_dialog.dart new file mode 100644 index 0000000..d0e87d7 --- /dev/null +++ b/lib/pages/repeataftercontent/widgets/repeat_after_content_dialog.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/route/route.dart'; + +class RepeatAfterContentDialog extends Dialog { + const RepeatAfterContentDialog(this.onLeftTap, {super.key}); + final Function() onLeftTap; + @override + Widget build(BuildContext context) { + super.build(context); + return Center( + child: Column( + children: [ + 20.verticalSpace, + Image.asset( + 'photo_pause'.assetPng, + height: 202.h, + width: 321.w, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + popPage(); + onLeftTap(); + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image:AssetImage('bacun'.assetPng) + ) + ), + height: 44.h, + width: 137.w, + alignment: Alignment.center, + child: Text( + '保存并退出', + textAlign: TextAlign.center, + style: TextStyle( + color: const Color(0xFF333333), + fontSize: 17.sp + ), + ), + ), + ), + 33.horizontalSpace, + GestureDetector( + onTap: () { + popPage(); + }, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image:AssetImage('back_study'.assetPng) + ) + ), + height: 44.h, + width: 137.w, + alignment: Alignment.center, + child: Text( + '返回继续学习', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 17.sp + ), + ), + ), + ) + ], + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/user/information/user_information_page.dart b/lib/pages/user/information/user_information_page.dart index cbce0c7..1130638 100644 --- a/lib/pages/user/information/user_information_page.dart +++ b/lib/pages/user/information/user_information_page.dart @@ -72,7 +72,7 @@ class _UserInformationContentView extends StatelessWidget { _buildContentRow( '年龄', Text( - user.age.toString(), + (user.age??0).toString(), style: TextStyle( fontWeight: FontWeight.w500, color: const Color(0xFF333333), diff --git a/lib/pages/user/modify/modify_user_information_page.dart b/lib/pages/user/modify/modify_user_information_page.dart index 599e3d8..f2924fc 100644 --- a/lib/pages/user/modify/modify_user_information_page.dart +++ b/lib/pages/user/modify/modify_user_information_page.dart @@ -5,6 +5,7 @@ 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/dialogs/show_dialog.dart'; import 'package:wow_english/common/widgets/textfield_customer_widget.dart'; import 'package:wow_english/common/widgets/we_app_bar.dart'; import 'package:wow_english/pages/user/bloc/user_bloc.dart'; @@ -53,86 +54,100 @@ class ModifyUserInformationPage extends StatelessWidget { } }) ], - child: Scaffold( - backgroundColor: Colors.white, - appBar: WEAppBar( - titleText: '修改${type.title}', - ), - body: BlocBuilder( - builder: (context, state) { - final bloc = BlocProvider.of(context); - return SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(left: 65.w, right: 55.w, top: 38.h), - child: Row( - children: [ - Text( - type.title, - style: TextStyle( - fontWeight: FontWeight.w700, - color: const Color(0xFF333333), - fontSize: 21.sp, - ), - ), - 20.horizontalSpace, - // 输入框 or 选择框 - _buildTextFieldWidget(context), - // 占位 - Expanded( - child: Container(), + child: BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Scaffold( + backgroundColor: Colors.white, + appBar: WEAppBar( + titleText: '修改${type.title}', + onBack: () { + final bloc = BlocProvider.of(context); + if (bloc.isChangeInfo) { + showTwoActionDialog('提示', '确定离开', '继续修改', '您的信息尚未保存', () { + popPage(); + popPage(); + }, () { + popPage(); + }); + } else { + popPage(); + } + }, + ), + body: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: EdgeInsets.only(left: 65.w, right: 55.w, top: 38.h), + child: Row( + children: [ + Text( + type.title, + style: TextStyle( + fontWeight: FontWeight.w700, + color: const Color(0xFF333333), + fontSize: 21.sp, ), - // 按钮 - GestureDetector( - onTap: () { - var text = ''; - if (type == ModifyUserInformationType.name || type == ModifyUserInformationType.age){ - if(bloc.modifyTextController.text.isEmpty) { - showToast('内容不能为空'); - return; - } - text = bloc.modifyTextController.text; + ), + 20.horizontalSpace, + // 输入框 or 选择框 + _buildTextFieldWidget(context), + // 占位 + Expanded( + child: Container(), + ), + // 按钮 + GestureDetector( + onTap: () { + var text = ''; + if (type == ModifyUserInformationType.name || type == ModifyUserInformationType.age){ + if(bloc.modifyTextController.text.isEmpty) { + showToast('内容不能为空'); + return; } + text = bloc.modifyTextController.text; + } - if (type == ModifyUserInformationType.gender) { - text = bloc.gender.toString(); - } - // 更新type类型的字段 - context.read().add(UserUpdate(type,text)); - }, - child: Container( - alignment: Alignment.center, - width: 90.w, - height: 44.h, - decoration: const BoxDecoration( - image: DecorationImage(image: AssetImage(AssetsConst.bgButtonBlue), fit: BoxFit.fill), - ), - child: Text( - '确定', - style: TextStyle(fontSize: 17.sp, color: Colors.white), - ), + if (type == ModifyUserInformationType.gender) { + text = bloc.gender.toString(); + } + // 更新type类型的字段 + context.read().add(UserUpdate(type,text)); + }, + child: Container( + alignment: Alignment.center, + width: 90.w, + height: 44.h, + decoration: const BoxDecoration( + image: DecorationImage(image: AssetImage(AssetsConst.bgButtonBlue), fit: BoxFit.fill), + ), + child: Text( + '确定', + style: TextStyle(fontSize: 17.sp, color: Colors.white), ), - ) - ], - )), - Stack( - alignment: Alignment.topRight, - children: [ - Image.asset( - AssetsConst.bgEditUserInformation, - width: double.infinity, - ), - Positioned( - right: 125.w, - top: 10.h, - child: Image.asset(AssetsConst.bgIcSteveWrite, width: 161.w, height: 249.w), - ), - ], - ), - ], - )); - }), + ), + ) + ], + )), + Stack( + alignment: Alignment.topRight, + children: [ + Image.asset( + AssetsConst.bgEditUserInformation, + width: double.infinity, + ), + Positioned( + right: 125.w, + top: 10.h, + child: Image.asset(AssetsConst.bgIcSteveWrite, width: 161.w, height: 249.w), + ), + ], + ), + ], + )), + ); + }, ), ), ); @@ -188,9 +203,9 @@ class ModifyUserInformationPage extends StatelessWidget { textInputType: inputType, inputFormatters: formatters, controller: bloc.modifyTextController, - /*onChangeValue: (String value) { - bloc.add(CodeNumberChangeEvent()); - },*/ + onChangeValue: (String value) { + bloc.add(ChangeTextFieldEvent(value)); + }, ); }); } diff --git a/lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart b/lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart index 24e03b0..2522882 100644 --- a/lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart +++ b/lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:wow_english/common/core/assets_const.dart'; @@ -38,10 +39,9 @@ class UserAvatarBloc extends Bloc { Future _uploadAvatar(String imagePath) async { // todo 加个loading UI + EasyLoading.showToast(''); String avatarUrl = await AliyunOssUtil.uploadFile(imagePath); - debugPrint('>>>>>>>>>>阿里云图片地址$avatarUrl'); - // 上传服务器 - // await UserDao.updateUserInfoField(avatarUrl: avatarUrl); + EasyLoading.dismiss(); return avatarUrl; } diff --git a/lib/pages/user/modify/user_info_bloc/user_info_bloc.dart b/lib/pages/user/modify/user_info_bloc/user_info_bloc.dart index 2427120..e834f91 100644 --- a/lib/pages/user/modify/user_info_bloc/user_info_bloc.dart +++ b/lib/pages/user/modify/user_info_bloc/user_info_bloc.dart @@ -12,17 +12,28 @@ class UserInfoBloc extends Bloc { int get gender => _gender; + String _primitiveText = ''; + + bool isChangeInfo = false; + UserInfoBloc() : super(UserInfoInitial()) { on(_changeGender); + on(_changeTextField); on(_initControllerText); } - _initControllerText(InitControllerTextEvent event,Emitter emitter) async { + void _initControllerText(InitControllerTextEvent event,Emitter emitter) async { modifyTextController.text = event.text; + _primitiveText = event.text; } - _changeGender(ChangeGenderEvent event,Emitter emitter) async { + void _changeGender(ChangeGenderEvent event,Emitter emitter) async { _gender = event.gender; + isChangeInfo = _gender != (UserUtil.getUser()!.gender??0); emitter(ChangeGenderState()); } + + void _changeTextField(ChangeTextFieldEvent event,Emitter emitter) async { + isChangeInfo = _primitiveText != event.text; + } } diff --git a/lib/pages/user/modify/user_info_bloc/user_info_event.dart b/lib/pages/user/modify/user_info_bloc/user_info_event.dart index 92c3ebe..66e57e0 100644 --- a/lib/pages/user/modify/user_info_bloc/user_info_event.dart +++ b/lib/pages/user/modify/user_info_bloc/user_info_event.dart @@ -8,6 +8,11 @@ class InitControllerTextEvent extends UserInfoEvent { InitControllerTextEvent(this.text); } +class ChangeTextFieldEvent extends UserInfoEvent { + final String text; + ChangeTextFieldEvent(this.text); +} + class ChangeGenderEvent extends UserInfoEvent { final int gender; ChangeGenderEvent(this.gender); diff --git a/lib/pages/user/user_page.dart b/lib/pages/user/user_page.dart index 6ca22e8..c6e14f7 100644 --- a/lib/pages/user/user_page.dart +++ b/lib/pages/user/user_page.dart @@ -29,9 +29,6 @@ class _UserView extends StatelessWidget { } Widget _pageWidget() => BlocBuilder( - /*buildWhen: (previous, current) { - return current != previous; - },*/ builder: (context, state) { UserEntity user = UserUtil.getUser()!; final userBloc = BlocProvider.of(context); @@ -177,13 +174,20 @@ class _UserView extends StatelessWidget { )), 30.verticalSpace, OutlinedButton( - onPressed: () => userBloc.add(UserLogout()), + onPressed: () { + showTwoActionDialog(barrierDismissible:false,'提示', '取消', '确认', '您确认要退出Wow English吗?', () { + popPage(); + }, () { + popPage(); + userBloc.add(UserLogout()); + }); + }, style: ButtonStyle( side: MaterialStateProperty.all(const BorderSide(color: Color(0xFF140C10), width: 1.5)), shape: MaterialStateProperty.all( RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))), minimumSize: MaterialStateProperty.all(Size(295.w, 40.h)), - backgroundColor: MaterialStateProperty.all(Color(0xFFFBB621)), + backgroundColor: MaterialStateProperty.all(const Color(0xFFFBB621)), ), child: Text( "退出登录", diff --git a/lib/utils/aliyun_oss_util.dart b/lib/utils/aliyun_oss_util.dart index 6082d77..727b394 100644 --- a/lib/utils/aliyun_oss_util.dart +++ b/lib/utils/aliyun_oss_util.dart @@ -27,7 +27,7 @@ class AliyunOssUtil { ); // 上传文件 - final Response resp = await Client().putObjectFile( + await Client().putObjectFile( filePath, fileKey: stsEntity.fileKey, option: PutRequestOption( diff --git a/pubspec.yaml b/pubspec.yaml index aeb3d00..624ca21 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -88,7 +88,7 @@ dependencies: # 富文本插件 https://pub.dev/packages/extended_text extended_text: ^11.0.1 # 视频播放 https://pub.dev/packages/video_player - video_player: ^2.6.1 + video_player: ^2.7.0 # UI适配 https://pub.dev/packages/responsive_framework responsive_framework: ^1.0.0 # 音频播放 https://pub.dev/packages/audioplayers