RQExerciseSubViewController.m 32 KB

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