Commit 009cf00df190ae47e21695b202bb86ee682ba403

Authored by 吴启风
1 parent 8df5fbf9

feat:环节&单元解锁逻辑

.gitignore
... ... @@ -68,6 +68,7 @@
68 68 **/ios/xcode_build_ipa_adh
69 69 **/ios/xcode_build_ipa_aps
70 70 **/ios/xcode_build_ipa_dev
  71 +**/ios/build/
71 72  
72 73 # Exceptions to above rules.
73 74 !**/ios/**/default.mode1v3
... ...
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&lt;SectionEvent, SectionState&gt; {
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&lt;UnitEvent, UnitState&gt; {
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
... ... @@ -57,7 +57,7 @@ class UnitPage extends StatelessWidget {
57 57 return GestureDetector(
58 58 onTap: () {
59 59 if (data.lock == true) {
60   - showToast('当前课程暂未解锁');
  60 + showToast('当前单元课程暂未解锁');
61 61 return;
62 62 }
63 63  
... ...
lib/utils/list_ext.dart
... ... @@ -8,4 +8,14 @@ extension ListExtension&lt;E&gt; on List&lt;E&gt; {
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 }
... ...