diff --git a/lib/pages/practice/bloc/topic_picture_bloc.dart b/lib/pages/practice/bloc/topic_picture_bloc.dart index 59d46d5..f422502 100644 --- a/lib/pages/practice/bloc/topic_picture_bloc.dart +++ b/lib/pages/practice/bloc/topic_picture_bloc.dart @@ -9,10 +9,14 @@ import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/common/request/dao/listen_dao.dart'; import 'package:wow_english/common/request/exception.dart'; import 'package:wow_english/models/course_process_entity.dart'; +import 'package:wow_english/pages/section/subsection/base_section/bloc.dart'; +import 'package:wow_english/pages/section/subsection/base_section/event.dart'; +import 'package:wow_english/pages/section/subsection/base_section/state.dart'; import 'package:wow_english/utils/loading.dart'; import 'package:wow_english/utils/toast_util.dart'; import '../../../common/permission/permissionRequestPage.dart'; +import '../../../route/route.dart'; part 'topic_picture_event.dart'; part 'topic_picture_state.dart'; @@ -28,7 +32,7 @@ enum VoicePlayState { stop } -class TopicPictureBloc extends Bloc { +class TopicPictureBloc extends BaseSectionBloc { final PageController pageController; @@ -94,11 +98,15 @@ class TopicPictureBloc extends Bloc { _forbiddenWhenCorrect = false; debugPrint('播放完成后解除禁止'); if (event == PlayerState.completed) { - // 答对后且播放完自动翻页 - pageController.nextPage( - duration: const Duration(milliseconds: 500), - curve: Curves.ease, - ); + if (isLastPage()) { + showStepPage(); + } else { + // 答对后且播放完自动翻页 + pageController.nextPage( + duration: const Duration(milliseconds: 500), + curve: Curves.ease, + ); + } } } } @@ -263,6 +271,9 @@ class TopicPictureBloc extends Bloc { showToast('测评成功,分数是$overall',duration: const Duration(seconds: 5)); _isVoicing = false; emitter(XSVoiceTestState()); + if (isLastPage()) { + showStepPage(); + } } // 暂时没用上 @@ -288,6 +299,7 @@ class TopicPictureBloc extends Bloc { } } + ///播放选择结果音效 void _playResultSound(bool isCorrect) async { // await audioPlayer.stop(); if (audioPlayer.state == PlayerState.playing && _isResultSoundPlaying == false) { @@ -302,4 +314,26 @@ class TopicPictureBloc extends Bloc { await audioPlayer.play(AssetSource('incorrect_voice'.assetMp3)); } } + + ///是否是最后一页 + bool isLastPage() { + return currentPage == _entity?.topics?.length; + } + + ///展示过渡页 + void showStepPage() { + ///如果最后一页是语音问答题,评测完后自动翻页 + sectionComplete(() { + popPage( + data:{ + 'currentStep':currentPage.toString(), + 'courseLessonId':courseLessonId, + 'isLastPage': true, + 'nextSection': true + }); + }, againSectionTap: () { + debugPrint("WQF 重做"); + pageController.jumpToPage(0); + }); + } } diff --git a/lib/pages/practice/bloc/topic_picture_event.dart b/lib/pages/practice/bloc/topic_picture_event.dart index 965fed5..4914c1b 100644 --- a/lib/pages/practice/bloc/topic_picture_event.dart +++ b/lib/pages/practice/bloc/topic_picture_event.dart @@ -1,7 +1,7 @@ part of 'topic_picture_bloc.dart'; @immutable -abstract class TopicPictureEvent {} +abstract class TopicPictureEvent extends BaseSectionEvent {} class InitBlocEvent extends TopicPictureEvent {} diff --git a/lib/pages/practice/bloc/topic_picture_state.dart b/lib/pages/practice/bloc/topic_picture_state.dart index 96d7381..d1d9b5d 100644 --- a/lib/pages/practice/bloc/topic_picture_state.dart +++ b/lib/pages/practice/bloc/topic_picture_state.dart @@ -1,7 +1,7 @@ part of 'topic_picture_bloc.dart'; @immutable -abstract class TopicPictureState {} +abstract class TopicPictureState extends BaseSectionState {} class TopicPictureInitial extends TopicPictureState {} diff --git a/lib/pages/practice/topic_picture_page.dart b/lib/pages/practice/topic_picture_page.dart index 2c0dc48..193a659 100644 --- a/lib/pages/practice/topic_picture_page.dart +++ b/lib/pages/practice/topic_picture_page.dart @@ -6,6 +6,7 @@ import 'package:wow_english/common/core/user_util.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_process_entity.dart'; +import 'package:wow_english/pages/practice/topic_type.dart'; import 'package:wow_english/route/route.dart'; import 'package:wow_english/utils/toast_util.dart'; @@ -71,7 +72,8 @@ class _TopicPicturePage extends StatelessWidget { popPage( data:{ 'currentStep':bloc.currentPage.toString(), - 'courseLessonId':bloc.courseLessonId + 'courseLessonId':bloc.courseLessonId, + 'isLastPage': bloc.isLastPage(), }); // Navigator.pop(context); }, @@ -86,13 +88,13 @@ class _TopicPicturePage extends StatelessWidget { }, itemBuilder: (BuildContext context,int index){ CourseProcessTopics? topics = bloc.entity?.topics![index]; - if (topics?.type == 1) {//听音选图 + if (topics?.type == TopicType.audioImageSelect.value) {//听音选图 return _pageViewVoicePictureItemWidget(topics); - } else if (topics?.type == 2) {//听音选字 + } else if (topics?.type == TopicType.audioCharSelect.value) {//听音选字 return _pageViewVoiceWordItemWidget(topics); - } else if (topics?.type == 3) {//看题选字 + } else if (topics?.type == TopicType.questionCharSelect.value) {//看题选字 return _pageViewWordItemWidget(topics); - } else if (topics?.type == 4) {//看题选图 + } else if (topics?.type == TopicType.questionImageSelect.value) {//看题选图 return _pageViewItemWidget(topics); } else {//语音问答 return _voiceAnswerItem(topics); diff --git a/lib/pages/practice/topic_type.dart b/lib/pages/practice/topic_type.dart new file mode 100644 index 0000000..91ac9ac --- /dev/null +++ b/lib/pages/practice/topic_type.dart @@ -0,0 +1,36 @@ +///练习(题型)类型 +enum TopicType { + ///听音选图 + audioImageSelect, + + ///听音选字 + audioCharSelect, + + ///看题选字 + questionCharSelect, + + ///看题选图 + questionImageSelect, + + ///语音问答 + voiceQuestion +} + +extension TopicTypeExtension on TopicType { + int get value { + switch (this) { + case TopicType.audioImageSelect: + return 1; + case TopicType.audioCharSelect: + return 2; + case TopicType.questionCharSelect: + return 3; + case TopicType.questionImageSelect: + return 4; + case TopicType.voiceQuestion: + return 5; + default: + throw ArgumentError('Unknown topic type'); + } + } +} diff --git a/lib/pages/section/bloc/section_bloc.dart b/lib/pages/section/bloc/section_bloc.dart index 01d47a4..13bdab5 100644 --- a/lib/pages/section/bloc/section_bloc.dart +++ b/lib/pages/section/bloc/section_bloc.dart @@ -46,19 +46,22 @@ class SectionBloc extends Bloc { CourseProcessEntity? get processEntity => _processEntity; - SectionBloc(this._courseUnitEntity, this._courseUnitDetail, this._pageController, this._listController) : super(LessonInitial()) { + SectionBloc(this._courseUnitEntity, this._courseUnitDetail, + this._pageController, this._listController) + : super(LessonInitial()) { on(_requestData); - on(_requestExitClass); on(_requestEndClass); on(_requestEnterClass); on(_requestVideoLesson); on(_pageControllerChange); } - void _requestData(RequestDataEvent event, Emitter emitter) async { + void _requestData( + RequestDataEvent event, Emitter emitter) async { try { await loading(() async { - _courseSectionDatas = await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!); + _courseSectionDatas = + await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!); emitter(LessonDataLoadState()); }); } catch (e) { @@ -68,68 +71,84 @@ class SectionBloc extends Bloc { } } - void _requestVideoLesson(RequestVideoLessonEvent event, Emitter emitter) async { + void _requestVideoLesson( + RequestVideoLessonEvent event, Emitter emitter) async { try { await loading(() async { _processEntity = await ListenDao.process(event.courseLessonId); - emitter(RequestVideoLessonState(event.courseLessonId,event.courseType)); + emitter( + RequestVideoLessonState(event.courseLessonId, event.courseType)); }); } catch (e) { if (e is ApiException) { - showToast(e.message??'请求失败,请检查网络连接'); + showToast(e.message ?? '请求失败,请检查网络连接'); } } } - - void _requestEnterClass(RequestEnterClassEvent event,Emitter emitter) async { + void _requestEnterClass( + RequestEnterClassEvent event, Emitter emitter) async { try { await loading(() async { - await ListenDao.enterClass(event.courseLessonId); - emitter(RequestEnterClassState(event.courseLessonId,event.courseType)); + await ListenDao.enterClass(event.courseLessonId); + emitter(RequestEnterClassState(event.courseLessonId, event.courseType)); }); } catch (e) { if (e is ApiException) { - showToast(e.message??'请求失败,请检查网络连接'); + showToast(e.message ?? '请求失败,请检查网络连接'); } } } - void _requestExitClass(RequestExitClassEvent event,Emitter emitter) async { - await ListenDao.exitClass(event.courseLessonId,event.currentStep); - } - - void _requestEndClass(RequestEndClassEvent event,Emitter emitter) async { - final obj = await ListenDao.endClass(event.courseLessonId,event.currentStep); + void _requestEndClass( + RequestEndClassEvent event, Emitter emitter) async { + if (event.isLastPage) { + await await ListenDao.endClass(event.courseLessonId, event.currentStep, + currentTime: event.currentTime); + } else { + await await ListenDao.exitClass(event.courseLessonId, event.currentStep, + currentTime: event.currentTime); + } + debugPrint("WQF _requestEndClass autoNextSection=${event.autoNextSection}"); if (event.autoNextSection) { - final nextCourseSection = getNextCourseSectionBySort(int.parse(event.courseLessonId)); + final nextCourseSection = + getNextCourseSectionBySort(int.parse(event.courseLessonId)); + debugPrint("WQF nextCourseSection = $nextCourseSection"); ///进入课堂 - add(RequestEnterClassEvent(nextCourseSection!.id.toString() ?? '', nextCourseSection.courseType)); + add(RequestEnterClassEvent(nextCourseSection!.id.toString(), + nextCourseSection.courseType)); } } - void _pageControllerChange(CurrentUnitIndexChangeEvent event, - Emitter emitter) async { + void _pageControllerChange( + CurrentUnitIndexChangeEvent event, Emitter emitter) async { _currentPage = event.unitIndex; emitter(CurrentPageIndexState()); } // 未锁定的页数 int unlockPageCount() { - return _courseUnitEntity.courseUnitVOList?.indexWhereOrNull((element) => element.lock == true) ?? 1; + return _courseUnitEntity.courseUnitVOList + ?.indexWhereOrNull((element) => element.lock == true) ?? + 1; } CourseSectionEntity? getNextCourseSectionBySort(int courseLessonId) { - final curCourseSectionEntity = _courseSectionDatas?.firstWhere((element) => element.id == courseLessonId); + final curCourseSectionEntity = _courseSectionDatas + ?.firstWhere((element) => element.id == courseLessonId); final curSort = curCourseSectionEntity?.sortOrder ?? 0; - CourseSectionEntity? nextCourseSectionEntity = _courseSectionDatas?.firstWhere((element) => element.sortOrder == curSort + 1); + CourseSectionEntity? nextCourseSectionEntity = _courseSectionDatas + ?.firstWhere((element) => element.sortOrder == curSort + 1); if (nextCourseSectionEntity != null) { return nextCourseSectionEntity; } else { ///跨unit选lesson - final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList?.firstWhere((element) => element.id == curCourseSectionEntity?.courseUnitId); + final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList + ?.firstWhere( + (element) => element.id == curCourseSectionEntity?.courseUnitId); if (curCourseUnitDetail != null) { - final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList?.firstWhere((element) => element.sortOrder == 0); + final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList + ?.firstWhere((element) => element.sortOrder == 0); if (nextCourseUnitDetail != null) { ///pageView翻页了,可能需要预加载 todo return null; diff --git a/lib/pages/section/bloc/section_event.dart b/lib/pages/section/bloc/section_event.dart index 0738d28..1936ae1 100644 --- a/lib/pages/section/bloc/section_event.dart +++ b/lib/pages/section/bloc/section_event.dart @@ -9,6 +9,7 @@ class RequestDataEvent extends SectionEvent {} class RequestVideoLessonEvent extends SectionEvent { final String courseLessonId; final int courseType; + RequestVideoLessonEvent(this.courseLessonId, this.courseType); } @@ -16,29 +17,29 @@ class RequestVideoLessonEvent extends SectionEvent { class RequestEnterClassEvent extends SectionEvent { final String courseLessonId; final int courseType; - RequestEnterClassEvent(this.courseLessonId,this.courseType); -} -///退出课堂 -class RequestExitClassEvent extends SectionEvent { - final String courseLessonId; - final String currentStep; - final String currentTime; - RequestExitClassEvent(this.courseLessonId,this.currentStep,this.currentTime); + RequestEnterClassEvent(this.courseLessonId, this.courseType); } ///结束课堂 class RequestEndClassEvent extends SectionEvent { final String courseLessonId; final String currentStep; - final String currentTime; + + ///是否是最后一页(决定调结束接口还是退出接口) + final bool isLastPage; + final int? currentTime; + ///自动进入下一环节 final bool autoNextSection; - RequestEndClassEvent(this.courseLessonId,this.currentStep,this.currentTime,{this.autoNextSection = false}); + + RequestEndClassEvent(this.courseLessonId, this.currentStep, this.isLastPage, + {this.currentTime, this.autoNextSection = false}); } ///页面切换 class CurrentUnitIndexChangeEvent extends SectionEvent { final int unitIndex; + CurrentUnitIndexChangeEvent(this.unitIndex); } diff --git a/lib/pages/section/section_page.dart b/lib/pages/section/section_page.dart index c267178..3c64fe8 100644 --- a/lib/pages/section/section_page.dart +++ b/lib/pages/section/section_page.dart @@ -76,8 +76,8 @@ class _SectionPageView extends StatelessWidget { }).then((value) { if (value != null) { Map dataMap = value as Map; - bloc.add(RequestEndClassEvent(dataMap['courseLessonId']!, '0', - dataMap['currentTime']!, autoNextSection: dataMap['nextSection'] as bool)); + bloc.add(RequestEndClassEvent(dataMap['courseLessonId']!, + dataMap['currentTime']!, true, autoNextSection: dataMap['nextSection'] as bool)); } }); return; @@ -99,9 +99,10 @@ class _SectionPageView extends StatelessWidget { arguments: {'courseLessonId': state.courseLessonId}) .then((value) { if (value != null) { - Map dataMap = value as Map; - bloc.add(RequestExitClassEvent( - dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); + Map dataMap = value as Map; + bloc.add(RequestEndClassEvent( + dataMap['courseLessonId']!, dataMap['currentStep']!, + dataMap['isLastPage']! as bool, autoNextSection: dataMap['nextSection'] as bool)); } }); return; @@ -113,9 +114,10 @@ class _SectionPageView extends StatelessWidget { arguments: {'courseLessonId': state.courseLessonId}) .then((value) { if (value != null) { - Map dataMap = value as Map; - bloc.add(RequestExitClassEvent( - dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); + Map dataMap = value as Map; + bloc.add(RequestEndClassEvent( + dataMap['courseLessonId']!, dataMap['currentStep']!, + dataMap['isLastPage']! as bool, autoNextSection: dataMap['nextSection'] as bool)); } }); return; diff --git a/lib/pages/section/subsection/base_section/bloc.dart b/lib/pages/section/subsection/base_section/bloc.dart index 40bb4fe..99bbba5 100644 --- a/lib/pages/section/subsection/base_section/bloc.dart +++ b/lib/pages/section/subsection/base_section/bloc.dart @@ -14,7 +14,7 @@ abstract class BaseSectionBloc