Commit 22f362320722bc706da82d9fd40629dde0345b76

Authored by 吴启风
1 parent aa0d2360

feat:过渡页-练习环节

lib/pages/practice/bloc/topic_picture_bloc.dart
@@ -9,10 +9,14 @@ import 'package:wow_english/common/extension/string_extension.dart'; @@ -9,10 +9,14 @@ import 'package:wow_english/common/extension/string_extension.dart';
9 import 'package:wow_english/common/request/dao/listen_dao.dart'; 9 import 'package:wow_english/common/request/dao/listen_dao.dart';
10 import 'package:wow_english/common/request/exception.dart'; 10 import 'package:wow_english/common/request/exception.dart';
11 import 'package:wow_english/models/course_process_entity.dart'; 11 import 'package:wow_english/models/course_process_entity.dart';
  12 +import 'package:wow_english/pages/section/subsection/base_section/bloc.dart';
  13 +import 'package:wow_english/pages/section/subsection/base_section/event.dart';
  14 +import 'package:wow_english/pages/section/subsection/base_section/state.dart';
12 import 'package:wow_english/utils/loading.dart'; 15 import 'package:wow_english/utils/loading.dart';
13 import 'package:wow_english/utils/toast_util.dart'; 16 import 'package:wow_english/utils/toast_util.dart';
14 17
15 import '../../../common/permission/permissionRequestPage.dart'; 18 import '../../../common/permission/permissionRequestPage.dart';
  19 +import '../../../route/route.dart';
16 20
17 part 'topic_picture_event.dart'; 21 part 'topic_picture_event.dart';
18 part 'topic_picture_state.dart'; 22 part 'topic_picture_state.dart';
@@ -28,7 +32,7 @@ enum VoicePlayState { @@ -28,7 +32,7 @@ enum VoicePlayState {
28 stop 32 stop
29 } 33 }
30 34
31 -class TopicPictureBloc extends Bloc<TopicPictureEvent, TopicPictureState> { 35 +class TopicPictureBloc extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> {
32 36
33 final PageController pageController; 37 final PageController pageController;
34 38
@@ -94,11 +98,15 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; { @@ -94,11 +98,15 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
94 _forbiddenWhenCorrect = false; 98 _forbiddenWhenCorrect = false;
95 debugPrint('播放完成后解除禁止'); 99 debugPrint('播放完成后解除禁止');
96 if (event == PlayerState.completed) { 100 if (event == PlayerState.completed) {
97 - // 答对后且播放完自动翻页  
98 - pageController.nextPage(  
99 - duration: const Duration(milliseconds: 500),  
100 - curve: Curves.ease,  
101 - ); 101 + if (isLastPage()) {
  102 + showStepPage();
  103 + } else {
  104 + // 答对后且播放完自动翻页
  105 + pageController.nextPage(
  106 + duration: const Duration(milliseconds: 500),
  107 + curve: Curves.ease,
  108 + );
  109 + }
102 } 110 }
103 } 111 }
104 } 112 }
@@ -263,6 +271,9 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; { @@ -263,6 +271,9 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
263 showToast('测评成功,分数是$overall',duration: const Duration(seconds: 5)); 271 showToast('测评成功,分数是$overall',duration: const Duration(seconds: 5));
264 _isVoicing = false; 272 _isVoicing = false;
265 emitter(XSVoiceTestState()); 273 emitter(XSVoiceTestState());
  274 + if (isLastPage()) {
  275 + showStepPage();
  276 + }
266 } 277 }
267 278
268 // 暂时没用上 279 // 暂时没用上
@@ -288,6 +299,7 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; { @@ -288,6 +299,7 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
288 } 299 }
289 } 300 }
290 301
  302 + ///播放选择结果音效
291 void _playResultSound(bool isCorrect) async { 303 void _playResultSound(bool isCorrect) async {
292 // await audioPlayer.stop(); 304 // await audioPlayer.stop();
293 if (audioPlayer.state == PlayerState.playing && _isResultSoundPlaying == false) { 305 if (audioPlayer.state == PlayerState.playing && _isResultSoundPlaying == false) {
@@ -302,4 +314,26 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; { @@ -302,4 +314,26 @@ class TopicPictureBloc extends Bloc&lt;TopicPictureEvent, TopicPictureState&gt; {
302 await audioPlayer.play(AssetSource('incorrect_voice'.assetMp3)); 314 await audioPlayer.play(AssetSource('incorrect_voice'.assetMp3));
303 } 315 }
304 } 316 }
  317 +
  318 + ///是否是最后一页
  319 + bool isLastPage() {
  320 + return currentPage == _entity?.topics?.length;
  321 + }
  322 +
  323 + ///展示过渡页
  324 + void showStepPage() {
  325 + ///如果最后一页是语音问答题,评测完后自动翻页
  326 + sectionComplete(() {
  327 + popPage(
  328 + data:{
  329 + 'currentStep':currentPage.toString(),
  330 + 'courseLessonId':courseLessonId,
  331 + 'isLastPage': true,
  332 + 'nextSection': true
  333 + });
  334 + }, againSectionTap: () {
  335 + debugPrint("WQF 重做");
  336 + pageController.jumpToPage(0);
  337 + });
  338 + }
305 } 339 }
lib/pages/practice/bloc/topic_picture_event.dart
1 part of 'topic_picture_bloc.dart'; 1 part of 'topic_picture_bloc.dart';
2 2
3 @immutable 3 @immutable
4 -abstract class TopicPictureEvent {} 4 +abstract class TopicPictureEvent extends BaseSectionEvent {}
5 5
6 class InitBlocEvent extends TopicPictureEvent {} 6 class InitBlocEvent extends TopicPictureEvent {}
7 7
lib/pages/practice/bloc/topic_picture_state.dart
1 part of 'topic_picture_bloc.dart'; 1 part of 'topic_picture_bloc.dart';
2 2
3 @immutable 3 @immutable
4 -abstract class TopicPictureState {} 4 +abstract class TopicPictureState extends BaseSectionState {}
5 5
6 class TopicPictureInitial extends TopicPictureState {} 6 class TopicPictureInitial extends TopicPictureState {}
7 7
lib/pages/practice/topic_picture_page.dart
@@ -6,6 +6,7 @@ import &#39;package:wow_english/common/core/user_util.dart&#39;; @@ -6,6 +6,7 @@ import &#39;package:wow_english/common/core/user_util.dart&#39;;
6 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/ow_image_widget.dart'; 7 import 'package:wow_english/common/widgets/ow_image_widget.dart';
8 import 'package:wow_english/models/course_process_entity.dart'; 8 import 'package:wow_english/models/course_process_entity.dart';
  9 +import 'package:wow_english/pages/practice/topic_type.dart';
9 import 'package:wow_english/route/route.dart'; 10 import 'package:wow_english/route/route.dart';
10 import 'package:wow_english/utils/toast_util.dart'; 11 import 'package:wow_english/utils/toast_util.dart';
11 12
@@ -71,7 +72,8 @@ class _TopicPicturePage extends StatelessWidget { @@ -71,7 +72,8 @@ class _TopicPicturePage extends StatelessWidget {
71 popPage( 72 popPage(
72 data:{ 73 data:{
73 'currentStep':bloc.currentPage.toString(), 74 'currentStep':bloc.currentPage.toString(),
74 - 'courseLessonId':bloc.courseLessonId 75 + 'courseLessonId':bloc.courseLessonId,
  76 + 'isLastPage': bloc.isLastPage(),
75 }); 77 });
76 // Navigator.pop(context); 78 // Navigator.pop(context);
77 }, 79 },
@@ -86,13 +88,13 @@ class _TopicPicturePage extends StatelessWidget { @@ -86,13 +88,13 @@ class _TopicPicturePage extends StatelessWidget {
86 }, 88 },
87 itemBuilder: (BuildContext context,int index){ 89 itemBuilder: (BuildContext context,int index){
88 CourseProcessTopics? topics = bloc.entity?.topics![index]; 90 CourseProcessTopics? topics = bloc.entity?.topics![index];
89 - if (topics?.type == 1) {//听音选图 91 + if (topics?.type == TopicType.audioImageSelect.value) {//听音选图
90 return _pageViewVoicePictureItemWidget(topics); 92 return _pageViewVoicePictureItemWidget(topics);
91 - } else if (topics?.type == 2) {//听音选字 93 + } else if (topics?.type == TopicType.audioCharSelect.value) {//听音选字
92 return _pageViewVoiceWordItemWidget(topics); 94 return _pageViewVoiceWordItemWidget(topics);
93 - } else if (topics?.type == 3) {//看题选字 95 + } else if (topics?.type == TopicType.questionCharSelect.value) {//看题选字
94 return _pageViewWordItemWidget(topics); 96 return _pageViewWordItemWidget(topics);
95 - } else if (topics?.type == 4) {//看题选图 97 + } else if (topics?.type == TopicType.questionImageSelect.value) {//看题选图
96 return _pageViewItemWidget(topics); 98 return _pageViewItemWidget(topics);
97 } else {//语音问答 99 } else {//语音问答
98 return _voiceAnswerItem(topics); 100 return _voiceAnswerItem(topics);
lib/pages/practice/topic_type.dart 0 → 100644
  1 +///练习(题型)类型
  2 +enum TopicType {
  3 + ///听音选图
  4 + audioImageSelect,
  5 +
  6 + ///听音选字
  7 + audioCharSelect,
  8 +
  9 + ///看题选字
  10 + questionCharSelect,
  11 +
  12 + ///看题选图
  13 + questionImageSelect,
  14 +
  15 + ///语音问答
  16 + voiceQuestion
  17 +}
  18 +
  19 +extension TopicTypeExtension on TopicType {
  20 + int get value {
  21 + switch (this) {
  22 + case TopicType.audioImageSelect:
  23 + return 1;
  24 + case TopicType.audioCharSelect:
  25 + return 2;
  26 + case TopicType.questionCharSelect:
  27 + return 3;
  28 + case TopicType.questionImageSelect:
  29 + return 4;
  30 + case TopicType.voiceQuestion:
  31 + return 5;
  32 + default:
  33 + throw ArgumentError('Unknown topic type');
  34 + }
  35 + }
  36 +}
lib/pages/section/bloc/section_bloc.dart
@@ -46,19 +46,22 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; { @@ -46,19 +46,22 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; {
46 46
47 CourseProcessEntity? get processEntity => _processEntity; 47 CourseProcessEntity? get processEntity => _processEntity;
48 48
49 - SectionBloc(this._courseUnitEntity, this._courseUnitDetail, this._pageController, this._listController) : super(LessonInitial()) { 49 + SectionBloc(this._courseUnitEntity, this._courseUnitDetail,
  50 + this._pageController, this._listController)
  51 + : super(LessonInitial()) {
50 on<RequestDataEvent>(_requestData); 52 on<RequestDataEvent>(_requestData);
51 - on<RequestExitClassEvent>(_requestExitClass);  
52 on<RequestEndClassEvent>(_requestEndClass); 53 on<RequestEndClassEvent>(_requestEndClass);
53 on<RequestEnterClassEvent>(_requestEnterClass); 54 on<RequestEnterClassEvent>(_requestEnterClass);
54 on<RequestVideoLessonEvent>(_requestVideoLesson); 55 on<RequestVideoLessonEvent>(_requestVideoLesson);
55 on<CurrentUnitIndexChangeEvent>(_pageControllerChange); 56 on<CurrentUnitIndexChangeEvent>(_pageControllerChange);
56 } 57 }
57 58
58 - void _requestData(RequestDataEvent event, Emitter<SectionState> emitter) async { 59 + void _requestData(
  60 + RequestDataEvent event, Emitter<SectionState> emitter) async {
59 try { 61 try {
60 await loading(() async { 62 await loading(() async {
61 - _courseSectionDatas = await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!); 63 + _courseSectionDatas =
  64 + await LessonDao.courseSection(courseUnitId: _courseUnitDetail.id!);
62 emitter(LessonDataLoadState()); 65 emitter(LessonDataLoadState());
63 }); 66 });
64 } catch (e) { 67 } catch (e) {
@@ -68,68 +71,84 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; { @@ -68,68 +71,84 @@ class SectionBloc extends Bloc&lt;SectionEvent, SectionState&gt; {
68 } 71 }
69 } 72 }
70 73
71 - void _requestVideoLesson(RequestVideoLessonEvent event, Emitter<SectionState> emitter) async { 74 + void _requestVideoLesson(
  75 + RequestVideoLessonEvent event, Emitter<SectionState> emitter) async {
72 try { 76 try {
73 await loading(() async { 77 await loading(() async {
74 _processEntity = await ListenDao.process(event.courseLessonId); 78 _processEntity = await ListenDao.process(event.courseLessonId);
75 - emitter(RequestVideoLessonState(event.courseLessonId,event.courseType)); 79 + emitter(
  80 + RequestVideoLessonState(event.courseLessonId, event.courseType));
76 }); 81 });
77 } catch (e) { 82 } catch (e) {
78 if (e is ApiException) { 83 if (e is ApiException) {
79 - showToast(e.message??'请求失败,请检查网络连接'); 84 + showToast(e.message ?? '请求失败,请检查网络连接');
80 } 85 }
81 } 86 }
82 } 87 }
83 88
84 -  
85 - void _requestEnterClass(RequestEnterClassEvent event,Emitter<SectionState> emitter) async { 89 + void _requestEnterClass(
  90 + RequestEnterClassEvent event, Emitter<SectionState> emitter) async {
86 try { 91 try {
87 await loading(() async { 92 await loading(() async {
88 - await ListenDao.enterClass(event.courseLessonId);  
89 - emitter(RequestEnterClassState(event.courseLessonId,event.courseType)); 93 + await ListenDao.enterClass(event.courseLessonId);
  94 + emitter(RequestEnterClassState(event.courseLessonId, event.courseType));
90 }); 95 });
91 } catch (e) { 96 } catch (e) {
92 if (e is ApiException) { 97 if (e is ApiException) {
93 - showToast(e.message??'请求失败,请检查网络连接'); 98 + showToast(e.message ?? '请求失败,请检查网络连接');
94 } 99 }
95 } 100 }
96 } 101 }
97 102
98 - void _requestExitClass(RequestExitClassEvent event,Emitter<SectionState> emitter) async {  
99 - await ListenDao.exitClass(event.courseLessonId,event.currentStep);  
100 - }  
101 -  
102 - void _requestEndClass(RequestEndClassEvent event,Emitter<SectionState> emitter) async {  
103 - final obj = await ListenDao.endClass(event.courseLessonId,event.currentStep); 103 + void _requestEndClass(
  104 + RequestEndClassEvent event, Emitter<SectionState> emitter) async {
  105 + if (event.isLastPage) {
  106 + await await ListenDao.endClass(event.courseLessonId, event.currentStep,
  107 + currentTime: event.currentTime);
  108 + } else {
  109 + await await ListenDao.exitClass(event.courseLessonId, event.currentStep,
  110 + currentTime: event.currentTime);
  111 + }
  112 + debugPrint("WQF _requestEndClass autoNextSection=${event.autoNextSection}");
104 if (event.autoNextSection) { 113 if (event.autoNextSection) {
105 - final nextCourseSection = getNextCourseSectionBySort(int.parse(event.courseLessonId)); 114 + final nextCourseSection =
  115 + getNextCourseSectionBySort(int.parse(event.courseLessonId));
  116 + debugPrint("WQF nextCourseSection = $nextCourseSection");
106 ///进入课堂 117 ///进入课堂
107 - add(RequestEnterClassEvent(nextCourseSection!.id.toString() ?? '', nextCourseSection.courseType)); 118 + add(RequestEnterClassEvent(nextCourseSection!.id.toString(),
  119 + nextCourseSection.courseType));
108 } 120 }
109 } 121 }
110 122
111 - void _pageControllerChange(CurrentUnitIndexChangeEvent event,  
112 - Emitter<SectionState> emitter) async { 123 + void _pageControllerChange(
  124 + CurrentUnitIndexChangeEvent event, Emitter<SectionState> emitter) async {
113 _currentPage = event.unitIndex; 125 _currentPage = event.unitIndex;
114 emitter(CurrentPageIndexState()); 126 emitter(CurrentPageIndexState());
115 } 127 }
116 128
117 // 未锁定的页数 129 // 未锁定的页数
118 int unlockPageCount() { 130 int unlockPageCount() {
119 - return _courseUnitEntity.courseUnitVOList?.indexWhereOrNull((element) => element.lock == true) ?? 1; 131 + return _courseUnitEntity.courseUnitVOList
  132 + ?.indexWhereOrNull((element) => element.lock == true) ??
  133 + 1;
120 } 134 }
121 135
122 CourseSectionEntity? getNextCourseSectionBySort(int courseLessonId) { 136 CourseSectionEntity? getNextCourseSectionBySort(int courseLessonId) {
123 - final curCourseSectionEntity = _courseSectionDatas?.firstWhere((element) => element.id == courseLessonId); 137 + final curCourseSectionEntity = _courseSectionDatas
  138 + ?.firstWhere((element) => element.id == courseLessonId);
124 final curSort = curCourseSectionEntity?.sortOrder ?? 0; 139 final curSort = curCourseSectionEntity?.sortOrder ?? 0;
125 - CourseSectionEntity? nextCourseSectionEntity = _courseSectionDatas?.firstWhere((element) => element.sortOrder == curSort + 1); 140 + CourseSectionEntity? nextCourseSectionEntity = _courseSectionDatas
  141 + ?.firstWhere((element) => element.sortOrder == curSort + 1);
126 if (nextCourseSectionEntity != null) { 142 if (nextCourseSectionEntity != null) {
127 return nextCourseSectionEntity; 143 return nextCourseSectionEntity;
128 } else { 144 } else {
129 ///跨unit选lesson 145 ///跨unit选lesson
130 - final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList?.firstWhere((element) => element.id == curCourseSectionEntity?.courseUnitId); 146 + final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList
  147 + ?.firstWhere(
  148 + (element) => element.id == curCourseSectionEntity?.courseUnitId);
131 if (curCourseUnitDetail != null) { 149 if (curCourseUnitDetail != null) {
132 - final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList?.firstWhere((element) => element.sortOrder == 0); 150 + final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList
  151 + ?.firstWhere((element) => element.sortOrder == 0);
133 if (nextCourseUnitDetail != null) { 152 if (nextCourseUnitDetail != null) {
134 ///pageView翻页了,可能需要预加载 todo 153 ///pageView翻页了,可能需要预加载 todo
135 return null; 154 return null;
lib/pages/section/bloc/section_event.dart
@@ -9,6 +9,7 @@ class RequestDataEvent extends SectionEvent {} @@ -9,6 +9,7 @@ class RequestDataEvent extends SectionEvent {}
9 class RequestVideoLessonEvent extends SectionEvent { 9 class RequestVideoLessonEvent extends SectionEvent {
10 final String courseLessonId; 10 final String courseLessonId;
11 final int courseType; 11 final int courseType;
  12 +
12 RequestVideoLessonEvent(this.courseLessonId, this.courseType); 13 RequestVideoLessonEvent(this.courseLessonId, this.courseType);
13 } 14 }
14 15
@@ -16,29 +17,29 @@ class RequestVideoLessonEvent extends SectionEvent { @@ -16,29 +17,29 @@ class RequestVideoLessonEvent extends SectionEvent {
16 class RequestEnterClassEvent extends SectionEvent { 17 class RequestEnterClassEvent extends SectionEvent {
17 final String courseLessonId; 18 final String courseLessonId;
18 final int courseType; 19 final int courseType;
19 - RequestEnterClassEvent(this.courseLessonId,this.courseType);  
20 -}  
21 20
22 -///退出课堂  
23 -class RequestExitClassEvent extends SectionEvent {  
24 - final String courseLessonId;  
25 - final String currentStep;  
26 - final String currentTime;  
27 - RequestExitClassEvent(this.courseLessonId,this.currentStep,this.currentTime); 21 + RequestEnterClassEvent(this.courseLessonId, this.courseType);
28 } 22 }
29 23
30 ///结束课堂 24 ///结束课堂
31 class RequestEndClassEvent extends SectionEvent { 25 class RequestEndClassEvent extends SectionEvent {
32 final String courseLessonId; 26 final String courseLessonId;
33 final String currentStep; 27 final String currentStep;
34 - final String currentTime; 28 +
  29 + ///是否是最后一页(决定调结束接口还是退出接口)
  30 + final bool isLastPage;
  31 + final int? currentTime;
  32 +
35 ///自动进入下一环节 33 ///自动进入下一环节
36 final bool autoNextSection; 34 final bool autoNextSection;
37 - RequestEndClassEvent(this.courseLessonId,this.currentStep,this.currentTime,{this.autoNextSection = false}); 35 +
  36 + RequestEndClassEvent(this.courseLessonId, this.currentStep, this.isLastPage,
  37 + {this.currentTime, this.autoNextSection = false});
38 } 38 }
39 39
40 ///页面切换 40 ///页面切换
41 class CurrentUnitIndexChangeEvent extends SectionEvent { 41 class CurrentUnitIndexChangeEvent extends SectionEvent {
42 final int unitIndex; 42 final int unitIndex;
  43 +
43 CurrentUnitIndexChangeEvent(this.unitIndex); 44 CurrentUnitIndexChangeEvent(this.unitIndex);
44 } 45 }
lib/pages/section/section_page.dart
@@ -76,8 +76,8 @@ class _SectionPageView extends StatelessWidget { @@ -76,8 +76,8 @@ class _SectionPageView extends StatelessWidget {
76 }).then((value) { 76 }).then((value) {
77 if (value != null) { 77 if (value != null) {
78 Map<String, dynamic> dataMap = value as Map<String, dynamic>; 78 Map<String, dynamic> dataMap = value as Map<String, dynamic>;
79 - bloc.add(RequestEndClassEvent(dataMap['courseLessonId']!, '0',  
80 - dataMap['currentTime']!, autoNextSection: dataMap['nextSection'] as bool)); 79 + bloc.add(RequestEndClassEvent(dataMap['courseLessonId']!,
  80 + dataMap['currentTime']!, true, autoNextSection: dataMap['nextSection'] as bool));
81 } 81 }
82 }); 82 });
83 return; 83 return;
@@ -99,9 +99,10 @@ class _SectionPageView extends StatelessWidget { @@ -99,9 +99,10 @@ class _SectionPageView extends StatelessWidget {
99 arguments: {'courseLessonId': state.courseLessonId}) 99 arguments: {'courseLessonId': state.courseLessonId})
100 .then((value) { 100 .then((value) {
101 if (value != null) { 101 if (value != null) {
102 - Map<String, String> dataMap = value as Map<String, String>;  
103 - bloc.add(RequestExitClassEvent(  
104 - dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); 102 + Map<String, dynamic> dataMap = value as Map<String, dynamic>;
  103 + bloc.add(RequestEndClassEvent(
  104 + dataMap['courseLessonId']!, dataMap['currentStep']!,
  105 + dataMap['isLastPage']! as bool, autoNextSection: dataMap['nextSection'] as bool));
105 } 106 }
106 }); 107 });
107 return; 108 return;
@@ -113,9 +114,10 @@ class _SectionPageView extends StatelessWidget { @@ -113,9 +114,10 @@ class _SectionPageView extends StatelessWidget {
113 arguments: {'courseLessonId': state.courseLessonId}) 114 arguments: {'courseLessonId': state.courseLessonId})
114 .then((value) { 115 .then((value) {
115 if (value != null) { 116 if (value != null) {
116 - Map<String, String> dataMap = value as Map<String, String>;  
117 - bloc.add(RequestExitClassEvent(  
118 - dataMap['courseLessonId']!, dataMap['currentStep']!, '0')); 117 + Map<String, dynamic> dataMap = value as Map<String, dynamic>;
  118 + bloc.add(RequestEndClassEvent(
  119 + dataMap['courseLessonId']!, dataMap['currentStep']!,
  120 + dataMap['isLastPage']! as bool, autoNextSection: dataMap['nextSection'] as bool));
119 } 121 }
120 }); 122 });
121 return; 123 return;
lib/pages/section/subsection/base_section/bloc.dart
@@ -14,7 +14,7 @@ abstract class BaseSectionBloc&lt;E extends BaseSectionEvent, @@ -14,7 +14,7 @@ abstract class BaseSectionBloc&lt;E extends BaseSectionEvent,
14 14
15 ///这里可以定义一些通用的逻辑 15 ///这里可以定义一些通用的逻辑
16 void sectionComplete(final VoidCallback? nextSectionTap, 16 void sectionComplete(final VoidCallback? nextSectionTap,
17 - {BuildContext? context}) { 17 + {VoidCallback? againSectionTap, BuildContext? context}) {
18 // 逻辑来标记步骤为已完成 18 // 逻辑来标记步骤为已完成
19 // 比如更新状态 19 // 比如更新状态
20 if (isCompleteDialogShow) { 20 if (isCompleteDialogShow) {
@@ -38,8 +38,8 @@ abstract class BaseSectionBloc&lt;E extends BaseSectionEvent, @@ -38,8 +38,8 @@ abstract class BaseSectionBloc&lt;E extends BaseSectionEvent,
38 flex: 1, 38 flex: 1,
39 child: GestureDetector( 39 child: GestureDetector(
40 onTap: () { 40 onTap: () {
41 - add(SectionAgainEvent() as E);  
42 popPage(); 41 popPage();
  42 + againSectionTap!();
43 }, 43 },
44 child: Image.asset('section_finish_again'.assetPng), 44 child: Image.asset('section_finish_again'.assetPng),
45 ), 45 ),