Commit 009cf00df190ae47e21695b202bb86ee682ba403
1 parent
8df5fbf9
feat:环节&单元解锁逻辑
Showing
5 changed files
with
126 additions
and
28 deletions
.gitignore
@@ -68,6 +68,7 @@ | @@ -68,6 +68,7 @@ | ||
68 | **/ios/xcode_build_ipa_adh | 68 | **/ios/xcode_build_ipa_adh |
69 | **/ios/xcode_build_ipa_aps | 69 | **/ios/xcode_build_ipa_aps |
70 | **/ios/xcode_build_ipa_dev | 70 | **/ios/xcode_build_ipa_dev |
71 | +**/ios/build/ | ||
71 | 72 | ||
72 | # Exceptions to above rules. | 73 | # Exceptions to above rules. |
73 | !**/ios/**/default.mode1v3 | 74 | !**/ios/**/default.mode1v3 |
lib/pages/section/bloc/section_bloc.dart
@@ -200,7 +200,7 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -200,7 +200,7 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
200 | final curCourseSectionEntity = findCourseSectionById(courseLessonId); | 200 | final curCourseSectionEntity = findCourseSectionById(courseLessonId); |
201 | if (curCourseSectionEntity != null) { | 201 | if (curCourseSectionEntity != null) { |
202 | final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList | 202 | final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList |
203 | - ?.firstWhere( | 203 | + ?.firstWhereOrNull( |
204 | (element) => element.id == curCourseSectionEntity.courseUnitId); | 204 | (element) => element.id == curCourseSectionEntity.courseUnitId); |
205 | return curCourseUnitDetail; | 205 | return curCourseUnitDetail; |
206 | } | 206 | } |
@@ -213,39 +213,86 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -213,39 +213,86 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
213 | final curCourseSectionEntity = findCourseSectionById(courseLessonId); | 213 | final curCourseSectionEntity = findCourseSectionById(courseLessonId); |
214 | final curSectionSort = curCourseSectionEntity?.sortOrder ?? 0; | 214 | final curSectionSort = curCourseSectionEntity?.sortOrder ?? 0; |
215 | 215 | ||
216 | - ///查找下一个section | ||
217 | - final nextCourseSectionEntity = findCourseSectionBySort(curSectionSort + 1); | ||
218 | - if (nextCourseSectionEntity != null) { | ||
219 | - return nextCourseSectionEntity; | 216 | + try { |
217 | + ///查找当前unit的下一个section | ||
218 | + CourseSectionEntity? nextCourseSectionEntity = | ||
219 | + findCourseSectionBySort(curSectionSort + 1); | ||
220 | + return checkCourseSectionLocked(courseLessonId, nextCourseSectionEntity, emitter); | ||
221 | + } catch (e) { | ||
222 | + if (e is ApiException) { | ||
223 | + showToast(e.message.toString()); | ||
224 | + } | ||
225 | + return null; | ||
226 | + } | ||
227 | + } | ||
228 | + | ||
229 | + ///检查section是否锁定 | ||
230 | + Future<CourseSectionEntity?> checkCourseSectionLocked(int courseLessonId, CourseSectionEntity? courseSectionEntity, | ||
231 | + Emitter<SectionState> emitter) async { | ||
232 | + if (courseSectionEntity != null) { | ||
233 | + if (courseSectionEntity.lock == false) { | ||
234 | + ///如果section没锁,直接返回 | ||
235 | + return courseSectionEntity; | ||
236 | + } else { | ||
237 | + ///如果section锁了,请求当前unit下的section数据,查询解锁状态 | ||
238 | + int courseUnitId = courseSectionEntity.courseUnitId; | ||
239 | + await loading(() async { | ||
240 | + List<CourseSectionEntity>? tempSectionEntities = | ||
241 | + await LessonDao.courseSection(courseUnitId: courseUnitId); | ||
242 | + if (tempSectionEntities != null) { | ||
243 | + _courseSectionDatasMap[courseUnitId] = tempSectionEntities; | ||
244 | + emitter(LessonDataLoadState()); | ||
245 | + } | ||
246 | + courseSectionEntity = tempSectionEntities?.firstWhereOrNull( | ||
247 | + (element) => element.id == courseSectionEntity?.id); | ||
248 | + if (courseSectionEntity?.lock == false) { | ||
249 | + ///刷新后的数据如果解锁了,直接返回 | ||
250 | + return courseSectionEntity; | ||
251 | + } else { | ||
252 | + ///请求失败或者锁定状态没变(没变就感觉状态异常了,理论上不应该进入这条分支),返回null | ||
253 | + showToast('下个课程还没解锁哦'); | ||
254 | + return null; | ||
255 | + } | ||
256 | + }); | ||
257 | + } | ||
220 | } else { | 258 | } else { |
221 | - ///section为空说明当前unit学完了,找下一个unit。(跨unit选lesson) | 259 | + ///section为空说明当前unit学完了,找下一个unit。(跨unit选section) |
222 | ///先根据courseLessonId找出当前的unit | 260 | ///先根据courseLessonId找出当前的unit |
223 | final curCourseUnitDetail = findCourseUnitDetailById(courseLessonId); | 261 | final curCourseUnitDetail = findCourseUnitDetailById(courseLessonId); |
224 | if (curCourseUnitDetail != null) { | 262 | if (curCourseUnitDetail != null) { |
225 | - ///再根据当前unit找出下一个unit | ||
226 | - final nextCourseUnitDetail = _courseUnitEntity.courseUnitVOList | ||
227 | - ?.firstWhere((element) => | ||
228 | - element.sortOrder == (curCourseUnitDetail.sortOrder! + 1)); | 263 | + ///再根据当前unit的sortOrder找出下一个unit |
264 | + CourseUnitDetail? nextCourseUnitDetail = | ||
265 | + _courseUnitEntity.courseUnitVOList?.firstWhereOrNull((element) => | ||
266 | + element.sortOrder == (curCourseUnitDetail.sortOrder! + 1)); | ||
267 | + | ||
229 | if (nextCourseUnitDetail != null) { | 268 | if (nextCourseUnitDetail != null) { |
230 | - final courseUnitId = nextCourseUnitDetail.id!; | ||
231 | - try { | 269 | + if (nextCourseUnitDetail.lock == true) { |
270 | + ///如果下一个unit是锁定状态,请求数据刷新查询解锁状态 | ||
232 | await loading(() async { | 271 | await loading(() async { |
233 | - _courseSectionDatasMap[courseUnitId] = | ||
234 | - await LessonDao.courseSection(courseUnitId: courseUnitId); | ||
235 | - emitter(LessonDataLoadState()); | 272 | + CourseUnitEntity? newCourseUnitEntity = await LessonDao.courseUnit( |
273 | + _courseUnitEntity.nowCourseModuleId); | ||
274 | + | ||
275 | + ///拿到重新获取到的unit后,再次判断是否解锁 | ||
276 | + nextCourseUnitDetail = newCourseUnitEntity?.courseUnitVOList?.firstWhereOrNull( | ||
277 | + (element) => element.id == nextCourseUnitDetail?.id); | ||
278 | + if (nextCourseUnitDetail?.lock == false) { | ||
279 | + ///解锁状态从锁定到解锁,覆盖原unit数据并刷新ui | ||
280 | + _courseUnitEntity = newCourseUnitEntity!; | ||
281 | + emitter(LessonDataLoadState()); | ||
282 | + | ||
283 | + return checkCourseSectionLockedOfNextUnit(courseLessonId, nextCourseUnitDetail!.id!, emitter); | ||
284 | + } else { | ||
285 | + showToast('下个单元课程还没解锁哦'); | ||
286 | + | ||
287 | + ///如果还是锁定状态,返回null | ||
288 | + return null; | ||
289 | + } | ||
236 | }); | 290 | }); |
237 | - _pageController.nextPage( | ||
238 | - duration: const Duration(milliseconds: 500), | ||
239 | - curve: Curves.ease, | ||
240 | - ); | ||
241 | - return _courseSectionDatasMap[courseUnitId]!.first; | ||
242 | - } catch (e) { | ||
243 | - if (e is ApiException) { | ||
244 | - showToast(e.message.toString()); | ||
245 | - } | ||
246 | - return null; | 291 | + } else { |
292 | + return checkCourseSectionLockedOfNextUnit(courseLessonId, nextCourseUnitDetail.id!, emitter); | ||
247 | } | 293 | } |
248 | } else { | 294 | } else { |
295 | + showToast("恭喜你,本阶段学到顶啦"); | ||
249 | ///最后一个unit了 | 296 | ///最后一个unit了 |
250 | return null; | 297 | return null; |
251 | } | 298 | } |
@@ -254,5 +301,45 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | @@ -254,5 +301,45 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { | ||
254 | return null; | 301 | return null; |
255 | } | 302 | } |
256 | } | 303 | } |
304 | + return null; | ||
305 | + } | ||
306 | + | ||
307 | + ///检查下一个unit的(第一个)section | ||
308 | + Future<CourseSectionEntity?> checkCourseSectionLockedOfNextUnit(int courseLessonId, int nextCourseUnitDetailId, | ||
309 | + Emitter<SectionState> emitter) async { | ||
310 | + CourseSectionEntity? firstSectionNextUnit = await getFirstSectionByUnitId( | ||
311 | + nextCourseUnitDetailId, emitter); | ||
312 | + if (firstSectionNextUnit != null) { | ||
313 | + ///下个unit的第一个section如果不为空,再次检查是否锁定 | ||
314 | + CourseSectionEntity? courseSectionEntity = await checkCourseSectionLocked(courseLessonId, firstSectionNextUnit, emitter); | ||
315 | + if (courseSectionEntity != null) { | ||
316 | + ///只有是下一unit的第一个section并且解锁了,才跳转 | ||
317 | + _pageController.nextPage( | ||
318 | + duration: const Duration(milliseconds: 250), | ||
319 | + curve: Curves.ease, | ||
320 | + ); | ||
321 | + } | ||
322 | + return courseSectionEntity; | ||
323 | + } else { | ||
324 | + ///下个unit的第一个section如果为空,返回null | ||
325 | + showToast('下个课程暂未找到'); | ||
326 | + return null; | ||
327 | + } | ||
328 | + } | ||
329 | + | ||
330 | + ///根据unitId获取当前unit的第一个section | ||
331 | + Future<CourseSectionEntity?> getFirstSectionByUnitId( | ||
332 | + int courseUnitId, Emitter<SectionState> emitter) async { | ||
333 | + List<CourseSectionEntity>? courseSectionEntity = | ||
334 | + _courseSectionDatasMap[courseUnitId]; | ||
335 | + if (courseSectionEntity == null) { | ||
336 | + ///如果没下载过,请求数据 | ||
337 | + await loading(() async { | ||
338 | + _courseSectionDatasMap[courseUnitId] = | ||
339 | + await LessonDao.courseSection(courseUnitId: courseUnitId); | ||
340 | + emitter(LessonDataLoadState()); | ||
341 | + }); | ||
342 | + } | ||
343 | + return _courseSectionDatasMap[courseUnitId]?.first; | ||
257 | } | 344 | } |
258 | } | 345 | } |
lib/pages/unit/bloc.dart
@@ -23,10 +23,10 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | @@ -23,10 +23,10 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { | ||
23 | 23 | ||
24 | 24 | ||
25 | UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { | 25 | UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { |
26 | - on<RequestUnitDataEvent>(_requestData); | 26 | + on<RequestUnitDataEvent>(_requestUnitDatas); |
27 | } | 27 | } |
28 | 28 | ||
29 | - void _requestData(RequestUnitDataEvent event, Emitter<UnitState> emitter) async { | 29 | + void _requestUnitDatas(RequestUnitDataEvent event, Emitter<UnitState> emitter) async { |
30 | try { | 30 | try { |
31 | await loading(() async { | 31 | await loading(() async { |
32 | _unitData = await LessonDao.courseUnit(event.moduleId); | 32 | _unitData = await LessonDao.courseUnit(event.moduleId); |
lib/pages/unit/view.dart
@@ -57,7 +57,7 @@ class UnitPage extends StatelessWidget { | @@ -57,7 +57,7 @@ class UnitPage extends StatelessWidget { | ||
57 | return GestureDetector( | 57 | return GestureDetector( |
58 | onTap: () { | 58 | onTap: () { |
59 | if (data.lock == true) { | 59 | if (data.lock == true) { |
60 | - showToast('当前课程暂未解锁'); | 60 | + showToast('当前单元课程暂未解锁'); |
61 | return; | 61 | return; |
62 | } | 62 | } |
63 | 63 |
lib/utils/list_ext.dart
@@ -8,4 +8,14 @@ extension ListExtension<E> on List<E> { | @@ -8,4 +8,14 @@ extension ListExtension<E> on List<E> { | ||
8 | } | 8 | } |
9 | return null; | 9 | return null; |
10 | } | 10 | } |
11 | + | ||
12 | + /// 获取数组中第一个匹配元素,没有就返回null | ||
13 | + E? firstWhereOrNull(bool Function(E element) test) { | ||
14 | + for (E element in this) { | ||
15 | + if (test(element)) { | ||
16 | + return element; | ||
17 | + } | ||
18 | + } | ||
19 | + return null; | ||
20 | + } | ||
11 | } | 21 | } |