RQExerciseSubViewController.m 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. //
  2. // RQExerciseSubViewController.m
  3. // JSJP
  4. //
  5. // Created by 张嵘 on 2021/8/12.
  6. //
  7. #import "RQExerciseSubViewController.h"
  8. #import "HWPanModal.h"
  9. @interface RQExerciseSubViewController ()
  10. /// viewModel
  11. @property (nonatomic, readonly, strong) RQExerciseSubViewModel *viewModel;
  12. @property (nonatomic, readwrite, strong) RQExerciseToolBarView *exerciseToolBarView;
  13. @property (nonatomic, readwrite, strong) JXPagerSmoothView *pagerView;
  14. @property (nonatomic, readwrite, strong) JXCategoryTitleView *categoryView;
  15. @property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView);
  16. @property (nonatomic, readwrite, strong) UIScrollView *currentListView;
  17. @property (nonatomic, readwrite, copy) NSArray <NSString *> *titles;
  18. @property (nonatomic, readwrite, copy) NSArray <RQYDTQuestionModel *> *ydtQuestionsArr;
  19. @property (nonatomic, readwrite, copy) NSArray <RQExerciseModel *> *reDoQuestionsArr;
  20. @property (nonatomic, readwrite, strong) NSMutableDictionary *listVcDic;
  21. @property (nonatomic, readwrite, strong) NSMapTable *mapTable;
  22. @end
  23. @implementation RQExerciseSubViewController
  24. @dynamic viewModel;
  25. #pragma mark - SystemMethod
  26. - (void)viewDidLoad {
  27. [super viewDidLoad];
  28. /// 初始化
  29. [self rq_setup];
  30. @weakify(self)
  31. dispatch_async(dispatch_get_main_queue(), ^{
  32. CGFloat height = RQ_SCREEN_HEIGHT - (RQ_APPLICATION_NAV_BAR_HEIGHT + RQ_APPLICATION_STATUS_BAR_HEIGHT) - RQ_APPLICATION_SAFEAREA_BOTTOM_HEIGHT - RQ_FIT_HORIZONTAL(50.f);
  33. self.pagerView.frame = CGRectMake(0, 0, RQ_SCREEN_WIDTH, height);
  34. [self.exerciseToolBarView mas_makeConstraints:^(MASConstraintMaker *make) {
  35. @strongify(self)
  36. make.centerX.mas_equalTo(self.view);
  37. make.bottom.mas_equalTo(self.view.mas_bottom).mas_offset(0);
  38. make.size.mas_equalTo(CGSizeMake(RQ_SCREEN_WIDTH, RQ_FIT_HORIZONTAL(50.f)));
  39. }];
  40. });
  41. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateScoreView) name:@"updateScoreView" object:nil];
  42. }
  43. - (void)viewWillDisappear:(BOOL)animated {
  44. [super viewWillDisappear:animated];
  45. // int popNum = _firstNum<self.questionArr.count-1 ?_firstNum+1:(int)self.questionArr.count-1;
  46. // [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInt:popNum] forKey:@"QUESTIONNUM"];
  47. // [[NSUserDefaults standardUserDefaults] synchronize];
  48. }
  49. - (void)viewWillLayoutSubviews {
  50. [super viewWillLayoutSubviews];
  51. }
  52. - (void)updateScoreView {
  53. RQExamResultViewModel *examResultViewModel = [[RQExamResultViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:@{
  54. RQViewModelUtilKey : self.viewModel.questionArr,
  55. RQViewModelIDKey : RQ_Exercise_Module.correctArr,
  56. RQViewCommonValueKey : RQ_Exercise_Module.errorArr,
  57. RQHomeSubPageTypeKHModeKey : @(self.viewModel.subPageTypeKHMode)
  58. }];
  59. [RQ_APPDELEGATE.services pushViewModel:examResultViewModel animated:YES];
  60. }
  61. - (void)dealloc {
  62. [[NSNotificationCenter defaultCenter] removeObserver:self];
  63. RQ_Exercise_Module.correctArr = @[];
  64. RQ_Exercise_Module.errorArr = @[];
  65. self.categoryView.delegate = nil;
  66. self.categoryView = nil;
  67. // self.pagerView.delegate = nil;
  68. self.pagerView = nil;
  69. RQ_Exercise_Module.questionArr = @[];
  70. }
  71. #pragma mark - PrivateMethods
  72. /// 初始化
  73. - (void)rq_setup {
  74. @weakify(self)
  75. [self.view addSubview:self.pagerView];
  76. [self.view addSubview:self.exerciseToolBarView];
  77. if (RQ_Exercise_Module.currentExerciseType == RQExerciseType_Exam) {
  78. RQ_Exercise_Module.questionArr = self.viewModel.questionArr;
  79. [self jumpQuestionWithIndex:0];
  80. [self reDoQuestionsArr];
  81. } else {
  82. NSInteger historyNum = [RQ_YDTQuestion_Module getHistoryQuestionNum];
  83. if (self.viewModel.questionArr.count >= historyNum + 1) {
  84. if (historyNum == 0) {
  85. [self jumpQuestionWithIndex:0];
  86. } else {
  87. if(RQ_Exercise_Module.currentExerciseType != RQExerciseType_Error_Special_List){//易错题不记录跳转
  88. [RQ_ALERTVIEW_MANAGER showAlertWithAlertType:RQAlertType_Default title:@"温馨提示" message:[NSString stringWithFormat:@"上次做题至%ld题,是否继续?",historyNum + 1] confirmTitle:@"是" cancelTitle:@"否" confirmAction:^(__kindof QMUIDialogViewController * _Nonnull dialogViewController) {
  89. @strongify(self)
  90. [self jumpQuestionWithIndex:historyNum];
  91. } cancelAction:^(__kindof QMUIDialogViewController * _Nonnull dialogViewController) {
  92. @strongify(self)
  93. [self jumpQuestionWithIndex:0];
  94. }];
  95. }
  96. }
  97. }
  98. }
  99. [[RACObserve(self, number) deliverOnMainThread] subscribeNext:^(id _Nullable x) {
  100. @strongify(self)
  101. if (self.viewModel.questionArr) {
  102. if (self.viewModel.questionArr.count >= self.number + 1) {
  103. self.exerciseToolBarView.totalNumberOfQuestionsLabel.text = [NSString stringWithFormat:@"%ld/%lu",[x integerValue] + 1,(unsigned long)self.viewModel.questionArr.count];
  104. RQExerciseModel *exerciseModel = self.viewModel.questionArr[self.number];
  105. self.exerciseToolBarView.collectBtn.selected = [RQ_YDT_USER_Question_Module getCollectRecordWithQuestionId:exerciseModel.ydtQuestionModel.ID carType:RQ_YDTQuestion_Module.carType subject:RQ_YDTQuestion_Module.subject];
  106. }
  107. }
  108. if(RQ_Exercise_Module.errorArr.count)
  109. self.exerciseToolBarView.errorOptionNumLabel.text = (RQ_Exercise_Module.currentExerciseType == RQExerciseType_Recitation)? @"0" : [NSString qmui_stringWithNSInteger:RQ_Exercise_Module.errorArr.count];//错题
  110. if(RQ_Exercise_Module.correctArr.count)
  111. self.exerciseToolBarView.correctOptionNumLabel.text = (RQ_Exercise_Module.currentExerciseType == RQExerciseType_Recitation)? @"0" : [NSString qmui_stringWithNSInteger:RQ_Exercise_Module.correctArr.count];//对题
  112. }];
  113. // RAC(self.exerciseToolBarView.errorOptionNumLabel, text) = [RACObserve(RQ_Exercise_Module, errorArr) map:^id _Nullable(id _Nullable value) {
  114. // return (RQ_Exercise_Module.currentExerciseType == RQExerciseType_Recitation)? @"0" : [NSString qmui_stringWithNSInteger:RQ_Exercise_Module.errorArr.count];
  115. // }];
  116. //
  117. // RAC(self.exerciseToolBarView.correctOptionNumLabel, text) = [RACObserve(RQ_Exercise_Module, correctArr) map:^id _Nullable(id _Nullable value) {
  118. // return (RQ_Exercise_Module.currentExerciseType == RQExerciseType_Recitation)? @"0" : [NSString qmui_stringWithNSInteger:RQ_Exercise_Module.correctArr.count];
  119. // }];
  120. // [[[[RQNotificationCenter rac_addObserverForName:RQExerciseAlertNotification object:nil] deliverOnMainThread] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * note) {
  121. // @strongify(self)
  122. // RQExerciseAlertType type = [note.object[RQExerciseAlertTypeKey] integerValue];
  123. // if (RQ_Exercise_Module.currentExerciseType == RQExerciseType_Exam) {
  124. // NSDictionary *dic = @{
  125. // @"questionArr" : self.viewModel.questionArr,
  126. // };
  127. //
  128. // [RQ_Exercise_Module showAlertWithRQExerciseAlertType:type valueDic:dic confirmAction:^(__kindof QMUIDialogViewController *dialogViewController) {
  129. // @strongify(self);
  130. // if (type == RQExerciseAlertType_Exam_HandUp) {
  131. // /// 交卷
  132. // RQExamResultViewModel *examResultViewModel = [[RQExamResultViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:@{
  133. // RQViewModelUtilKey : self.viewModel.questionArr,
  134. // RQViewModelIDKey : RQ_Exercise_Module.correctArr,
  135. // RQViewCommonValueKey : RQ_Exercise_Module.errorArr,
  136. // }];
  137. // [RQ_APPDELEGATE.services pushViewModel:examResultViewModel animated:YES];
  138. // } else if (type == RQExerciseAlertType_Exam_Resume || type == RQExerciseAlertType_Exam_Suspend) {
  139. // if (RQ_Exercise_Module.timer) {
  140. // [RQ_Exercise_Module.timer setFireDate:[NSDate distantPast]];
  141. // }
  142. // }
  143. // } cancelAction:^(__kindof QMUIDialogViewController *dialogViewController) {
  144. // @strongify(self)
  145. // if (type == RQExerciseAlertType_Exam_HandUp) {
  146. // if (RQ_Exercise_Module.timer) {
  147. // [RQ_Exercise_Module.timer setFireDate:[NSDate distantPast]];
  148. // }
  149. // } else if (type == RQExerciseAlertType_Exam_Resume || type == RQExerciseAlertType_Exam_Suspend) {
  150. // /// 重新考试
  151. // self.viewModel.questionArr = self.reDoQuestionsArr;
  152. // if (RQ_Exercise_Module.timer) {
  153. // [RQ_Exercise_Module.timer invalidate];
  154. // RQ_Exercise_Module.timer = nil;
  155. // [RQ_Exercise_Module startTimer];
  156. // RQ_Exercise_Module.errorArr = @[];
  157. // RQ_Exercise_Module.correctArr = @[];
  158. // [self jumpQuestionWithIndex:0];
  159. // }
  160. // }
  161. // }];
  162. // }
  163. // }];
  164. [[[[RQNotificationCenter rac_addObserverForName:RQAutoJumpNextNotification object:nil] deliverOnMainThread] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * _Nullable x) {
  165. @strongify(self);
  166. if (RQ_Exercise_Module.isRightAutoJumpToNext) {
  167. if (self.viewModel.questionArr.count == self.number + 1) {
  168. [QMUITips showWithText:@"已经是最后一题啦!"];
  169. } else {
  170. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  171. [self jumpQuestionWithIndex:self.number + 1];
  172. });
  173. }
  174. }
  175. }];
  176. }
  177. - (void)jumpQuestionWithIndex:(NSUInteger)index {
  178. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  179. self.number = (int)index;
  180. self.pagerView.defaultSelectedIndex = index;
  181. self.categoryView.defaultSelectedIndex = index;
  182. [self.pagerView reloadData];
  183. [self.categoryView reloadData];
  184. [self saveNumWithIndex:index];
  185. });
  186. }
  187. - (void)showCatalogue {
  188. @weakify(self)
  189. RQ_Exercise_Module.isShow_CatalogueView = YES;
  190. RQCatalogueViewModel *catalogueViewModel = [[RQCatalogueViewModel alloc] initWithServices:self.viewModel.services params:@{
  191. RQViewModelIDKey : @(self.number),
  192. RQViewModelUtilKey : self.viewModel.questionArr,
  193. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  194. }];
  195. RQCatalogueViewController *catalogueViewController = [[RQCatalogueViewController alloc] initWithViewModel:catalogueViewModel];
  196. [catalogueViewController initCompletionWithSelectIndexBlock:^(NSInteger index) {
  197. @strongify(self)
  198. [self jumpQuestionWithIndex:index];
  199. }];
  200. [self presentPanModal:catalogueViewController];
  201. }
  202. #pragma mark - UITableViewDataSource, UITableViewDelegate
  203. - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  204. !self.scrollCallback ?: self.scrollCallback(scrollView);
  205. }
  206. #pragma mark - JXPagerViewListViewDelegate
  207. - (UIView *)listView {
  208. return self.view;
  209. }
  210. - (UIScrollView *)listScrollView {
  211. return self.tableView;
  212. }
  213. - (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback {
  214. self.scrollCallback = callback;
  215. }
  216. - (void)listScrollViewWillResetContentOffset {
  217. //当前的listScrollView需要重置的时候,就把所有列表的contentOffset都重置了
  218. for (RQTestQuestionsViewController *list in self.pagerView.listDict.allValues) {
  219. list.tableView.contentOffset = CGPointZero;
  220. }
  221. }
  222. #pragma mark - JXPagerSmoothViewDataSource
  223. - (UIView *)viewForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView {
  224. return [UIView new];
  225. }
  226. - (CGFloat)heightForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView {
  227. return 0.f;
  228. }
  229. - (CGFloat)heightForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView {
  230. return 0.f;
  231. }
  232. - (UIView *)viewForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView {
  233. return self.categoryView;
  234. }
  235. - (NSInteger)numberOfListsInPagerView:(JXPagerSmoothView *)pagerView {
  236. return self.categoryView.titles.count;
  237. }
  238. - (id<JXPagerSmoothViewListViewDelegate>)pagerView:(JXPagerSmoothView *)pagerView initListAtIndex:(NSInteger)index {
  239. NSLog(@"JXCategoryViewDelegate=====initListAtIndex=%zd",index);
  240. @weakify(self)
  241. RQTestQuestionsViewController *currentQuestionsViewController = [self.listVcDic objectForKey:[NSString qmui_stringWithNSInteger:index]];
  242. if (RQObjectIsNil(currentQuestionsViewController)) {
  243. RQExerciseModel *exerciseModel = self.viewModel.questionArr[index];
  244. // exerciseModel.exerciseType = self.viewModel.exerciseType;
  245. exerciseModel.allNum = self.viewModel.questionArr.count;
  246. RQTestQuestionsViewModel *testQuestionsViewModel = [[RQTestQuestionsViewModel alloc] initWithServices:self.viewModel.services params:@{
  247. RQViewModelUtilKey : exerciseModel,
  248. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  249. RQHomePageCarTypeKey : @(self.viewModel.homePageCarType),
  250. RQHomePageSubjectTypeKey: @(self.viewModel.homePageSubjectType),
  251. }];
  252. RQTestQuestionsViewController *testQuestionsViewController = [[RQTestQuestionsViewController alloc] initWithViewModel:testQuestionsViewModel];
  253. currentQuestionsViewController = testQuestionsViewController;
  254. [self.listVcDic setObject:testQuestionsViewController forKey:[NSString qmui_stringWithNSInteger:index]];
  255. }
  256. [[RACScheduler scheduler] schedule:^{
  257. @strongify(self)
  258. if (index > 0) {
  259. if (index > 1) {
  260. RQTestQuestionsViewController *lastQuestionsViewController1 = [self.listVcDic objectForKey:[NSString qmui_stringWithNSInteger:index - 2]];
  261. if (RQObjectIsNil(lastQuestionsViewController1)) {
  262. RQExerciseModel *exerciseModel = self.viewModel.questionArr[index - 2];
  263. // exerciseModel.exerciseType = self.viewModel.exerciseType;
  264. exerciseModel.allNum = self.viewModel.questionArr.count;
  265. RQTestQuestionsViewModel *testQuestionsViewModel = [[RQTestQuestionsViewModel alloc] initWithServices:self.viewModel.services params:@{
  266. RQViewModelUtilKey : exerciseModel,
  267. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  268. RQHomePageCarTypeKey : @(self.viewModel.homePageCarType),
  269. RQHomePageSubjectTypeKey: @(self.viewModel.homePageSubjectType),
  270. }];
  271. RQTestQuestionsViewController *testQuestionsViewController = [[RQTestQuestionsViewController alloc] initWithViewModel:testQuestionsViewModel];
  272. [self.listVcDic setObject:testQuestionsViewController forKey:[NSString qmui_stringWithNSInteger:index - 2]];
  273. }
  274. }
  275. RQTestQuestionsViewController *lastQuestionsViewController = [self.listVcDic objectForKey:[NSString qmui_stringWithNSInteger:index - 1]];
  276. if (RQObjectIsNil(lastQuestionsViewController)) {
  277. RQExerciseModel *exerciseModel = self.viewModel.questionArr[index - 1];
  278. // exerciseModel.exerciseType = self.viewModel.exerciseType;
  279. exerciseModel.allNum = self.viewModel.questionArr.count;
  280. RQTestQuestionsViewModel *testQuestionsViewModel = [[RQTestQuestionsViewModel alloc] initWithServices:self.viewModel.services params:@{
  281. RQViewModelUtilKey : exerciseModel,
  282. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  283. RQHomePageCarTypeKey : @(self.viewModel.homePageCarType),
  284. RQHomePageSubjectTypeKey: @(self.viewModel.homePageSubjectType),
  285. }];
  286. RQTestQuestionsViewController *testQuestionsViewController = [[RQTestQuestionsViewController alloc] initWithViewModel:testQuestionsViewModel];
  287. [self.listVcDic setObject:testQuestionsViewController forKey:[NSString qmui_stringWithNSInteger:index - 1]];
  288. }
  289. }
  290. if (index + 1 < self.viewModel.questionArr.count) {
  291. if (index + 2 < self.viewModel.questionArr.count) {
  292. RQTestQuestionsViewController *nextQuestionsViewController1 = [self.listVcDic objectForKey:[NSString qmui_stringWithNSInteger:index + 2]];
  293. if (RQObjectIsNil(nextQuestionsViewController1)) {
  294. RQExerciseModel *exerciseModel = self.viewModel.questionArr[index + 2];
  295. // exerciseModel.exerciseType = self.viewModel.exerciseType;
  296. exerciseModel.allNum = self.viewModel.questionArr.count;
  297. RQTestQuestionsViewModel *testQuestionsViewModel = [[RQTestQuestionsViewModel alloc] initWithServices:self.viewModel.services params:@{
  298. RQViewModelUtilKey : exerciseModel,
  299. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  300. RQHomePageCarTypeKey : @(self.viewModel.homePageCarType),
  301. RQHomePageSubjectTypeKey: @(self.viewModel.homePageSubjectType),
  302. }];
  303. RQTestQuestionsViewController *testQuestionsViewController = [[RQTestQuestionsViewController alloc] initWithViewModel:testQuestionsViewModel];
  304. [self.listVcDic setObject:testQuestionsViewController forKey:[NSString qmui_stringWithNSInteger:index + 2]];
  305. }
  306. }
  307. RQTestQuestionsViewController *nextQuestionsViewController = [self.listVcDic objectForKey:[NSString qmui_stringWithNSInteger:index + 1]];
  308. if (RQObjectIsNil(nextQuestionsViewController)) {
  309. RQExerciseModel *exerciseModel = self.viewModel.questionArr[index + 1];
  310. // exerciseModel.exerciseType = self.viewModel.exerciseType;
  311. exerciseModel.allNum = self.viewModel.questionArr.count;
  312. RQTestQuestionsViewModel *testQuestionsViewModel = [[RQTestQuestionsViewModel alloc] initWithServices:self.viewModel.services params:@{
  313. RQViewModelUtilKey : exerciseModel,
  314. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  315. RQHomePageCarTypeKey : @(self.viewModel.homePageCarType),
  316. RQHomePageSubjectTypeKey: @(self.viewModel.homePageSubjectType),
  317. }];
  318. RQTestQuestionsViewController *testQuestionsViewController = [[RQTestQuestionsViewController alloc] initWithViewModel:testQuestionsViewModel];
  319. [self.listVcDic setObject:testQuestionsViewController forKey:[NSString qmui_stringWithNSInteger:index + 1]];
  320. }
  321. }
  322. }];
  323. // RQExerciseModel *exerciseModel = self.viewModel.questionArr[index];
  324. // exerciseModel.exerciseType = self.viewModel.exerciseType;
  325. // exerciseModel.allNum = self.viewModel.questionArr.count;
  326. //
  327. // RQTestQuestionsViewModel *testQuestionsViewModel = [[RQTestQuestionsViewModel alloc] initWithServices:self.viewModel.services params:@{
  328. // RQViewModelUtilKey : exerciseModel,
  329. // RQExerciseTypeKey : @(self.viewModel.exerciseType),
  330. // RQHomePageCarTypeKey : @(self.viewModel.homePageCarType),
  331. // RQHomePageSubjectTypeKey: @(self.viewModel.homePageSubjectType),
  332. // }];
  333. // RQTestQuestionsViewController *testQuestionsViewController = [[RQTestQuestionsViewController alloc] initWithViewModel:testQuestionsViewModel];
  334. self.currentListView = currentQuestionsViewController.tableView;
  335. __weak typeof(currentQuestionsViewController) weakController = currentQuestionsViewController;
  336. [[RACScheduler scheduler] schedule:^{
  337. if (pagerView.listDict.allValues.count > 5) {
  338. NSMutableDictionary *dic = pagerView.listDict.mutableCopy;
  339. [[dic.allKeys.rac_sequence.signal filter:^BOOL(id _Nullable value) {
  340. NSInteger integerValue = [value integerValue];
  341. NSInteger frontIndex = ((index - 1) < 0)? 0 : index - 1;
  342. NSInteger frontIndex1 = ((index - 2) < 0)? 0 : index - 2;
  343. NSInteger beforeIndex = index + 1;
  344. NSInteger beforeIndex1 = index + 2;
  345. return index != integerValue && beforeIndex != integerValue && frontIndex != integerValue && beforeIndex1 != integerValue && frontIndex1 != integerValue;
  346. }].toArray.rac_sequence.signal subscribeNext:^(id _Nullable x) {
  347. @strongify(self)
  348. NSString *key = [NSString stringWithFormat:@"%@",x];
  349. RQTestQuestionsViewController *list = [dic objectForKey:key.numberValue];
  350. [[list listView] removeFromSuperview];
  351. [list removeFromParentViewController];
  352. [dic removeObjectForKey:key.numberValue];
  353. pagerView.listDict = dic;
  354. RQTestQuestionsViewController *list1 = [self.listVcDic objectForKey:key];
  355. [[list1 listView] removeFromSuperview];
  356. [list1 removeFromParentViewController];
  357. [self.listVcDic removeObjectForKey:key];
  358. }];
  359. }
  360. }];
  361. return weakController;
  362. }
  363. #pragma mark - JXCategoryViewDelegate
  364. - (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
  365. self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0);
  366. //根据选中的下标,实时更新currentListView
  367. RQTestQuestionsViewController *list = (RQTestQuestionsViewController *)self.pagerView.listDict[@(index)];
  368. self.currentListView = list.tableView;
  369. self.number = index;
  370. [self saveNumWithIndex:index];
  371. NSLog(@"JXCategoryViewDelegate=====didSelectedItemAtIndex=%zd",index);
  372. //控制-语音停止-切换
  373. // RQExerciseModel *exerciseModel = self.viewModel.questionArr[index];
  374. // if(![exerciseModel.ydtQuestionModel.Question isEqual:NY_VOICE_MANAGER.paytext]&&
  375. // //NY_VOICE_MANAGER.state==NYVoiceType_Start&&
  376. // NY_VOICE_MANAGER.paytext!=nil){
  377. //
  378. // }
  379. [NY_VOICE_MANAGER stopPayVoiceAction];
  380. [NY_VOICE_MANAGER stopPayVoiceActionUrl];
  381. }
  382. - (void)saveNumWithIndex:(NSInteger)index {
  383. RQExerciseModel *exerciseModel = self.viewModel.questionArr[index];
  384. [RQ_YDTQuestion_Module saveHistoryQuestionNumWithQuestionId:exerciseModel.ydtQuestionModel.num];
  385. }
  386. - (void)categoryView:(JXCategoryBaseView *)categoryView scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio {
  387. RQ_Exercise_Module.isScrolling = (ratio > 0.1) && (ratio < 0.9);
  388. }
  389. #pragma mark - JXPagerMainTableViewGestureDelegate
  390. - (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
  391. //禁止categoryView左右滑动的时候,上下和左右都可以滚动
  392. if (otherGestureRecognizer == self.categoryView.collectionView.panGestureRecognizer) {
  393. return NO;
  394. }
  395. return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
  396. }
  397. #pragma mark - LazyLoad
  398. - (RQExerciseToolBarView *)exerciseToolBarView {
  399. if (!_exerciseToolBarView) {
  400. _exerciseToolBarView = [RQExerciseToolBarView exerciseToolBarView];
  401. @weakify(self, _exerciseToolBarView)
  402. [_exerciseToolBarView.catalogueView setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  403. [[RACScheduler mainThreadScheduler] schedule:^{
  404. @strongify(self)
  405. [self showCatalogue];
  406. }];
  407. }];
  408. RAC(_exerciseToolBarView.handInBtn, hidden) = [RACObserve(RQ_Exercise_Module, currentExerciseType) map:^id _Nullable(id _Nullable value) {
  409. return @(RQ_Exercise_Module.currentExerciseType != RQExerciseType_Exam);
  410. }];
  411. RAC(_exerciseToolBarView.collectBtn, hidden) = [RACObserve(self.viewModel, homeSubPageType) map:^id _Nullable(id _Nullable value) {
  412. @strongify(self)
  413. return @(self.viewModel.homeSubPageType == RQHomeSubPageType_WrongTopicAndCollection);
  414. }];
  415. RAC(_exerciseToolBarView.deleteBtn, hidden) = [RACObserve(self.viewModel, homeSubPageType) map:^id _Nullable(id _Nullable value) {
  416. @strongify(self)
  417. return @(self.viewModel.homeSubPageType != RQHomeSubPageType_WrongTopicAndCollection);
  418. }];
  419. [_exerciseToolBarView.handInBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  420. @strongify(self)
  421. if (RQ_Exercise_Module.timer) {
  422. [RQ_Exercise_Module.timer setFireDate:[NSDate distantFuture]];
  423. }
  424. NSDictionary *dic = @{
  425. @"questionArr" : self.viewModel.questionArr,
  426. };
  427. [RQ_Exercise_Module showAlertWithRQExerciseAlertType:RQExerciseAlertType_Exam_HandUp valueDic:dic confirmAction:^(__kindof QMUIDialogViewController *dialogViewController) {
  428. @strongify(self);
  429. NSInteger totalNum = self.viewModel.questionArr.count;
  430. NSInteger rightNum = RQ_Exercise_Module.correctArr.count;
  431. NSInteger perScore = 100 / totalNum;
  432. NSInteger score = rightNum * perScore;
  433. if(self.viewModel.subPageTypeKHMode == 1){//广西特殊处理score
  434. dispatch_time_t dipatchTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC));
  435. dispatch_after(dipatchTime, dispatch_get_main_queue(), ^{
  436. [[NSNotificationCenter defaultCenter] postNotificationName:RQHomeSubPageTypeKHModeKey object:@(score)];//通知-签退
  437. });
  438. }else{
  439. /// 现在交卷
  440. RQExamResultViewModel *examResultViewModel = [[RQExamResultViewModel alloc] initWithServices:RQ_APPDELEGATE.services params:@{
  441. RQViewModelUtilKey : self.viewModel.questionArr,
  442. RQViewModelIDKey : RQ_Exercise_Module.correctArr,
  443. RQViewCommonValueKey : RQ_Exercise_Module.errorArr,
  444. RQHomeSubPageTypeKHModeKey : @(self.viewModel.subPageTypeKHMode)
  445. }];
  446. [RQ_APPDELEGATE.services pushViewModel:examResultViewModel animated:YES];
  447. }
  448. } cancelAction:^(__kindof QMUIDialogViewController *dialogViewController) {
  449. if (RQ_Exercise_Module.timer) {
  450. [RQ_Exercise_Module.timer setFireDate:[NSDate distantPast]];
  451. }
  452. }];
  453. }];
  454. [_exerciseToolBarView.collectBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  455. @strongify(self, _exerciseToolBarView)
  456. RQExerciseModel *exerciseModel = self.viewModel.questionArr[self.number];
  457. if (_exerciseToolBarView.collectBtn.selected) {
  458. [MBProgressHUD rq_showProgressHUD:@"取消中..."];
  459. [[[RQ_HTTP_Service deleteFavQuestionWithQuestionId:exerciseModel.ydtQuestionModel.ID type:RQSaveFavQuestionType_Collect] deliverOnMainThread] subscribeNext:^(id _Nullable x) {
  460. @strongify(_exerciseToolBarView)
  461. [RQ_YDT_USER_Question_Module deleteCollectRecordWithQuestionId:exerciseModel.ydtQuestionModel.ID];
  462. _exerciseToolBarView.collectBtn.selected = [RQ_YDT_USER_Question_Module getCollectRecordWithQuestionId:exerciseModel.ydtQuestionModel.ID carType:RQ_YDTQuestion_Module.carType subject:RQ_YDTQuestion_Module.subject];
  463. [MBProgressHUD rq_hideHUD];
  464. } error:^(NSError * _Nullable error) {
  465. [MBProgressHUD rq_hideHUD];
  466. }];
  467. } else {
  468. [MBProgressHUD rq_showProgressHUD:@"收藏中..."];
  469. [[[RQ_HTTP_Service saveFavQuestionWithQuestionId:exerciseModel.ydtQuestionModel.ID type:RQSaveFavQuestionType_Collect] deliverOnMainThread] subscribeNext:^(id _Nullable x) {
  470. @strongify(_exerciseToolBarView)
  471. [RQ_YDT_USER_Question_Module collectQuestionWithID:exerciseModel.ydtQuestionModel.ID carType:RQ_YDTQuestion_Module.carType subject:RQ_YDTQuestion_Module.subject];
  472. _exerciseToolBarView.collectBtn.selected = [RQ_YDT_USER_Question_Module getCollectRecordWithQuestionId:exerciseModel.ydtQuestionModel.ID carType:RQ_YDTQuestion_Module.carType subject:RQ_YDTQuestion_Module.subject];
  473. [MBProgressHUD rq_hideHUD];
  474. } error:^(NSError * _Nullable error) {
  475. [MBProgressHUD rq_hideHUD];
  476. }];
  477. }
  478. }];
  479. [_exerciseToolBarView.deleteBtn setTapActionWithBlock:^(UITapGestureRecognizer *tap) {
  480. @strongify(self)
  481. RQExerciseModel *exerciseModel = self.viewModel.questionArr[self.number];
  482. NSMutableArray *questionArr = self.viewModel.questionArr.mutableCopy;
  483. NSInteger index = [questionArr indexOfObject:exerciseModel];
  484. NSMutableArray *titleArr = self.titles.mutableCopy;
  485. NSMutableArray *errorArr = RQ_Exercise_Module.errorArr.mutableCopy;
  486. NSMutableArray *correctArr = RQ_Exercise_Module.correctArr.mutableCopy;
  487. [MBProgressHUD rq_showProgressHUD:@"删除中..."];
  488. [[[RQ_HTTP_Service deleteFavQuestionWithQuestionId:exerciseModel.ydtQuestionModel.ID type:RQSaveFavQuestionType_Collect] deliverOnMainThread] subscribeNext:^(id _Nullable x) {
  489. @strongify(self)
  490. [RQ_YDT_USER_Question_Module deleteCollectRecordWithQuestionId:exerciseModel.ydtQuestionModel.ID];
  491. [questionArr removeObject:exerciseModel];
  492. [titleArr removeObjectAtIndex:self.number];
  493. self.viewModel.questionArr = questionArr.copy;
  494. [RQNotificationCenter postNotificationName:RQCancelCollectNotification object:nil userInfo:@{RQCancelCollectExerciseModelKey:self.viewModel.questionArr}];
  495. if ([errorArr containsObject:exerciseModel]) {
  496. [errorArr removeObject:exerciseModel];
  497. RQ_Exercise_Module.errorArr = errorArr.copy;
  498. }
  499. if ([correctArr containsObject:exerciseModel]) {
  500. [correctArr removeObject:exerciseModel];
  501. RQ_Exercise_Module.correctArr = correctArr.copy;
  502. }
  503. if (questionArr.count > 0) {
  504. if (questionArr.count - 1 >= index) {
  505. // [self jumpQuestionWithIndex:index];
  506. // self.number = index;
  507. [self jumpQuestionWithIndex:index];
  508. self.categoryView.titles = titleArr;
  509. [self.categoryView reloadData];
  510. } else {
  511. if (questionArr.count - 1 >= index - 1 && index - 1 > 0) {
  512. // [self jumpQuestionWithIndex:index - 1];
  513. // self.number = index - 1;
  514. // self.categoryView.defaultSelectedIndex = index - 1;
  515. [self jumpQuestionWithIndex:index - 1];
  516. self.categoryView.titles = titleArr;
  517. [self.categoryView reloadData];
  518. }
  519. }
  520. } else {
  521. [self.viewModel.services popViewModelAnimated:YES];
  522. }
  523. [MBProgressHUD rq_hideHUD];
  524. } error:^(NSError * _Nullable error) {
  525. [MBProgressHUD rq_hideHUD];
  526. }];
  527. }];
  528. }
  529. return _exerciseToolBarView;
  530. }
  531. - (JXCategoryTitleView *)categoryView {
  532. if (!_categoryView) {
  533. __typeof(self) __weak weakSelf = self;
  534. _categoryView = [[JXCategoryTitleView alloc] init];
  535. _categoryView.titles = self.titles;
  536. _categoryView.delegate = weakSelf;
  537. /// !!!: 将列表容器视图关联到 categoryView
  538. _categoryView.contentScrollView = self.pagerView.listCollectionView;
  539. // self.categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listDict;
  540. }
  541. return _categoryView;
  542. }
  543. - (JXPagerSmoothView *)pagerView {
  544. if (!_pagerView) {
  545. _pagerView = [[JXPagerSmoothView alloc] initWithDataSource:self];
  546. self.contentScrollView = _pagerView.listCollectionView;
  547. }
  548. return _pagerView;
  549. }
  550. - (NSArray<NSString *> *)titles {
  551. return [self.viewModel.questionArr.rac_sequence.signal map:^id _Nullable(RQExerciseModel *exerciseModel) {
  552. return [NSString qmui_stringWithNSInteger:exerciseModel.ydtQuestionModel.ID];
  553. }].toArray;
  554. }
  555. - (NSArray<RQYDTQuestionModel *> *)ydtQuestionsArr {
  556. if (!_ydtQuestionsArr) {
  557. _ydtQuestionsArr = [self.viewModel.questionArr.rac_sequence.signal map:^id _Nullable(RQExerciseModel *exerciseModel) {
  558. return exerciseModel.ydtQuestionModel;
  559. }].toArray;
  560. }
  561. return _ydtQuestionsArr;
  562. }
  563. - (NSArray<RQExerciseModel *> *)reDoQuestionsArr {
  564. if (!_reDoQuestionsArr) {
  565. _reDoQuestionsArr = [self.ydtQuestionsArr.rac_sequence.signal map:^id _Nullable(RQYDTQuestionModel *ydtQuestionModel) {
  566. return [RQExerciseModel exerciseModelWithRQYDTQuestionModel:ydtQuestionModel];
  567. }].toArray;
  568. }
  569. return _reDoQuestionsArr;
  570. }
  571. - (NSMapTable *)mapTable {
  572. if (!_mapTable) {
  573. _mapTable = [[NSMapTable alloc] initWithKeyOptions:NSMapTableWeakMemory valueOptions:NSMapTableWeakMemory capacity:0];
  574. }
  575. return _mapTable;
  576. }
  577. - (NSMutableDictionary *)listVcDic {
  578. if (!_listVcDic) {
  579. _listVcDic = @{}.mutableCopy;
  580. }
  581. return _listVcDic;
  582. }
  583. @end