Commit 009cf00df190ae47e21695b202bb86ee682ba403
1 parent
8df5fbf9
feat:环节&单元解锁逻辑
Showing
5 changed files
with
126 additions
and
28 deletions
.gitignore
lib/pages/section/bloc/section_bloc.dart
... | ... | @@ -200,7 +200,7 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
200 | 200 | final curCourseSectionEntity = findCourseSectionById(courseLessonId); |
201 | 201 | if (curCourseSectionEntity != null) { |
202 | 202 | final curCourseUnitDetail = _courseUnitEntity.courseUnitVOList |
203 | - ?.firstWhere( | |
203 | + ?.firstWhereOrNull( | |
204 | 204 | (element) => element.id == curCourseSectionEntity.courseUnitId); |
205 | 205 | return curCourseUnitDetail; |
206 | 206 | } |
... | ... | @@ -213,39 +213,86 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
213 | 213 | final curCourseSectionEntity = findCourseSectionById(courseLessonId); |
214 | 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 | 258 | } else { |
221 | - ///section为空说明当前unit学完了,找下一个unit。(跨unit选lesson) | |
259 | + ///section为空说明当前unit学完了,找下一个unit。(跨unit选section) | |
222 | 260 | ///先根据courseLessonId找出当前的unit |
223 | 261 | final curCourseUnitDetail = findCourseUnitDetailById(courseLessonId); |
224 | 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 | 268 | if (nextCourseUnitDetail != null) { |
230 | - final courseUnitId = nextCourseUnitDetail.id!; | |
231 | - try { | |
269 | + if (nextCourseUnitDetail.lock == true) { | |
270 | + ///如果下一个unit是锁定状态,请求数据刷新查询解锁状态 | |
232 | 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 | 294 | } else { |
295 | + showToast("恭喜你,本阶段学到顶啦"); | |
249 | 296 | ///最后一个unit了 |
250 | 297 | return null; |
251 | 298 | } |
... | ... | @@ -254,5 +301,45 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
254 | 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 | 23 | |
24 | 24 | |
25 | 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 | 30 | try { |
31 | 31 | await loading(() async { |
32 | 32 | _unitData = await LessonDao.courseUnit(event.moduleId); | ... | ... |
lib/pages/unit/view.dart
lib/utils/list_ext.dart
... | ... | @@ -8,4 +8,14 @@ extension ListExtension<E> on List<E> { |
8 | 8 | } |
9 | 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 | } | ... | ... |