RQHomePageViewController.m 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. //
  2. // RQHomePageViewController.m
  3. // RQCommon
  4. //
  5. // Created by 张嵘 on 2018/11/21.
  6. // Copyright © 2018 张嵘. All rights reserved.
  7. //
  8. #import "RQHomePageViewController.h"
  9. #import "HmV0.h"
  10. #import "HmV1.h"
  11. #import "HmV2.h"
  12. #import "HmV3.h"
  13. #import "HmV4.h"
  14. #import "HmV5.h"
  15. #import "MapManager.h"
  16. #import "ScanVC.h"
  17. #import "Tools.h"
  18. #import "ThirdLoginBindYunGuanVC.h"
  19. #import "DistenceTooLongMapVC.h"
  20. #import "DES3Util.h"
  21. #import "TheoryTrainVC.h"
  22. #import "DistenceTooLongMapVC.h"
  23. #import <BMKLocationkit/BMKLocationComponent.h>//引入定位功能所有的头文件(新)
  24. #import "OliveappLivenessDetectionViewController.h"
  25. #import "OliveappCameraPreviewController.h"
  26. #import "OliveappDetectedFrame.h"
  27. #import "OliveappBase64Helper.h"
  28. @interface RQHomePageViewController () <JXCategoryViewDelegate, JXPagerViewDelegate, JXPagerMainTableViewGestureDelegate, SDCycleScrollViewDelegate,BMKLocationManagerDelegate,OliveappLivenessResultDelegate,FaceDetectorsDelegate>
  29. /// viewModel
  30. @property (nonatomic, readonly, strong) RQHomePageViewModel *viewModel;
  31. @property (nonatomic, readwrite, strong) JXPagerView *pagerView;
  32. @property (nonatomic, readwrite, strong) JXCategoryTitleView *categoryView;
  33. @property (nonatomic, readwrite, copy) NSArray <NSString *> *titles;
  34. @property (nonatomic, readwrite, strong) LeftViewController *leftVC;
  35. //集中式理论
  36. @property (nonatomic, readwrite, assign) BOOL isNeedTest;
  37. @property (nonatomic, readwrite, assign) BOOL isCloseAudio;
  38. @property (nonatomic, readwrite, assign) NSInteger maxTime;
  39. @property (nonatomic, readwrite, copy) NSString *scanType;
  40. @property (nonatomic, readwrite, copy) NSString *scanData;
  41. @property (nonatomic, readwrite, assign) CLLocationCoordinate2D myLocation;
  42. @property (strong, readwrite, nonatomic) NSString *faceIdStr;
  43. @end
  44. @implementation RQHomePageViewController
  45. @dynamic viewModel;
  46. #pragma mark - SystemMethod
  47. - (void)viewDidLoad {
  48. [super viewDidLoad];
  49. if (RQ_COMMON_MANAGER.YYXC_SERVICE_OPEN) {
  50. if (!RQObjectIsNil(defUser.userDict)) {
  51. [defUser removeUserInfo];
  52. }
  53. } else {
  54. if (myDelegate.isLogin) {
  55. //更新登录信息 如果是登录状态的时候
  56. [LoginViewController reLoginFromViewController:self finishBlock:^{
  57. [LoginViewController getCurrentStateWithCompleteBlock:nil];
  58. }];
  59. }
  60. }
  61. /// 初始化
  62. [self rq_setup];
  63. }
  64. - (void)viewWillAppear:(BOOL)animated {
  65. [super viewWillAppear:animated];
  66. if (RQ_COMMON_MANAGER.YYXC_SERVICE_OPEN) {
  67. } else {
  68. //判断是否理论计时
  69. if (myDelegate.isLogin) {
  70. [self getStuSignFlag];
  71. }
  72. }
  73. }
  74. - (void)viewWillDisappear:(BOOL)animated {
  75. [super viewWillDisappear:animated];
  76. if (RQ_COMMON_MANAGER.YYXC_SERVICE_OPEN) {
  77. } else {
  78. [self setHidesBottomBarWhenPushed:NO];
  79. }
  80. }
  81. - (void)viewDidLayoutSubviews {
  82. [super viewDidLayoutSubviews];
  83. self.pagerView.frame = CGRectMake(0, RQ_APPLICATION_TOP_BAR_HEIGHT, RQ_SCREEN_WIDTH, RQ_SCREEN_HEIGHT - RQ_APPLICATION_TOP_BAR_HEIGHT - RQ_APPLICATION_TAB_BAR_HEIGHT - (RQ_COMMON_MANAGER.YYXC_SERVICE_OPEN? 0 : RQ_APPLICATION_SAFEAREA_BOTTOM_HEIGHT));
  84. }
  85. - (void)dealloc{
  86. //移除指定的通知,不然会造成内存泄露
  87. [[NSNotificationCenter defaultCenter] removeObserver:self name:@"Tiku_Change" object:nil];
  88. }
  89. #pragma mark - PrivateMethods
  90. /// 初始化
  91. - (void)rq_setup {
  92. /// set up ...
  93. [self.view addSubview:self.pagerView];
  94. if (RQ_COMMON_MANAGER.YYXC_SERVICE_OPEN) {
  95. //头像
  96. CGFloat sBoader = (kNavBarHeight - 35)/2.0;
  97. UIButton *sideBtn = [[UIButton alloc] initWithFrame:CGRectMake(sBoader, kStatusHeight + sBoader, kNavBarHeight - sBoader*2, kNavBarHeight - sBoader*2)];
  98. [self.view addSubview:sideBtn];
  99. UIImageView *iv = [[UIImageView alloc] initWithFrame:sideBtn.bounds];
  100. iv.image = [UIImage imageNamed:@"drawer_head"];
  101. iv.contentMode = UIViewContentModeScaleAspectFill;
  102. [iv borderColor:defGreen width:1 cornorRadios:6];
  103. [iv setRound];
  104. [sideBtn addSubview:iv];
  105. [sideBtn addTarget:self action:@selector(showLeftViewAction) forControlEvents:UIControlEventTouchUpInside];
  106. UIBarButtonItem* bbi0 = [[UIBarButtonItem alloc] initWithCustomView:sideBtn];
  107. self.navigationItem.leftBarButtonItem = bbi0;
  108. } else {
  109. [[RACObserve(defUser, userDict) distinctUntilChanged] subscribeNext:^(NSDictionary *dic) {
  110. //头像
  111. CGFloat sBoader = (kNavBarHeight - 35)/2.0;
  112. UIButton *sideBtn = [[UIButton alloc] initWithFrame:CGRectMake(sBoader, kStatusHeight + sBoader, kNavBarHeight - sBoader*2, kNavBarHeight - sBoader*2)];
  113. [self.view addSubview:sideBtn];
  114. UIImageView *iv = [[UIImageView alloc] initWithFrame:sideBtn.bounds];
  115. [iv sd_setImageWithURL:[NSURL URLWithString:dic[@"photo"]] placeholderImage:[UIImage imageNamed:@"drawer_head"]];
  116. iv.contentMode = UIViewContentModeScaleAspectFill;
  117. [iv borderColor:defGreen width:1 cornorRadios:6];
  118. [iv setRound];
  119. [sideBtn addSubview:iv];
  120. [sideBtn addTarget:self action:@selector(showLeftViewAction) forControlEvents:UIControlEventTouchUpInside];
  121. UIBarButtonItem* bbi0 = [[UIBarButtonItem alloc] initWithCustomView:sideBtn];
  122. self.navigationItem.leftBarButtonItem = bbi0;
  123. }];
  124. //检测本地是否有学时未上传 如果有不能进行任何操作
  125. if (myDelegate.isLogin && defUser.isycbd != 1) {
  126. NSString *pxkm = defUser.userDict[@"pxjd"];
  127. if (pxkm.length < 1) {
  128. pxkm = @"1";
  129. }
  130. NSArray* trainArray = [DB_Helper quearyTrain:defUser.userStuId Subject:pxkm];
  131. if (trainArray.count > 0) {
  132. UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"您本地有未上传学时,请确认上传!" preferredStyle:UIAlertControllerStyleAlert];
  133. UIAlertAction *saveAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  134. [self uploadMoreTrainRecordWithArray:trainArray];
  135. }];
  136. [alert addAction:saveAction];
  137. [self presentViewController:alert animated:YES completion:nil];
  138. }
  139. }
  140. //二维码扫描登陆网页
  141. UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"erWeiMa.png"] originImageScaleToSize:CGSizeMake(22.5, 22.5)] style:UIBarButtonItemStyleDone target:self action:@selector(clickToScan)];
  142. item.tintColor = defGreen;
  143. [self.navigationItem setRightBarButtonItem:item];
  144. }
  145. // if (myDelegate.isSyn) {
  146. // myDelegate.isSyn = NO;
  147. //
  148. // if ([myDelegate.markQuestionTableData isKindOfClass:[NSMutableArray class]]) {
  149. // if (myDelegate.markQuestionTableData.count == 0) {
  150. // [DB_Que_Helper moveIsDoneToMarkQuestion];//移动已做题
  151. // if (myDelegate.isLogin)//更新版本 先做一次同步
  152. // {
  153. // [self syncQuestion];
  154. // }
  155. // }
  156. // }
  157. // }
  158. //监听题库变化
  159. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction:) name:@"Tiku_Change" object:nil];
  160. //查看是否在进行集中式理论学习
  161. _isNeedTest = NO;
  162. _maxTime = 0;
  163. // 注册手势驱动
  164. __weak typeof(self)weakSelf = self;
  165. [self cw_registerShowIntractiveWithEdgeGesture:YES transitionDirectionAutoBlock:^(CWDrawerTransitionDirection direction) {
  166. if (direction == CWDrawerTransitionFromLeft) { // 左侧滑出
  167. [weakSelf defaultAnimationFromLeft];
  168. }
  169. }];
  170. }
  171. - (void)notificationAction:(NSNotification *)notification{
  172. self.pagerView.defaultSelectedIndex = 1;
  173. self.categoryView.defaultSelectedIndex = 1;
  174. [self.pagerView reloadData];
  175. [self.categoryView reloadData];
  176. self.pagerView.isListHorizontalScrollEnabled = ![defUser.isZhiGeZheng isEqualToString:@"YES"];
  177. if ([notification.userInfo[@"zhigezhengChanged"] isEqualToString:@"NO"]) {
  178. return;
  179. }
  180. }
  181. /**显示左边抽屉
  182. */
  183. - (void)showLeftViewAction {
  184. [self defaultAnimationFromLeft];
  185. }
  186. - (void)clickToScan {
  187. if (!myDelegate.isLogin) {
  188. [LoadingView showMsg:@"请登录后操作"];
  189. [LoginViewController loginFromVC:self];
  190. return;
  191. }
  192. ScanVC *scan = [[ScanVC alloc] init];
  193. scan.type = @"1";
  194. [scan scanBlock:^(NSDictionary *dic) {
  195. //模拟
  196. if ([dic[@"scanType"] isEqualToString:@"MNQTrain"]) {
  197. // 成功
  198. //根据是否存在mnTrainType判断本地记录的学时编号等数据是否与服务器同步过(即登录完调的状态接口成功与否)
  199. if (myDelegate.mnTrainType) {
  200. myDelegate.mnTrainType = @"2";//已经登录未人脸验证
  201. UINavigationController *nav = [LoginViewController getPeriodVCWithName:@"MNQtTrainVC"];
  202. if (nav) {
  203. nav.modalPresentationStyle = UIModalPresentationFullScreen;
  204. [self presentViewController:nav animated:YES completion:nil];
  205. }
  206. }else{
  207. [MBProgressHUD showMessage:@"正在获取当前训练状态" toView:self.view];
  208. //这个主要目的是为了更新本地学时编号等数据
  209. [LoginViewController getCurrentStateWithCompleteBlock:^(NSDictionary *root) {
  210. [MBProgressHUD hideHUDForView:self.view animated:NO];
  211. if (!root) {
  212. ShowMsg(@"请求失败");
  213. return;
  214. }
  215. if ([root[@"code"] isEqualToString:@"0"]) {
  216. UINavigationController *nav = [LoginViewController getPeriodVCWithName:@"MNQtTrainVC"];
  217. if (nav) {
  218. nav.modalPresentationStyle = UIModalPresentationFullScreen;
  219. [self presentViewController:nav animated:YES completion:nil];
  220. }
  221. }else{
  222. ShowMsg(root[@"msg"]);
  223. }
  224. }];
  225. }
  226. return;
  227. }
  228. //理论扫码
  229. NSInteger isNeed = 1;
  230. for (NSDictionary * dic in defUser.userDict[@"params"]) {
  231. if ([dic[@"KEY"] isEqualToString:@"SP_VERIFY_IMEI"]) {
  232. isNeed = [dic[@"VALUE"] integerValue];
  233. }
  234. }
  235. NSString *IMEI = defUser.userDict[@"imei"];
  236. if (IMEI.length > 0) {
  237. if (isNeed == 1) {
  238. if ([Tools getIDFAWithType:GetIDFAType_Default]) {
  239. if (![IMEI isEqualToString:[Tools getIDFAWithType:GetIDFAType_Default]]) {
  240. ShowMsg(@"请用本人手机进行理论计时");
  241. return;
  242. }
  243. }
  244. }else{
  245. [Tools saveNotBindImeiLogWithType:@"1" block:^(BOOL isSuccess) {
  246. }];//操作类型(1理论设备扫码,2远程计时,3模拟终端,4大车)

  247. }
  248. }else {
  249. UIAlertController *alertFind = [UIAlertController alertControllerWithTitle:nil message:@"您暂未绑定学员账号,是否绑定?" preferredStyle:UIAlertControllerStyleAlert];
  250. [alertFind addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
  251. [alertFind addAction:[UIAlertAction actionWithTitle:@"去绑定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  252. ThirdLoginBindYunGuanVC *vc = [[ThirdLoginBindYunGuanVC alloc] init];
  253. [self navPushHideTabbarToVC:vc];
  254. }]];
  255. [self presentViewController:alertFind animated:true completion:nil];
  256. return;
  257. }
  258. _isCloseAudio = YES;
  259. _scanType = dic[@"scanType"];
  260. _scanData = dic[@"dataString"];
  261. if ([dic[@"scanType"] intValue] == 2) {
  262. UIAlertController *alertFind = [UIAlertController alertControllerWithTitle:nil message:@"是否结束理论学习?" preferredStyle:UIAlertControllerStyleAlert];
  263. [alertFind addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
  264. [alertFind addAction:[UIAlertAction actionWithTitle:@"结束计时" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  265. [self getMyLocation];
  266. }]];
  267. [self presentViewController:alertFind animated:true completion:nil];
  268. }else {
  269. [self getMyLocation];
  270. }
  271. }];
  272. [self navPushHideTabbarToVC:scan];
  273. [MBProgressHUD showMessage:@"正在获取当前位置..." toView:self.view];
  274. [[MapManager sharedManager] updateLocationWithCompleteBlock:^(BOOL success, CLLocation *location) {
  275. [MBProgressHUD hideHUDForView:self.view animated:YES];
  276. if (success) {
  277. _myLocation = location.coordinate;
  278. // [self takePhoto];
  279. [self getQgCode];
  280. }
  281. }];
  282. }
  283. //更新第一次进入同步数据
  284. - (void)syncQuestion {
  285. if (![Util connectedToNetWork]) {
  286. return;
  287. }
  288. [self getMyQuestionType:@"" Subject:@""];
  289. }
  290. - (void)getMyQuestionType:(NSString*)type Subject:(NSString*)subject {
  291. NSMutableArray *arr = [NSMutableArray array];
  292. [arr addPro:@"user" Value:defUser.userDict[@"id"]];
  293. [arr addPro:@"outId" Value:defUser.userStuId];
  294. [arr addPro:@"type" Value:type];
  295. [arr addPro:@"subject" Value:subject];
  296. [arr addPro:@"carType" Value:defUser.car_type];
  297. [arr addPro:@"isPage" Value:@"0"];
  298. [arr addPro:@"pageSize" Value:@"0"];
  299. [arr addPro:@"currentPage" Value:@"0"];
  300. NSString* method = @"getMyQuestionFavs";
  301. [MBProgressHUD rq_showProgressHUD:@"收藏、错题同步中,请稍后..."];
  302. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary *root) {
  303. //NSLog(@"同步错题收藏---->%@--->%@",arr,root);
  304. if (!root || [root[@"code"] integerValue] == 1) {
  305. [MBProgressHUD rq_hideHUD];
  306. ShowMsg(@"题库错题、收藏、排除同步失败,请在侧栏手动同步");
  307. return;
  308. }
  309. NSArray *body = [root objectForKey:@"body"];
  310. if (body.count > 0) {
  311. if ([DB_Que_Helper deleteAllMarkQuestion]) {
  312. [DB_Que_Helper setMarkQuestionWithArray:body];
  313. }
  314. }
  315. [MBProgressHUD rq_hideHUD];
  316. [MBProgressHUD rq_showTips:@"题库错题、收藏、排除已同步完毕"];
  317. }];
  318. }
  319. // 仿QQ从左侧划出
  320. - (void)defaultAnimationFromLeft {
  321. // 强引用leftVC,不用每次创建新的,也可以每次在这里创建leftVC,抽屉收起的时候会释放掉
  322. // [self cw_showDefaultDrawerViewController:self.leftVC];
  323. CWLateralSlideConfiguration *conf = [CWLateralSlideConfiguration configurationWithDistance:kCWSCREENWIDTH * 0.87 maskAlpha:0.4 scaleY:1 direction:CWDrawerTransitionFromLeft backImage:nil];
  324. // 或者这样调用
  325. [self cw_showDrawerViewController:self.leftVC animationType:CWDrawerAnimationTypeMask configuration:conf];
  326. }
  327. #pragma mark - JXPagerViewDelegate
  328. - (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView {
  329. return [UIView new];
  330. }
  331. - (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView {
  332. return 0.f;
  333. }
  334. - (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
  335. return [defUser.isZhiGeZheng isEqualToString:@"YES"]? 0.f : 49.f;
  336. }
  337. - (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
  338. return self.categoryView;
  339. }
  340. - (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView {
  341. //和categoryView的item数量一致
  342. return self.categoryView.titles.count;
  343. }
  344. - (id<JXPagerViewListViewDelegate>)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index {
  345. myDelegate.subject = [NSString stringWithFormat:@"%d",(int)index];
  346. NSInteger myIndex = (index > 0 && index < 5)? index - 1 : 1;
  347. RQ_YDTQuestion_Module.subject = myIndex;
  348. RQ_SHARE_FUNCTION.myErorNum = [RQ_YDTQuestion_Module getQuestionWithExerciseType:RQExerciseType_Wrong].count;
  349. switch (index) {
  350. case 0: {
  351. HmV0 *vc = [[HmV0 alloc] init];
  352. return vc;
  353. }
  354. case 1:
  355. case 2:
  356. case 3:
  357. case 4:{
  358. RQHomePageSubjectOneOrFourViewModel *homePageSubjectFourViewModel = [[RQHomePageSubjectOneOrFourViewModel alloc] initWithServices:self.viewModel.services params:@{RQHomePageCarTypeKey : @(RQHomePageCarType_Car), RQHomePageSubjectTypeKey : @(index - 1)}];
  359. RQHomePageSubjectOneOrFourViewController *homePageSubjectFourViewController = [[RQHomePageSubjectOneOrFourViewController alloc] initWithViewModel:homePageSubjectFourViewModel];
  360. return homePageSubjectFourViewController;
  361. }
  362. case 5: {
  363. HmV5 *vc = [[HmV5 alloc] init];
  364. return vc;
  365. }
  366. default:
  367. return nil;
  368. }
  369. }
  370. #pragma mark - JXCategoryViewDelegate
  371. - (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
  372. RQ_YDTQuestion_Module.subject = (index > 0 && index < 5)? index - 1 : 1;
  373. RQ_SHARE_FUNCTION.myErorNum = [RQ_YDTQuestion_Module getQuestionWithExerciseType:RQExerciseType_Wrong].count;
  374. myDelegate.subject = [NSString stringWithFormat:@"%d",(int)index];
  375. self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0);
  376. }
  377. - (void)categoryView:(JXCategoryBaseView *)categoryView didClickSelectedItemAtIndex:(NSInteger)index {
  378. }
  379. - (void)categoryView:(JXCategoryBaseView *)categoryView didScrollSelectedItemAtIndex:(NSInteger)index {
  380. }
  381. #pragma mark - JXPagerMainTableViewGestureDelegate
  382. - (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
  383. if ([self checkIsNestContentScrollView:(UIScrollView *)gestureRecognizer.view] || [self checkIsNestContentScrollView:(UIScrollView *)otherGestureRecognizer.view]) {
  384. //如果交互的是嵌套的contentScrollView,证明在左右滑动,就不允许同时响应
  385. return NO;
  386. }
  387. return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
  388. }
  389. - (BOOL)checkIsNestContentScrollView:(UIScrollView *)scrollView {
  390. for (RQHomeSubPageViewController *list in self.pagerView.validListDict.allValues) {
  391. if (list.contentScrollView == scrollView) {
  392. return YES;
  393. }
  394. }
  395. return NO;
  396. }
  397. #pragma mark - SDCycleScrollViewDelegate
  398. - (void)cycleScrollView:(SDCycleScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index {
  399. }
  400. #pragma mark - LazyLoad
  401. - (JXPagerView *)pagerView {
  402. if (!_pagerView) {
  403. _pagerView = [[JXPagerView alloc] initWithDelegate:self];
  404. _pagerView.mainTableView.gestureDelegate = self;
  405. _pagerView.defaultSelectedIndex = 1;
  406. _pagerView.mainTableView.bounces = NO;
  407. }
  408. return _pagerView;
  409. }
  410. - (JXCategoryTitleView *)categoryView {
  411. if (!_categoryView) {
  412. _categoryView = [[JXCategoryTitleView alloc] init];
  413. _categoryView.titles = self.titles;
  414. _categoryView.backgroundColor = [UIColor whiteColor];
  415. _categoryView.titleSelectedColor = RQ_MAIN_TEXT_COLOR_1;
  416. _categoryView.titleColor = RQ_MAIN_TEXT_COLOR_2;
  417. _categoryView.titleFont = RQRegularFont(13);
  418. _categoryView.titleSelectedFont = RQRegularFont(15);
  419. _categoryView.titleColorGradientEnabled = YES;
  420. _categoryView.titleLabelZoomEnabled = NO;
  421. _categoryView.contentScrollViewClickTransitionAnimationEnabled = NO;
  422. _categoryView.titleLabelZoomSelectedVerticalOffset = 0.0f;
  423. JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init];
  424. lineView.indicatorColor = RQ_MAIN_COLOR;
  425. lineView.indicatorHeight = 4;
  426. lineView.verticalMargin = 0;
  427. _categoryView.indicators = @[lineView];
  428. _categoryView.defaultSelectedIndex = 0;
  429. _categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listContainerView;
  430. _categoryView.delegate = self;
  431. _categoryView.defaultSelectedIndex = 1;
  432. }
  433. return _categoryView;
  434. }
  435. - (LeftViewController *)leftVC {
  436. if (_leftVC == nil) {
  437. _leftVC = [LeftViewController new];
  438. }
  439. return _leftVC;
  440. }
  441. - (NSArray<NSString *> *)titles {
  442. return @[@"报名", @"科一", @"科二", @"科三", @"科四", @"拿本"];
  443. }
  444. #pragma mark - PrivateMethods
  445. //获取当前学员计时状态
  446. - (void)getStuSignFlag {
  447. if (![Util connectedToNetWork]) {
  448. return;
  449. }
  450. NSString *stuId = defUser.userDict[@"outId"];
  451. if (!stuId || stuId.length == 0) {
  452. return;
  453. }
  454. NSMutableArray *arr=[NSMutableArray array];
  455. [arr addPro:@"stuId" Value:stuId];
  456. [arr addPro:@"dqbh" Value:defUser.userDict[@"city"]];
  457. NSString* method = @"getStuSignFlag";
  458. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  459. if (!root || [root[@"code"] integerValue] == 1) {
  460. return;
  461. }
  462. //这里接收服务器返回状态 当前训练培训训练状态 0 未签到 4集中理论签到中
  463. // if ([[root[@"body"] objectForKey:@"status"] integerValue] == 0) {
  464. // //还没开始集中式理论
  465. //
  466. // }
  467. // if ([[root[@"body"] objectForKey:@"status"] integerValue] == 4) {
  468. // //集中式理论学习中
  469. // }
  470. if ([[root[@"body"] objectForKey:@"theoryVerify"] integerValue] == 1) {
  471. //开启过程验证
  472. _isNeedTest = YES;
  473. }else {
  474. //关闭过程验证
  475. _isNeedTest = NO;
  476. }
  477. NSInteger newTime = [[root[@"body"] objectForKey:@"timre"] integerValue];
  478. _maxTime = [[root[@"body"] objectForKey:@"theoryTime"] integerValue];
  479. if ([[root[@"body"] objectForKey:@"status"] integerValue] == 4) {//已经签到 集中式计时中
  480. myDelegate.trainStateLabel.text = @"理论学习中...";
  481. if (_isNeedTest) {
  482. if (_maxTime > newTime) {
  483. [self setNotificationWithFireTime:_maxTime - newTime withType:LocalNotificationTypeTheory];
  484. }else {
  485. myDelegate.trainStateLabel.text = @"请扫描过程验证二维码";
  486. if (_isCloseAudio) {
  487. _isCloseAudio = NO;
  488. }else {
  489. [Tools playAudioWithString:@"请扫描过程验证二维码"];
  490. }
  491. }
  492. }
  493. }else {
  494. myDelegate.trainStateLabel.text = @"";
  495. }
  496. }];
  497. }
  498. //语音播报或者推送
  499. - (void)setNotificationWithFireTime:(NSInteger)fireTime withType:(LocalNotificationType)localNotificationType{
  500. switch (localNotificationType) {
  501. /// 课堂
  502. case LocalNotificationTypeTheory: {
  503. NSString *identifierStr = @"Theory";
  504. /// 间隔时间大于5分钟(300秒)
  505. if (fireTime >= 300) {
  506. NSInteger timeInterval = fireTime - 300;
  507. // if (DEBUG) {
  508. // timeInterval = 120;
  509. // }
  510. [RQ_LocalNoti_Manager removeNotificationWithIdentifierID:identifierStr];
  511. [RQ_LocalNoti_Manager addLocalNotificationWithTitle:@"优易学车提醒您" subTitle:@"5分钟后将超过验证时间,请提前扫码验证" body:[RQ_SHARE_FUNCTION getCurrentTimeStringWithTimeStamp:timeInterval] timeInterval:timeInterval identifier:identifierStr userInfo:@{@"identifier" : identifierStr , @"message" : @"即将超过验证时间,请提前扫码验证"} repeats:0];
  512. } else {
  513. [RQ_LocalNoti_Manager removeNotificationWithIdentifierID:identifierStr];
  514. [RQ_LocalNoti_Manager addLocalNotificationWithTitle:@"优易学车提醒您" subTitle:@"即将超过验证时间,请提前扫码验证" body:[RQ_SHARE_FUNCTION getCurrentTimeStringWithTimeStamp:0] timeInterval:0 identifier:identifierStr userInfo:@{@"identifier" : identifierStr , @"message" : @"即将超过验证时间,请提前扫码验证"} repeats:0];
  515. }
  516. break;
  517. }
  518. /// 模拟
  519. case LocalNotificationTypSsimulation: {
  520. //移除旧的通知
  521. if ([[[UIApplication sharedApplication] scheduledLocalNotifications] count] > 0) {
  522. [[UIApplication sharedApplication] cancelAllLocalNotifications];
  523. }
  524. //定义本地通知对象
  525. UILocalNotification *notification = [[UILocalNotification alloc]init];
  526. //设置调用时间
  527. notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:fireTime];
  528. //设置通知属性
  529. notification.alertBody = @"优易学车提醒您"; //通知主体
  530. notification.applicationIconBadgeNumber = 1;//应用程序图标右上角显示的消息数
  531. notification.alertAction = @"打开应用"; //待机界面的滑动动作提示
  532. notification.soundName = @"TrainTest.mp3";//收到通知时播放的声音,默认消息声音
  533. // 通知参数
  534. NSDictionary *userDict = [NSDictionary dictionaryWithObjectsAndKeys:@"nothing",@"ShiCaoPeriodVC_reTakePhoto", nil];
  535. notification.userInfo = userDict;
  536. //调用通知
  537. [[UIApplication sharedApplication] scheduleLocalNotification:notification];
  538. break;
  539. }
  540. default:
  541. break;
  542. }
  543. }
  544. - (void)cancelLocalNotificationWithType:(LocalNotificationType)localNotificationType {
  545. switch (localNotificationType) {
  546. /// 课堂
  547. case LocalNotificationTypeTheory: {
  548. NSString *identifierStr = @"Theory";
  549. [RQ_LocalNoti_Manager removeNotificationWithIdentifierID:identifierStr];
  550. break;
  551. }
  552. /// 模拟
  553. case LocalNotificationTypSsimulation: {
  554. //移除旧的通知
  555. if ([[[UIApplication sharedApplication] scheduledLocalNotifications] count] > 0) {
  556. [[UIApplication sharedApplication] cancelAllLocalNotifications];
  557. }
  558. break;
  559. }
  560. default:
  561. break;
  562. }
  563. }
  564. - (void)getMyLocation {
  565. //定位功能
  566. [MBProgressHUD showMessage:@"正在获取当前位置..." toView:self.view];
  567. [[MapManager sharedManager] updateLocationWithCompleteBlock:^(BOOL success, CLLocation *location) {
  568. [MBProgressHUD hideHUDForView:self.view animated:YES];
  569. if (success) {
  570. self.myLocation = location.coordinate;
  571. [self studentQrcode];
  572. }
  573. }];
  574. }
  575. /** 扫描二维码调取接口 */
  576. - (void)studentQrcode
  577. {
  578. if (![Util connectedToNetWork]) {
  579. showMsgUnconnect();
  580. return;
  581. }
  582. if (_myLocation.longitude == 0.0) {
  583. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"位置获取失败,请重新扫描二维码!" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
  584. [alert show];
  585. return;
  586. }
  587. NSMutableArray *arr=[NSMutableArray array];
  588. [arr addPro:@"studentOutid" Value:defUser.userDict[@"outId"]];
  589. [arr addPro:@"qrcode" Value:_scanData];
  590. [arr addPro:@"dqbh" Value:defUser.userDict[@"city"]];
  591. [arr addPro:@"lng" Value:[NSString stringWithFormat:@"%f",_myLocation.longitude]];
  592. [arr addPro:@"lat" Value:[NSString stringWithFormat:@"%f",_myLocation.latitude]];
  593. // [arr addPro:@"lng" Value:@"123.907972"];
  594. // [arr addPro:@"lat" Value:@"41.887931"];
  595. [arr addPro:@"type" Value:_scanType];
  596. [arr addPro:@"telType" Value:@"ios"];
  597. if (_faceIdStr && ![_faceIdStr isEqualToString:@""]) {
  598. [arr addPro:@"faceId" Value:_faceIdStr];
  599. _faceIdStr = @"";
  600. }
  601. NSString *method = @"studentQrcode";
  602. NSString *str = [_scanType isEqualToString: @"1"] ? @"签到中...":@"签退中...";
  603. if ([_scanType isEqualToString: @"1"] ) {
  604. str = @"签到中...";
  605. }else if ([_scanType isEqualToString: @"2"]) {
  606. str = @"签退中...";
  607. }else if ([_scanType isEqualToString: @"3"]) {
  608. str = @"验证中...";
  609. }
  610. [MBProgressHUD showMessage:str toView:self.view];
  611. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  612. [MBProgressHUD hideHUDForView:self.view];
  613. if (!root) {
  614. ShowMsg(@"操作失败,请重试!");
  615. [Tools playAudioWithString:@"操作失败,请重试!"];
  616. return;
  617. }
  618. if ([root[@"code"] integerValue] == 0) {//代表操作成功
  619. if ([_scanType isEqualToString:@"1"] || [_scanType isEqualToString:@"3"]) {
  620. myDelegate.trainStateLabel.text = @"理论学习中...";
  621. }
  622. if ([_scanType isEqualToString:@"2"]) {
  623. myDelegate.trainStateLabel.text = @"";
  624. }
  625. // if (DEBUG) {
  626. // isNeedTest = YES;
  627. // }
  628. if (_isNeedTest) {
  629. switch ([_scanType integerValue]) { //1、签到 2、签退 3、过程验证
  630. case 1://签到成功
  631. if (_maxTime > 0) {
  632. [self setNotificationWithFireTime:_maxTime withType:LocalNotificationTypeTheory];
  633. }
  634. break;
  635. case 2://签退
  636. [self cancelLocalNotificationWithType:LocalNotificationTypeTheory];
  637. break;
  638. case 3://验证成功
  639. if (_maxTime > 0) {
  640. [self setNotificationWithFireTime:_maxTime withType:LocalNotificationTypeTheory];
  641. }
  642. break;
  643. default:
  644. break;
  645. }
  646. }
  647. }
  648. if ([root[@"code"] integerValue] == 2) {//距离理论教室位置较远
  649. NSString *str = root[@"msg"];
  650. if (str.length < 1) {
  651. return;
  652. }
  653. NSArray *mapArray = [str componentsSeparatedByString:@";"];
  654. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:[mapArray lastObject] preferredStyle:UIAlertControllerStyleAlert];
  655. [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]];
  656. [alert addAction:[UIAlertAction actionWithTitle:@"查看位置详情" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  657. //进入地图页面 传入两个点 一个距离 lng lat len
  658. if (mapArray.count > 3) {
  659. // lng = 123.467129,
  660. // lat = 41.813997
  661. //122.769684;41.515881;66822;您当前距离理论教室位置66822米,请到理论教室扫码!
  662. DistenceTooLongMapVC *mapVC = [[DistenceTooLongMapVC alloc] init];
  663. mapVC.lat1 = _myLocation.latitude;
  664. mapVC.lng1 = _myLocation.longitude;
  665. mapVC.lat2 = [mapArray[1] floatValue];
  666. mapVC.lng2 = [mapArray[0] floatValue];
  667. mapVC.distence = mapArray[2];
  668. mapVC.skipMspBlock = ^{
  669. _myLocation.longitude = 0.0;
  670. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"位置已重置,请重新扫描二维码!" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
  671. [alert show];
  672. };
  673. [self navPushHideTabbarToVC:mapVC];
  674. }
  675. }]];
  676. [self presentViewController:alert animated:true completion:nil];
  677. return;
  678. }
  679. // 需要进行人脸比对
  680. if ([root[@"code"] integerValue] == 99) {
  681. [self takePhoto];
  682. return;
  683. }
  684. [Tools playAudioWithString:root[@"msg"]];
  685. ShowMsg(root[@"msg"]);
  686. }];
  687. }
  688. // 人脸比对
  689. - (void)takePhoto {
  690. UIStoryboard * board = [UIStoryboard storyboardWithName:@"LivenessDetection" bundle:nil];
  691. OliveappLivenessDetectionViewController * livenessDetectionViewController;
  692. livenessDetectionViewController = (OliveappLivenessDetectionViewController *)[ board instantiateViewControllerWithIdentifier:@"LivenessDetectionStoryboard"];
  693. livenessDetectionViewController.modalPresentationStyle = 0;
  694. livenessDetectionViewController.faceDelegate = self;
  695. OliveappSessionManagerConfig* config = [OliveappSessionManagerConfig new];
  696. // config.timeoutMs = 100000;
  697. [config usePredefinedConfig: 4]; // 这里配置检测步骤
  698. livenessDetectionViewController.cusConfig = config;
  699. NSError *error;
  700. BOOL isSuccess = [livenessDetectionViewController setConfigLivenessDetection:self withError: &error];
  701. if (isSuccess){
  702. [self presentViewController:livenessDetectionViewController animated:YES completion:nil];
  703. }
  704. }
  705. - (void)onLivenessSuccess:(OliveappDetectedFrame *)detectedFrame{
  706. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  707. [self dismissViewControllerAnimated:YES completion:nil];
  708. });
  709. }
  710. - (void)onLivenessFail:(int)sessionState withDetectedFrame:(OliveappDetectedFrame *)detectedFrame{
  711. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  712. [self dismissViewControllerAnimated:YES completion:nil];
  713. UIAlertController *actionsheet = [UIAlertController alertControllerWithTitle:@"提示" message:@"获取人脸失败,是否重新进行人脸比对" preferredStyle:UIAlertControllerStyleAlert];
  714. UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"是" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  715. [self takePhoto];
  716. }];
  717. UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"否" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  718. }];
  719. [actionsheet addAction:action1];
  720. [actionsheet addAction:action2];
  721. [self presentViewController:actionsheet animated:YES completion:nil];
  722. });
  723. }
  724. - (void)onLivenessCancel{
  725. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  726. [self dismissViewControllerAnimated:YES completion:nil];
  727. });
  728. }
  729. - (void)sendFaceImage:(UIImage *)faceImage {
  730. UIImage *normalImage = [UIImage fixOrientation:faceImage];
  731. NSData *imgData = UIImageJPEGRepresentation(normalImage, .2f);
  732. NSString *backString = [NSString stringWithFormat:@"%@",[OliveappBase64Helper encode:imgData]];
  733. [self face2faceTheoryWithPhotoStr:backString ResultBlock:^(NSString *faceId) {
  734. if (![faceId isEqualToString:@""]) {
  735. _faceIdStr = faceId;
  736. [self studentQrcode];
  737. }
  738. }];
  739. }
  740. - (void)sendFaceImageError {
  741. }
  742. - (void)face2faceTheoryWithPhotoStr:(NSString *)photoStr ResultBlock:(void (^)(NSString *faceId))resultBlock {
  743. if (![Util connectedToNetWork]) {
  744. showMsgUnconnect();
  745. return;
  746. }
  747. if (_myLocation.longitude == 0.0) {
  748. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"位置获取失败,请重新扫描二维码!" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
  749. [alert show];
  750. return;
  751. }
  752. NSMutableArray *arr=[NSMutableArray array];
  753. [arr addPro:@"stunum" Value:defUser.userDict[@"stuNum"]];
  754. [arr addPro:@"dqbh" Value:defUser.userDict[@"city"]];
  755. [arr addPro:@"outId" Value:defUser.userDict[@"outId"]];
  756. [arr addPro:@"lng" Value:[NSString stringWithFormat:@"%f",_myLocation.longitude]];
  757. [arr addPro:@"lat" Value:[NSString stringWithFormat:@"%f",_myLocation.latitude]];
  758. [arr addPro:@"photo" Value:photoStr];
  759. NSString *method = @"face2faceTheory";
  760. [MBProgressHUD showHUDAddedTo:self.view animated:YES];
  761. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  762. [MBProgressHUD hideHUDForView:self.view];
  763. if (!root) {
  764. ShowMsg(@"操作失败,请重试!");
  765. [Tools playAudioWithString:@"操作失败,请重试!"];
  766. return;
  767. }
  768. if ([root[@"code"] integerValue] == 0) {//代表操作成功
  769. if (resultBlock && root[@"data"][@"faceId"]) {
  770. resultBlock(root[@"data"][@"faceId"]);
  771. }
  772. }
  773. [Tools playAudioWithString:root[@"msg"]];
  774. ShowMsg(root[@"msg"]);
  775. }];
  776. }
  777. - (void)uploadMoreTrainRecordWithArray:(NSArray *)trainArray
  778. {
  779. if (![Util connectedToNetWork]) {
  780. showMsgUnconnect();
  781. return;
  782. }
  783. NSString* str = @"";
  784. for (TrainRecord *record in trainArray) {
  785. str = [str stringByAppendingString:[NSString stringWithFormat:@"%@,%@,%@,%@;",record.studentId,record.beginTime,record.endTime,record.trainTime]];
  786. }
  787. TrainRecord *record = [trainArray firstObject];
  788. NSMutableArray *arr=[NSMutableArray array];
  789. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"ios",@"trainType", nil]];
  790. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:[DES3Util encrypt:str ],@"trainRecord", nil]];
  791. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:record.subject,@"pxkm", nil]];
  792. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:defUser.userDict[@"outId"],@"stuOutid", nil]];
  793. NSString* method = @"uploadMoreTrainRecord";
  794. [MBProgressHUD showLoadToView:self.view];
  795. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary *dict) {
  796. [MBProgressHUD hideHUDForView:self.view];
  797. if (!dict) {
  798. ShowMsg(@"上传学时失败!");
  799. return;
  800. }
  801. if ([dict[@"code"] isEqualToString:@"90"]) {
  802. UIAlertController *alertFind = [UIAlertController alertControllerWithTitle:nil message:dict[@"msg"] preferredStyle:UIAlertControllerStyleAlert];
  803. [alertFind addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  804. [LoginViewController loginFromVC:self];
  805. }]];
  806. [self presentViewController:alertFind animated:true completion:nil];
  807. return;
  808. }
  809. if ([dict[@"code"] isEqualToString:@"1"]) {
  810. ShowMsg(dict[@"body"]);
  811. return;
  812. }
  813. if ( [dict[@"code"] isEqualToString:@"0"]) {
  814. for (TrainRecord *record in trainArray) {
  815. [DB_Helper updateTrainState:record];
  816. }
  817. UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"上传学时成功!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
  818. [alert show];
  819. }
  820. }];
  821. }
  822. - (void)getQgCode {
  823. if (![Util connectedToNetWork]) {
  824. showMsgUnconnect();
  825. return;
  826. }
  827. NSMutableArray *arr=[NSMutableArray array];
  828. [arr addPro:@"dqbh" Value:@"2101"];
  829. [arr addPro:@"sim" Value:@"12101000042"];
  830. [arr addPro:@"roomId" Value:@"343"];
  831. [arr addPro:@"coachNum" Value:@"3623240296803372"];
  832. [arr addPro:@"type" Value:@"3"];
  833. NSString *method = @"getQgCode";
  834. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  835. }];
  836. }
  837. @end