RQTimingView.m 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. //
  2. // RQTimingView.m
  3. // XinShouJiaDao
  4. //
  5. // Created by 张嵘 on 2021/7/13.
  6. // Copyright © 2021 JCZ. All rights reserved.
  7. //
  8. #import "RQTimingView.h"
  9. #import "RQConfigureManager.h"
  10. #import "RQControllerHelper.h"
  11. #import "FLAnimatedImageView.h"
  12. #import "FLAnimatedImage.h"
  13. /// 显示状态的key
  14. static NSString * const RQTimingViewStatusKey = @"RQTimingViewStatusKey";
  15. @interface RQTimingView ()
  16. /// closeBtn
  17. @property (nonatomic, readwrite, weak) UIButton *closeBtn;
  18. /// 开始点
  19. @property (nonatomic, readwrite, assign) CGPoint startPoint;
  20. /// 背景图片
  21. @property (nonatomic, readwrite, strong) FLAnimatedImageView *bgImageView;
  22. /// GIF图片
  23. @property (nonatomic, readwrite, strong) FLAnimatedImage *animatedImage;
  24. /// Timer
  25. @property (nonatomic, readwrite, strong) NSTimer *timer;
  26. /// Count
  27. @property (nonatomic, readwrite, assign) NSUInteger seconds;
  28. /// Label
  29. @property (nonatomic, readwrite, strong) UILabel *timeLabel;
  30. /// Label
  31. @property (nonatomic, readwrite, strong) NSMutableArray *titleArr;
  32. /// 是否在计时
  33. @property (nonatomic, readwrite, assign , getter = isTiming) BOOL timing;
  34. /// 是否在动画
  35. @property (nonatomic, readwrite, assign , getter = isAnimated) BOOL animated;
  36. @property (nonatomic, readwrite, copy) NSString *secondString;
  37. @end
  38. @implementation RQTimingView
  39. @def_singleton(RQTimingView);
  40. #pragma mark - SystemMethods
  41. - (instancetype)initWithFrame:(CGRect)frame {
  42. self = [super initWithFrame:frame];
  43. if (self) {
  44. self.userInteractionEnabled = YES;
  45. self.backgroundColor = RQ_MAIN_COLOR;
  46. NSBundle *bundle = [NSBundle mainBundle];
  47. NSString *resourcePath = [bundle resourcePath];
  48. NSString *filePath = [resourcePath stringByAppendingPathComponent:@"1.gif"];
  49. self.bgImageView.image = [UIImage imageWithContentsOfFile:filePath];
  50. [self addSubview:self.bgImageView];
  51. [self addSubview:self.titleLabel];
  52. /// 添加tap手势
  53. [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapAction:)]];
  54. UIWindow *window = [UIApplication sharedApplication].keyWindow;
  55. [window addSubview:self];
  56. self.rq_x = [UIScreen mainScreen].bounds.size.width - self.rq_width - 20;
  57. self.rq_y = RQ_APPLICATION_TAB_BAR_HEIGHT + RQ_APPLICATION_NAV_BAR_HEIGHT + 44.f + 54.f;
  58. self.hidden = YES;
  59. }
  60. return self;
  61. }
  62. - (void)dealloc {
  63. [self.timer invalidate];
  64. self.timer = nil;
  65. }
  66. - (void)setHide:(BOOL)hide {
  67. if (self.isAnimated) return;
  68. [[NSUserDefaults standardUserDefaults] setBool:hide forKey:RQTimingViewStatusKey];
  69. [[NSUserDefaults standardUserDefaults] synchronize];
  70. hide?[self close]:[self open];
  71. }
  72. - (BOOL)isHide{
  73. BOOL temp = [[NSUserDefaults standardUserDefaults] boolForKey:RQTimingViewStatusKey];
  74. NSLog(@"++++ Touch View Is Hide %d ++++" , temp);
  75. return temp;
  76. }
  77. - (void)open{
  78. /// 动画开始,禁止交互
  79. self.userInteractionEnabled = NO;
  80. self.animated = YES;
  81. self.hidden = NO;
  82. self.transform = CGAffineTransformIdentity;
  83. self.transform = CGAffineTransformMakeScale(.2, .2);
  84. [UIView animateWithDuration:.25f delay:0 usingSpringWithDamping:.3f initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
  85. self.transform = CGAffineTransformMakeScale(1.0, 1.0);
  86. } completion:^(BOOL finished) {
  87. self.transform = CGAffineTransformIdentity;
  88. /// 动画结束,允许交互
  89. self.userInteractionEnabled = YES;
  90. self.animated = NO;
  91. }];
  92. }
  93. - (void)close{
  94. /// 动画开始,禁止交互
  95. self.animated = YES;
  96. self.userInteractionEnabled = NO;
  97. [UIView animateWithDuration:.25f animations:^{
  98. self.transform = CGAffineTransformMakeScale(.2, .2);
  99. } completion:^(BOOL finished) {
  100. self.transform = CGAffineTransformIdentity;
  101. self.hidden = YES;
  102. /// 动画结束,允许交互
  103. self.userInteractionEnabled = YES;
  104. self.animated = NO;
  105. }];
  106. }
  107. #pragma mark - Action
  108. - (void)_tapAction:(UITapGestureRecognizer *)tapGr {
  109. NSLog(@"%@",RQControllerHelper.currentViewController);
  110. BOOL isTakePhoto = [RQControllerHelper.currentViewController.className isEqualToString:@"CAMImagePickerCameraViewController"];
  111. if (isTakePhoto) {
  112. return;
  113. }
  114. LCActionSheet *actionSheet = [LCActionSheet sheetWithTitle:nil cancelButtonTitle:@"取消" didDismiss:^(LCActionSheet * _Nonnull actionSheet, NSInteger buttonIndex) {
  115. @weakify(self)
  116. switch (buttonIndex) {
  117. case 1: {
  118. if (_timer) {
  119. if (self.isTiming) {
  120. /// 暂停计时
  121. [self pauseTiming];
  122. } else {
  123. /// 继续计时
  124. [self continueTiming];
  125. }
  126. } else {
  127. //开始计时
  128. if (defUser.isycbd == 1) {
  129. [self startTimingWithResultBlock:^(BOOL isSuccess) {
  130. @strongify(self)
  131. if (isSuccess) {
  132. [self beginTiming];
  133. }
  134. }];
  135. } else {
  136. [self beginTime];
  137. }
  138. }
  139. break;
  140. }
  141. case 2: {
  142. if (defUser.isycbd == 1) {
  143. [self stopTimingWithResultBlock:^(BOOL isSuccessed) {
  144. @strongify(self)
  145. if (isSuccessed) {
  146. [self endTiming];
  147. }
  148. }];
  149. } else {
  150. [self stopTiming];
  151. }
  152. break;
  153. }
  154. default: break;
  155. }
  156. } otherButtonTitleArray:self.titleArr.copy];
  157. [actionSheet addSubview:self.timeLabel];
  158. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 300, RQ_SCREEN_WIDTH, 100)];
  159. label.backgroundColor = [UIColor clearColor];
  160. label.text = @"注:退出当前页面将结束计时,学时详情在“个人-我的学时”查看";
  161. label.textColor = UIColor.whiteColor;
  162. label.font = [UIFont systemFontOfSize:20 weight:UIFontWeightMedium];
  163. label.numberOfLines = 0;
  164. label.textAlignment = NSTextAlignmentCenter;
  165. [actionSheet addSubview:label];
  166. [actionSheet show];
  167. }
  168. #pragma mark - PrivateMethods
  169. - (void)rq_timerValueChanged {
  170. @weakify(self)
  171. self.seconds++;
  172. [self setSecondString:[NSString stringWithFormat:@"%d",(int)self.seconds]];
  173. if (defUser.isycbd == 1) {
  174. // NSString *pxkm = defUser.userDict[@"pxjd"];
  175. NSString *pxkm = myDelegate.subject;
  176. if (pxkm.length < 1) {
  177. pxkm = @"1";
  178. }
  179. if (([pxkm isEqualToString:@"2"] || [pxkm isEqualToString:@"3"])) {
  180. pxkm = @"4";
  181. }
  182. int remainder1 = (int)(self.seconds)%900;
  183. if (remainder1 == 0) {
  184. [self.timer setFireDate:[NSDate distantFuture]];
  185. SCLAlertView *alert = [[SCLAlertView alloc] initWithNewWindow];
  186. alert.backgroundViewColor = backGroundColor;
  187. alert.customViewColor = RQ_MAIN_COLOR;
  188. [alert addButton:@"立即开始 " actionBlock:^(void) {
  189. dispatch_async(dispatch_get_main_queue(), ^{
  190. @strongify(self)
  191. /// 1.本地活体检测
  192. [RQ_CHECKBODY_MANAGER beginCheckBodyWithCheckNum:defUser.ycbdFaceCount completeBlock:^(BOOL success, NSDictionary * _Nullable dic) {
  193. @strongify(self)
  194. if (success) {
  195. /// 2.线上活体检测
  196. [RQ_RemoteTheory_MANAGER edufaceTofaceWithPhotoStr:dic[@"normalImg"] loginFlagType:LoginFlagType_Process resultBlock:^(BOOL isSuccess, id dict) {
  197. @strongify(self)
  198. if (isSuccess) {
  199. NSString *timeStr = [self getTimes:self.seconds];
  200. /// 3.2上传过程照片
  201. if (dict) {
  202. NSDictionary *myDict = dict;
  203. NSString *imageUrlStr = myDict[@"body"];
  204. if (RQStringIsEmpty(imageUrlStr)) {
  205. ShowMsg(@"路径为空");
  206. }
  207. [RQ_RemoteTheory_MANAGER uploadEduPicWithClassidStr:self.classIdStr timeStr:timeStr actionPhotoStr:imageUrlStr loginFlagType:LoginFlagType_Process resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull uploadEduPicDict) {
  208. @strongify(self)
  209. if (isSuccess) {
  210. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"过程验证成功" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  211. @strongify(self)
  212. [self.timer setFireDate:[NSDate distantPast]];
  213. }];
  214. } else {
  215. self.seconds--;
  216. [self setSecondString:[NSString stringWithFormat:@"%d",(int)self.seconds]];
  217. [self.timer setFireDate:[NSDate distantPast]];
  218. }
  219. }];
  220. } else {
  221. self.seconds--;
  222. [self setSecondString:[NSString stringWithFormat:@"%d",(int)self.seconds]];
  223. [self.timer setFireDate:[NSDate distantPast]];
  224. }
  225. } else {
  226. self.seconds--;
  227. [self setSecondString:[NSString stringWithFormat:@"%d",(int)self.seconds]];
  228. [self.timer setFireDate:[NSDate distantPast]];
  229. }
  230. }];
  231. } else {
  232. self.seconds--;
  233. [self setSecondString:[NSString stringWithFormat:@"%d",(int)self.seconds]];
  234. [self.timer setFireDate:[NSDate distantPast]];
  235. }
  236. }];
  237. });
  238. }];
  239. [alert addTimerToButtonIndex:0 reverse:YES];
  240. [alert showNotice:@"温馨提示" subTitle:@"即将开始活体检测,请做好准备" closeButtonTitle:nil duration:5.0f];
  241. }
  242. }
  243. int hour = 0;
  244. int min = 0;
  245. int second = 0;
  246. int remainder = (int)self.seconds%60;
  247. if (remainder == 0)
  248. {
  249. //每1分钟保存一次
  250. [self saveTrain];
  251. }
  252. hour = (int)self.seconds / 3600;
  253. min = (int)self.seconds % 3600 / 60;
  254. second = (int)self.seconds % 3600 % 60;
  255. NSString *min_s;
  256. NSString *second_s;
  257. if (min<10) {
  258. min_s=[NSString stringWithFormat:@"0%d",min];
  259. }else{
  260. min_s=[NSString stringWithFormat:@"%d",min];
  261. }
  262. if (second<10) {
  263. second_s=[NSString stringWithFormat:@"0%d",second];
  264. }else{
  265. second_s=[NSString stringWithFormat:@"%d",second];
  266. }
  267. //更新UI上的时间
  268. self.timeLabel.text = [NSString stringWithFormat:@"0%d:%@:%@",hour,min_s,second_s];
  269. self.titleLabel.text = self.timeLabel.text;
  270. }
  271. #pragma mark - PublicMethods
  272. // 开始计时
  273. - (void)beginTiming {
  274. [self.timer fire];
  275. self.timing = YES;
  276. [_titleArr replaceObjectAtIndex:0 withObject:@"暂停计时"];
  277. self.bgImageView.animatedImage = self.animatedImage;
  278. }
  279. // 暂停计时
  280. - (void)pauseTiming {
  281. if (_timer) {
  282. [_timer setFireDate:[NSDate distantFuture]];
  283. self.timing = NO;
  284. [_titleArr replaceObjectAtIndex:0 withObject:@"继续计时"];
  285. [self.bgImageView stopAnimating];
  286. }
  287. }
  288. // 继续计时
  289. - (void)continueTiming {
  290. if (_timer) {
  291. [_timer setFireDate:[NSDate distantPast]];
  292. self.timing = YES;
  293. [_titleArr replaceObjectAtIndex:0 withObject:@"暂停计时"];
  294. [self.bgImageView startAnimating];
  295. }
  296. }
  297. // 结束计时
  298. - (void)endTiming {
  299. if (_timer) {
  300. [_timer invalidate];
  301. _timer = nil;
  302. self.timing = NO;
  303. self.seconds = 0;
  304. self.titleLabel.text = @"计时";
  305. self.timeLabel.text = @"00:00:00";
  306. [_titleArr replaceObjectAtIndex:0 withObject:@"开始计时"];
  307. }
  308. }
  309. #pragma mark - Override
  310. - (void)setFrame:(CGRect)frame{
  311. frame.size.width = 80;
  312. frame.size.height = 80;
  313. [super setFrame:frame];
  314. self.layer.cornerRadius = frame.size.width / 2.f;
  315. self.layer.masksToBounds = YES;
  316. }
  317. - (void)layoutSubviews{
  318. [super layoutSubviews];
  319. CGFloat closeBtnWH = 36;
  320. self.closeBtn.frame = CGRectMake(self.frame.size.width - closeBtnWH , 0, closeBtnWH, closeBtnWH);
  321. }
  322. #pragma mark - touch move
  323. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  324. //保存触摸起始点位置
  325. CGPoint point = [[touches anyObject] locationInView:self];
  326. self.startPoint = point;
  327. //该view置于最前
  328. [[self superview] bringSubviewToFront:self];
  329. }
  330. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  331. //计算位移=当前位置-起始位置
  332. CGPoint point = [[touches anyObject] locationInView:self];
  333. float dx = point.x - self.startPoint.x;
  334. float dy = point.y - self.startPoint.y;
  335. //计算移动后的view中心点
  336. CGPoint newcenter = CGPointMake(self.center.x + dx, self.center.y + dy);
  337. /* 限制用户不可将视图托出屏幕 */
  338. float halfx = CGRectGetMidX(self.bounds);
  339. //x坐标左边界
  340. newcenter.x = MAX(halfx, newcenter.x);
  341. //x坐标右边界
  342. newcenter.x = MIN(self.superview.bounds.size.width - halfx, newcenter.x);
  343. //y坐标同理
  344. float halfy = CGRectGetMidY(self.bounds);
  345. newcenter.y = MAX(halfy, newcenter.y);
  346. newcenter.y = MIN(self.superview.bounds.size.height - halfy, newcenter.y);
  347. /// 动画过度
  348. [UIView animateWithDuration:.25f delay:0 usingSpringWithDamping:.3f initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
  349. //移动view
  350. self.center = newcenter;
  351. } completion:^(BOOL finished) {
  352. }];
  353. }
  354. #pragma mark - LazyLoad
  355. - (FLAnimatedImageView *)bgImageView {
  356. if (!_bgImageView) {
  357. _bgImageView = [[FLAnimatedImageView alloc] initWithFrame:self.frame];
  358. @weakify(self);
  359. @weakify(_bgImageView);
  360. _bgImageView.loopCompletionBlock = ^(NSUInteger loopCountRemaining) {
  361. @strongify(self);
  362. @strongify(_bgImageView);
  363. if (!self.isTiming) {
  364. NSBundle *bundle = [NSBundle mainBundle];
  365. NSString *resourcePath = [bundle resourcePath];
  366. NSString *filePath = [resourcePath stringByAppendingPathComponent:@"1.gif"];
  367. _bgImageView.image = [UIImage imageWithContentsOfFile:filePath];
  368. }
  369. };
  370. }
  371. return _bgImageView;
  372. }
  373. - (UILabel *)timeLabel {
  374. if (!_timeLabel) {
  375. _timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, RQ_SCREEN_WIDTH, 54)];
  376. _timeLabel.text = @"00:00:00";
  377. _timeLabel.textColor = UIColor.whiteColor;
  378. _timeLabel.textAlignment = NSTextAlignmentCenter;
  379. _timeLabel.font = [UIFont systemFontOfSize:50 weight:UIFontWeightBold];
  380. }
  381. return _timeLabel;
  382. }
  383. - (NSTimer *)timer {
  384. if (!_timer) {
  385. _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(rq_timerValueChanged) userInfo:nil repeats:YES];
  386. }
  387. return _timer;
  388. }
  389. - (NSMutableArray *)titleArr {
  390. if (!_titleArr) {
  391. _titleArr = @[@"开始计时",@"结束计时"].mutableCopy;
  392. }
  393. return _titleArr;
  394. }
  395. - (UILabel *)titleLabel {
  396. if (!_titleLabel) {
  397. _titleLabel = [[UILabel alloc] initWithFrame:self.frame];
  398. _titleLabel.text = @"计时";
  399. _titleLabel.textColor = UIColor.whiteColor;
  400. _titleLabel.textAlignment = NSTextAlignmentCenter;
  401. _titleLabel.font = [UIFont systemFontOfSize:10 weight:UIFontWeightLight];
  402. }
  403. return _titleLabel;
  404. }
  405. - (FLAnimatedImage *)animatedImage {
  406. if (!_animatedImage) {
  407. NSString *filePath = [[NSBundle bundleWithPath:[[NSBundle mainBundle] bundlePath]] pathForResource:@"1" ofType:@"gif"];
  408. NSData *gifImageData = [NSData dataWithContentsOfFile:filePath];
  409. _animatedImage = [FLAnimatedImage animatedImageWithGIFData:gifImageData];
  410. }
  411. return _animatedImage;
  412. }
  413. #pragma mark - TimeModule
  414. - (void)startTimingWithResultBlock:(void (^)(BOOL isSuccess))resultBlock {
  415. @weakify(self)
  416. if (defUser.isycbd == 1) {
  417. [RQ_RemoteTheory_MANAGER getTheoryStatusWithResultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull statusDict) {
  418. @strongify(self)
  419. if (isSuccess) {
  420. NSString *statusStr = statusDict[@"body"];
  421. if (!statusStr && [statusStr isEqualToString:@""]) {
  422. ShowMsg(@"获取学员状态异常!");
  423. !resultBlock? : resultBlock(NO);
  424. return;
  425. }
  426. BOOL statusIsSignIn = [statusStr isEqualToString:@"1"];
  427. // NSString *pxkm = defUser.userDict[@"pxjd"];
  428. NSString *pxkm = myDelegate.subject;
  429. if (pxkm.length < 1) {
  430. pxkm = @"1";
  431. }
  432. if (([pxkm isEqualToString:@"2"] || [pxkm isEqualToString:@"3"])) {
  433. pxkm = @"4";
  434. }
  435. NSArray* array = [DB_Helper quearyTrain:RQStringIsNotEmpty(defUser.userStuId)? defUser.userStuId : @"" Subject:pxkm];
  436. __block NSInteger trainTime = 0;
  437. [array.rac_sequence.signal subscribeNext:^(TrainRecord *record) {
  438. trainTime = trainTime + record.trainTime.integerValue;
  439. } completed:^{
  440. dispatch_async(dispatch_get_main_queue(), ^{
  441. @strongify(self)
  442. if (trainTime > 0) {
  443. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:statusIsSignIn? @"检测到上次未正常签退,请签退后再开始理论计时" : @"检测到学员已签退!本地存在异常学时,是否删除异常学时?" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[statusIsSignIn? @"签退" : @"删除"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  444. @strongify(self)
  445. !resultBlock? : resultBlock(NO);
  446. if (selectedOtherButtonIndex == 0) {
  447. if (statusIsSignIn) {
  448. TrainRecord *lastRecord = [array lastObject];
  449. /// 1.本地活体检测
  450. [RQ_CHECKBODY_MANAGER beginCheckBodyWithCheckNum:defUser.ycbdFaceCount completeBlock:^(BOOL success, NSDictionary * _Nullable dic) {
  451. @strongify(self)
  452. if (success) {
  453. /// 2.线上活体检测
  454. [RQ_RemoteTheory_MANAGER edufaceTofaceWithPhotoStr:dic[@"normalImg"] loginFlagType:LoginFlagType_SignOut resultBlock:^(BOOL isSuccess, id dict) {
  455. @strongify(self)
  456. if (isSuccess) {
  457. if (dict) {
  458. NSDictionary *myDict = dict;
  459. NSString *imageUrlStr = myDict[@"body"];
  460. if (RQStringIsEmpty(imageUrlStr)) {
  461. ShowMsg(@"路径为空");
  462. }
  463. /// 4.2上传签退照片
  464. [RQ_RemoteTheory_MANAGER uploadEduPicWithClassidStr:lastRecord.classid timeStr:lastRecord.endTime actionPhotoStr:imageUrlStr loginFlagType:LoginFlagType_SignOut resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull uploadEduPicDict) {
  465. @strongify(self)
  466. if (isSuccess) {
  467. NSLog(@"上传签退照片成功!");
  468. /// 3.签退
  469. [RQ_RemoteTheory_MANAGER uploadEduSignOutWithArray:array resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull signOutDict) {
  470. @strongify(self)
  471. if (success) {
  472. [self signOutSuccessWithTrainArray:array signOutSuccess:YES uploadImageSuccess:YES completion:nil];
  473. }
  474. !resultBlock? : resultBlock(NO);
  475. }];
  476. } else {
  477. NSLog(@"上传签退照片失败!");
  478. [self signOutSuccessWithTrainArray:array signOutSuccess:YES uploadImageSuccess:NO completion:^{
  479. }];
  480. !resultBlock? : resultBlock(NO);
  481. }
  482. }];
  483. } else {
  484. !resultBlock? : resultBlock(NO);
  485. }
  486. } else {
  487. !resultBlock? : resultBlock(NO);
  488. }
  489. }];
  490. } else {
  491. !resultBlock? : resultBlock(NO);
  492. }
  493. }];
  494. } else {
  495. for (TrainRecord *record in array) {
  496. [DB_Helper deleteTrainRecord:record];
  497. }
  498. }
  499. }
  500. }];
  501. } else {
  502. if (statusIsSignIn) {
  503. [RQ_RemoteTheory_MANAGER uploadEduSignOutWithArray:@[] resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull signOutDict) {
  504. @strongify(self)
  505. if (isSuccess) {
  506. [self signOutSuccessWithTrainArray:@[] signOutSuccess:YES uploadImageSuccess:NO completion:nil];
  507. }
  508. !resultBlock? : resultBlock(isSuccess);
  509. }];
  510. } else {
  511. /// 1.本地活体检测
  512. [RQ_CHECKBODY_MANAGER beginCheckBodyWithCheckNum:defUser.ycbdFaceCount completeBlock:^(BOOL success, NSDictionary * _Nullable dic) {
  513. @strongify(self)
  514. if (success) {
  515. /// 2.线上活体检测
  516. [RQ_RemoteTheory_MANAGER edufaceTofaceWithPhotoStr:dic[@"normalImg"] loginFlagType:LoginFlagType_SignIn resultBlock:^(BOOL isSuccess, id dict) {
  517. @strongify(self)
  518. if (isSuccess) {
  519. if (dict) {
  520. NSDictionary *myDict = dict;
  521. NSString *imageUrlStr = myDict[@"body"];
  522. if (RQStringIsEmpty(imageUrlStr)) {
  523. ShowMsg(@"路径为空");
  524. }
  525. /// 3.获取线上时间
  526. [RQ_RemoteTheory_MANAGER getCurrentTimeWithResultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull timeDict) {
  527. @strongify(self)
  528. if (isSuccess) {
  529. // NSString *timeStr = @"2022-03-13 22:46:59";
  530. NSDate *date = [NSDate rq_dateWithTimestamp:timeDict[@"body"]];
  531. // NSDate *date = [NSDate rq_dateWithTimestamp:timeStr];
  532. NSInteger timeStamp = [[NSNumber numberWithDouble:[date timeIntervalSince1970]] integerValue];
  533. NSString *timeStampStr = [NSString stringWithFormat:@"%@",[NSNumber numberWithInteger:timeStamp]];
  534. self.classIdStr = timeStampStr;
  535. if (self.classIdStr.length < 10) {
  536. /// 如果生成时间戳错误 用一个随机十位数代替
  537. self.classIdStr = [NSString stringWithFormat:@"%@",[NSNumber numberWithInteger:[NSString rq_randomNumberWithFrom:1647311377 to:9999999999]]];
  538. }
  539. /// 4.签到
  540. [RQ_RemoteTheory_MANAGER uploadEduSignInWithClassidStr:self.classIdStr resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull signInDict) {
  541. if (isSuccess) {
  542. @strongify(self)
  543. NSString *timeStr = signInDict[@"body"];
  544. [self signInSuccessWithBeginTime:timeStr];
  545. /// 5.上传照片
  546. [RQ_RemoteTheory_MANAGER uploadEduPicWithClassidStr:self.classIdStr timeStr:timeStr actionPhotoStr:imageUrlStr loginFlagType:LoginFlagType_SignIn resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull uploadEduPicDict) {
  547. // @strongify(self)
  548. }];
  549. }
  550. !resultBlock? : resultBlock(isSuccess);
  551. }];
  552. } else {
  553. !resultBlock? : resultBlock(NO);
  554. }
  555. }];
  556. } else {
  557. !resultBlock? : resultBlock(NO);
  558. [self.timer setFireDate:[NSDate distantPast]];
  559. }
  560. } else {
  561. !resultBlock? : resultBlock(NO);
  562. }
  563. }];
  564. } else {
  565. !resultBlock? : resultBlock(NO);
  566. }
  567. }];
  568. }
  569. }
  570. });
  571. }];
  572. } else {
  573. !resultBlock? : resultBlock(NO);
  574. }
  575. }];
  576. } else {
  577. !resultBlock? : resultBlock(YES);
  578. [self beginTime];
  579. }
  580. }
  581. - (void)stopTimingWithResultBlock:(void (^)(BOOL isSuccessed))resultBlock {
  582. @weakify(self)
  583. [self.timer setFireDate:[NSDate distantFuture]];
  584. [self saveTrain];
  585. if (defUser.isycbd == 1) {
  586. /// 1.本地活体检测
  587. [RQ_CHECKBODY_MANAGER beginCheckBodyWithCheckNum:defUser.ycbdFaceCount completeBlock:^(BOOL success, NSDictionary * _Nullable dic) {
  588. @strongify(self)
  589. if (success) {
  590. /// 2.线上活体检测
  591. [RQ_RemoteTheory_MANAGER edufaceTofaceWithPhotoStr:dic[@"normalImg"] loginFlagType:LoginFlagType_SignOut resultBlock:^(BOOL isSuccess, id dict) {
  592. @strongify(self)
  593. if (isSuccess) {
  594. if (dict) {
  595. NSDictionary *myDict = dict;
  596. NSString *imageUrlStr = myDict[@"body"];
  597. if (RQStringIsEmpty(imageUrlStr)) {
  598. ShowMsg(@"路径为空");
  599. }
  600. /// 3.签退
  601. // NSString *pxkm = defUser.userDict[@"pxjd"];
  602. NSString *pxkm = myDelegate.subject;
  603. if (pxkm.length < 1) {
  604. pxkm = @"1";
  605. }
  606. if (([pxkm isEqualToString:@"2"] || [pxkm isEqualToString:@"3"])) {
  607. pxkm = @"4";
  608. }
  609. NSArray* array = [DB_Helper quearyTrain:RQStringIsNotEmpty(defUser.userStuId)? defUser.userStuId : @"" Subject:pxkm];
  610. if (array.count < 1) {
  611. !resultBlock? : resultBlock(YES);
  612. ShowMsg(@"本地无学时明细!");
  613. return;
  614. }
  615. /// 4.2上传签退照片
  616. NSString *timeStr = [self getTimes:self.seconds];
  617. [RQ_RemoteTheory_MANAGER uploadEduPicWithClassidStr:self.classIdStr timeStr:timeStr actionPhotoStr:imageUrlStr loginFlagType:LoginFlagType_SignOut resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull uploadEduPicDict) {
  618. @strongify(self)
  619. if (isSuccess) {
  620. NSLog(@"上传签退照片成功!");
  621. [RQ_RemoteTheory_MANAGER uploadEduSignOutWithArray:array resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull signOutDict) {
  622. @strongify(self)
  623. if (isSuccess) {
  624. !resultBlock? : resultBlock(YES);
  625. [self signOutSuccessWithTrainArray:array signOutSuccess:YES uploadImageSuccess:YES completion:nil];
  626. } else {
  627. !resultBlock? : resultBlock(NO);
  628. [self.timer setFireDate:[NSDate distantPast]];
  629. }
  630. }];
  631. } else {
  632. NSLog(@"上传签退照片失败!");
  633. !resultBlock? : resultBlock(NO);
  634. [self.timer setFireDate:[NSDate distantPast]];
  635. }
  636. }];
  637. } else {
  638. !resultBlock? : resultBlock(NO);
  639. [self.timer setFireDate:[NSDate distantPast]];
  640. }
  641. } else {
  642. !resultBlock? : resultBlock(NO);
  643. [self.timer setFireDate:[NSDate distantPast]];
  644. }
  645. }];
  646. } else {
  647. !resultBlock? : resultBlock(NO);
  648. [self.timer setFireDate:[NSDate distantPast]];
  649. }
  650. }];
  651. } else {
  652. !resultBlock? : resultBlock(YES);
  653. [self setSecondString:@"0"];
  654. [self.timer setFireDate:[NSDate distantFuture]];
  655. [self.timer invalidate];
  656. self.timer = nil;
  657. // myDelegate.timer = nil;
  658. myDelegate.isTrain = NO;
  659. self.timeLabel.text = @"00:00:00";
  660. // if (self.seconds < 60) {
  661. // ShowMsg(@"学时未满一分钟不统计");
  662. // return;
  663. // }
  664. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"结束计时,是否上传学时?" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"暂不上传" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  665. @strongify(self)
  666. if (selectedOtherButtonIndex == 0) {
  667. [self upLoadTrainRecord];
  668. }else if (selectedOtherButtonIndex == NSNotFound){
  669. ShowMsg(@"学时已保存在本地");
  670. }
  671. }];
  672. }
  673. }
  674. //远程理论签到成功
  675. - (void)signInSuccessWithBeginTime:(NSString *)beginTime {
  676. myDelegate.begin_Time = beginTime;
  677. [Tools playAudioWithString:@"操作成功,开始计时"];
  678. self.seconds = 0;
  679. // myDelegate.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeFireMethod) userInfo:nil repeats:YES];
  680. myDelegate.isUseriPhone = YES;
  681. myDelegate.isTrain = YES;
  682. // self.timer = myDelegate.timer;
  683. // begin_endBtn.selected = YES;
  684. //防止前五分钟内退出软件 造成理论无本地学时 无法签退的问题
  685. [self saveTrain];
  686. // myDelegate.tPeriodVC = self;
  687. ShowMsgSuc();
  688. [RQ_COMMON_MANAGER keepIdleTimerDisabledisOpen:YES];
  689. }
  690. //远程理论签退成功
  691. - (void)signOutSuccessWithTrainArray:(NSArray *)trainArray signOutSuccess:(BOOL)signOutSuccess uploadImageSuccess:(BOOL)uploadImageSuccess completion:(void (^)(void))completion {
  692. for (TrainRecord *record in trainArray) {
  693. [DB_Helper updateTrainState:record];
  694. }
  695. if (trainArray.count > 0) {
  696. if (signOutSuccess) {
  697. if (![_secondString isEqualToString:@"0"]) {
  698. [self setSecondString:@"0"];
  699. }
  700. if (self.timer.isValid) {
  701. [self.timer invalidate];
  702. }
  703. if (self.timer) {
  704. self.timer = nil;
  705. }
  706. // if (myDelegate.timer) {
  707. // myDelegate.timer = nil;
  708. // }
  709. // if (myDelegate.tPeriodVC) {
  710. // myDelegate.tPeriodVC = nil;
  711. // }
  712. if (myDelegate.isTrain) {
  713. myDelegate.isTrain = NO;
  714. }
  715. if (![self.timeLabel.text isEqualToString:@"00:00:00"]) {
  716. self.timeLabel.text = @"00:00:00";
  717. }
  718. }
  719. if (signOutSuccess && uploadImageSuccess) {
  720. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"签退成功!" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:nil];
  721. } else if (signOutSuccess && !uploadImageSuccess && completion) {
  722. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"上传照片失败!" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"重新上传" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  723. completion();
  724. }];
  725. }
  726. } else {
  727. // 强制签退后再去调签到
  728. [self startTimingWithResultBlock:nil];
  729. }
  730. [RQ_COMMON_MANAGER keepIdleTimerDisabledisOpen:NO];
  731. }
  732. - (void)reUploadPhotoWithClassidStr:(NSString *)classidStr timeStr:(NSString *)timeStr actionPhotoStr:(NSString *)actionPhotoStr loginFlagType:(LoginFlagType)loginFlagType {
  733. __block BOOL reUploadSuccess = YES;
  734. __block BOOL isUploading = NO;
  735. int i = 0;
  736. do {
  737. if (i == 0) {
  738. if (!isUploading) {
  739. isUploading = YES;
  740. [RQ_RemoteTheory_MANAGER uploadEduPicWithClassidStr:classidStr timeStr:timeStr actionPhotoStr:actionPhotoStr loginFlagType:loginFlagType resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull uploadEduPicDict) {
  741. if (isSuccess) {
  742. ShowMsg(@"重新上传照片成功!");
  743. reUploadSuccess = YES;
  744. } else {
  745. reUploadSuccess = NO;
  746. }
  747. isUploading = NO;
  748. }];
  749. }
  750. } else {
  751. if (!isUploading) {
  752. isUploading = YES;
  753. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"上传照片失败!" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"重新上传" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  754. [RQ_RemoteTheory_MANAGER uploadEduPicWithClassidStr:classidStr timeStr:timeStr actionPhotoStr:actionPhotoStr loginFlagType:loginFlagType resultBlock:^(BOOL isSuccess, NSDictionary * _Nonnull uploadEduPicDict) {
  755. if (isSuccess) {
  756. ShowMsg(@"重新上传照片成功!");
  757. reUploadSuccess = YES;
  758. } else {
  759. reUploadSuccess = NO;
  760. }
  761. isUploading = NO;
  762. }];
  763. }];
  764. }
  765. }
  766. i ++;
  767. } while (reUploadSuccess == NO);
  768. }
  769. - (NSString *)getTimes:(int)second {
  770. NSDateFormatter *formatter=[[NSDateFormatter alloc]init];
  771. [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  772. NSString *beginTimeStr = myDelegate.begin_Time;
  773. [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
  774. NSDate *beginDate = [formatter dateFromString:beginTimeStr];
  775. NSDate *newDate = [NSDate dateWithTimeInterval:second sinceDate:beginDate];
  776. NSString *nowString = [formatter stringFromDate:newDate];
  777. return nowString;
  778. }
  779. - (void)beginTime {
  780. @weakify(self)
  781. if (![Util connectedToNetWork])
  782. {
  783. ShowMsg(@"请检查网络连接。");
  784. return;
  785. }
  786. NSMutableArray *arr=[NSMutableArray array];
  787. [arr property:defUser.userDict[@"outId"] forKey:@"outId"];
  788. [arr property:defUser.userDict[@"city"] forKey:@"dqbh"];
  789. NSString* method = @"isUsePhone";
  790. [QMUITips showLoadingInView:DefaultTipsParentView];
  791. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary *dict) {
  792. @strongify(self)
  793. [QMUITips hideAllTips];
  794. if (!dict) {
  795. ShowMsgFailed();
  796. return;
  797. }
  798. if ([dict[@"code"] isEqualToString:@"90"]) {
  799. UIAlertController *alertFind = [UIAlertController alertControllerWithTitle:nil message:dict[@"msg"] preferredStyle:UIAlertControllerStyleAlert];
  800. [alertFind addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  801. [LoginViewController loginFromVC:RQControllerHelper.currentViewController];
  802. }]];
  803. [RQControllerHelper.currentViewController presentViewController:alertFind animated:true completion:nil];
  804. return;
  805. }
  806. if ([dict[@"code"] isEqualToString:@"0"]) {
  807. myDelegate.begin_Time = dict[@"body"];
  808. [Tools playAudioWithString:@"操作成功,开始计时"];
  809. [self beginTiming];
  810. self.seconds = 0;
  811. // myDelegate.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeFireMethod) userInfo:nil repeats:YES];
  812. myDelegate.isUseriPhone = YES;
  813. myDelegate.isTrain = YES;
  814. // begin_endBtn.selected = YES;
  815. //防止前五分钟内退出软件 造成理论无本地学时 无法签退的问题
  816. [self saveTrain];
  817. } else {
  818. NSString *msg = dict[@"msg"];
  819. if (msg.length < 1) {
  820. msg = dict[@"body"];
  821. }
  822. ShowMsg(msg);
  823. [Tools playAudioWithString:msg];
  824. }
  825. }];
  826. }
  827. - (void)stopTiming {
  828. // [myDelegate.timer invalidate];
  829. // myDelegate.timer = nil;
  830. myDelegate.isUseriPhone = NO;
  831. myDelegate.isTrain = NO;
  832. self.timeLabel.text = @"00:00:00";
  833. // if (seconds < 60) {
  834. // ShowMsg(@"学时未满一分钟不统计");
  835. // }
  836. [self endTiming];
  837. [self saveTrain];
  838. [self upLoadTrainRecord];
  839. }
  840. - (void)saveTrain {
  841. NSDateFormatter *formatter = [NSDateFormatter rq_defaultDateFormatter];
  842. TrainRecord *train = [[TrainRecord alloc] init];
  843. train.studentId = defUser.userStuId;
  844. train.beginTime = myDelegate.begin_Time;
  845. NSDate *date=[formatter dateFromString:myDelegate.begin_Time];
  846. date=[date dateByAddingTimeInterval:self.seconds];
  847. train.state = @"0";
  848. train.endTime=[formatter stringFromDate:date];
  849. NSInteger mins = self.seconds / 60;
  850. train.trainTime=[NSString stringWithFormat:@"%d",(int)mins];
  851. train.subject = myDelegate.subject;
  852. train.classid = (self.classIdStr && ![self.classIdStr isEqualToString:@""])? self.classIdStr : @"0";
  853. [DB_Helper saveTrain:train];
  854. }
  855. - (void)upLoadTrainRecord {
  856. // NSString *pxkm = defUser.userDict[@"pxjd"];
  857. //
  858. // if (pxkm.length < 1) {
  859. // pxkm = @"1";
  860. // }
  861. NSArray* array = [DB_Helper quearyTrain:defUser.userStuId Subject:myDelegate.subject];
  862. if (array.count < 1) {
  863. ShowMsg(@"本地无学时明细!");
  864. return;
  865. }
  866. //这里是对分段上传学时做的处理 如果学时上传有问题 查看这里
  867. [self uploadMoreTrainRecordWithArray:array];
  868. }
  869. - (void)uploadMoreTrainRecordWithArray:(NSArray *)trainArray {
  870. @weakify(self)
  871. if (![Util connectedToNetWork]) {
  872. showMsgUnconnect();
  873. return;
  874. }
  875. NSString* str = @"";
  876. for (TrainRecord *record in trainArray) {
  877. str = [str stringByAppendingString:[NSString stringWithFormat:@"%@,%@,%@,%@;",record.studentId,record.beginTime,record.endTime,record.trainTime]];
  878. }
  879. TrainRecord *record = [trainArray firstObject];
  880. NSMutableArray *arr=[NSMutableArray array];
  881. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"ios",@"trainType", nil]];
  882. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:[DES3Util encrypt:str ],@"trainRecord", nil]];
  883. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:record.subject,@"pxkm", nil]];
  884. [arr addObject:[NSDictionary dictionaryWithObjectsAndKeys:defUser.userDict[@"outId"],@"stuOutid", nil]];
  885. NSString* method = @"uploadMoreTrainRecord";
  886. [QMUITips showLoadingInView:DefaultTipsParentView];
  887. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary *dict) {
  888. [QMUITips hideAllTips];
  889. @strongify(self)
  890. if (!dict) {
  891. ShowMsg(@"操作失败");
  892. return;
  893. }
  894. if ([dict[@"code"] isEqualToString:@"90"]) {
  895. UIAlertController *alertFind = [UIAlertController alertControllerWithTitle:nil message:dict[@"msg"] preferredStyle:UIAlertControllerStyleAlert];
  896. [alertFind addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  897. @strongify(self)
  898. [LoginViewController loginFromVC:RQControllerHelper.currentViewController];
  899. }]];
  900. [RQControllerHelper.currentViewController presentViewController:alertFind animated:true completion:nil];
  901. return;
  902. }
  903. if ( [dict[@"code"] isEqualToString:@"1"]) {
  904. ShowMsg(dict[@"body"]);
  905. return;
  906. }
  907. if ( [dict[@"code"] isEqualToString:@"0"]) {
  908. for (TrainRecord *record in trainArray) {
  909. [DB_Helper updateTrainState:record];
  910. }
  911. UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"上传学时成功!" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
  912. [alert show];
  913. }
  914. }];
  915. }
  916. @end