KSScanViewController.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //
  2. // KSScanViewController.m
  3. // KulexiuForTeacher
  4. //
  5. // Created by 王智 on 2022/6/30.
  6. //
  7. #import "KSScanViewController.h"
  8. #import <KSToolLibrary/GRScanManager.h>
  9. #import "ScanNavView.h"
  10. #import "KSBaseWKWebViewController.h"
  11. #import "KSMediaManager.h"
  12. #import "KSPremissionAlert.h"
  13. #import <KSToolLibrary/RecordCheckManager.h>
  14. #import "ScanLoginViewController.h"
  15. #import "ScanFailViewController.h"
  16. #import "ScanOpenAlert.h"
  17. @interface KSScanViewController ()
  18. @property (nonatomic, strong) KSMediaManager *mediaManager;
  19. @property (nonatomic, strong) NSMutableArray *imageArray; // 图片数组
  20. @property (nonatomic, strong) NSMutableArray *imageAsset; // 图片 asset
  21. @property (nonatomic, strong) GRScanManager *scanManager;
  22. @property (nonatomic, strong) ScanNavView *navView;
  23. @property (nonatomic, strong) UIImageView *scanView;
  24. @property (nonatomic, strong) UIView *maskView;
  25. @property (nonatomic, strong) ScanOpenAlert *openAlert;
  26. @end
  27. @implementation KSScanViewController
  28. - (void)viewDidLoad {
  29. [super viewDidLoad];
  30. // Do any additional setup after loading the view.
  31. self.ks_prefersNavigationBarHidden = YES;
  32. self.view.backgroundColor = HexRGB(0x000000);
  33. [self configUI];
  34. }
  35. - (void)viewWillAppear:(BOOL)animated {
  36. [super viewWillAppear:animated];
  37. [self startScan];
  38. }
  39. - (void)viewWillDisappear:(BOOL)animated {
  40. [super viewWillDisappear:animated];
  41. [self.scanManager stopScanning];
  42. }
  43. - (void)configUI {
  44. UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake((KPortraitWidth - 255) / 2.0f, (KPortraitHeight - 255) / 2.0f, 255, 255)];
  45. CGRect qrViweFrame = imageView.frame;
  46. imageView.image = [UIImage imageNamed:@"ScanView"];
  47. [self.view addSubview:imageView];
  48. self.scanView = imageView;
  49. CAShapeLayer *shperLayer = [[CAShapeLayer alloc]init];
  50. CGMutablePathRef path = CGPathCreateMutable();
  51. // 保留顶部
  52. CGPathAddRect(path, nil, CGRectMake(0, 0, KPortraitWidth, CGRectGetMinY(qrViweFrame)));
  53. // 保留底部
  54. CGPathAddRect(path, nil, CGRectMake(0,CGRectGetMaxY(qrViweFrame), KPortraitWidth,KPortraitHeight - CGRectGetMaxY(qrViweFrame)));
  55. //保留左边
  56. CGPathAddRect(path, nil, CGRectMake(0,CGRectGetMinY(qrViweFrame), CGRectGetMinX(qrViweFrame),300));
  57. //保留右边
  58. CGPathAddRect(path, nil, CGRectMake(CGRectGetMaxX(qrViweFrame),CGRectGetMinY(qrViweFrame),KPortraitWidth - CGRectGetMaxX(qrViweFrame),300));
  59. shperLayer.path = path;
  60. CGPathRelease(path);
  61. UIView *view = [[UIView alloc] initWithFrame:self.view.bounds];
  62. view.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.7];
  63. [self.view addSubview:view];
  64. self.maskView = view;
  65. view.layer.mask = shperLayer;
  66. [self.view addSubview:self.navView];
  67. [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
  68. make.left.right.top.mas_equalTo(self.view);
  69. make.height.mas_equalTo(kNaviBarHeight);
  70. }];
  71. UILabel *msg = [[UILabel alloc] initWithFrame:CGRectMake(30, CGRectGetMaxY(imageView.frame) + 15, KPortraitWidth - 60, 22)];
  72. msg.backgroundColor = [UIColor clearColor];
  73. msg.textColor = HexRGB(0xffffff);
  74. msg.textAlignment = NSTextAlignmentCenter;
  75. msg.font = [UIFont systemFontOfSize:16];
  76. msg.text = @"请对准需要识别的二维码。";
  77. [self.view addSubview:msg];
  78. }
  79. - (void)startScan {
  80. MJWeakSelf;
  81. [self.scanManager startScanningQRCodeWithInView:self.view scanView:self.scanView resultCallback:^(NSString *result) {
  82. [weakSelf.scanManager stopScanning];
  83. [weakSelf dealWithCheckSource:result];
  84. NSLog(@"%@",result);
  85. }];
  86. }
  87. - (void)dealWithCheckSource:(NSString *)result {
  88. if (result) {
  89. if ([result containsString:hostURL]) { // 如果是本端链接
  90. result = [result getUrlEndcodeString];
  91. KSBaseWKWebViewController *webCtrl = [[KSBaseWKWebViewController alloc] init];
  92. webCtrl.url = result;
  93. [self.navigationController pushViewController:webCtrl animated:YES];
  94. }
  95. else if ([result hasPrefix:@"http://"] || [result hasPrefix:@"https://"]) { // 如果非本端链接
  96. result = [result getUrlEndcodeString];
  97. [self.openAlert configWithLinkUrl:result];
  98. [self.openAlert showAlertInView:self.view];
  99. }
  100. else {
  101. NSData *jsonData = [result mj_JSONData];
  102. NSError *error;
  103. NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
  104. if (!error) {
  105. NSString *action = [dict ks_stringValueForKey:@"action"];
  106. if ([action isEqualToString:@"login"]) { // 登录乐教通
  107. NSString *uuid = [dict ks_stringValueForKey:@"uuid"];
  108. [self scanAuthCodeRequest:uuid];
  109. }
  110. }
  111. else {
  112. // 无法识别
  113. [self showScanFailedPage];
  114. }
  115. }
  116. }
  117. else {
  118. // 无法识别
  119. [self showScanFailedPage];
  120. }
  121. }
  122. - (void)showScanFailedPage {
  123. ScanFailViewController *ctrl = [[ScanFailViewController alloc] init];
  124. ctrl.failType = SCANFAIL_UNRECOGNIZE;
  125. [self.navigationController pushViewController:ctrl animated:YES];
  126. }
  127. - (void)scanAuthCodeRequest:(NSString *)uuid {
  128. [KSNetworkingManager scanQrCodeRequest:KS_POST uuid:uuid success:^(NSDictionary * _Nonnull dic) {
  129. if ([dic ks_integerValueForKey:@"code"] == 200) { // 正常
  130. ScanLoginViewController *ctrl = [[ScanLoginViewController alloc] init];
  131. ctrl.uuid = uuid;
  132. [self.navigationController pushViewController:ctrl animated:YES];
  133. }
  134. else if ([dic ks_integerValueForKey:@"code"] == 5440) { // 过期
  135. ScanFailViewController *ctrl = [[ScanFailViewController alloc] init];
  136. ctrl.failType = SCANFAIL_EXPIRED;
  137. [self.navigationController pushViewController:ctrl animated:YES];
  138. }
  139. else if ([dic ks_integerValueForKey:@"code"] == 5445) { // 不支持授权
  140. ScanFailViewController *ctrl = [[ScanFailViewController alloc] init];
  141. ctrl.failType = SCANFAIL_UNSUPPORAUTH;
  142. [self.navigationController pushViewController:ctrl animated:YES];
  143. }
  144. else {
  145. [LOADING_MANAGER KSShowMsg:MESSAGEKEY promptCompletion:^{
  146. [self startScan];
  147. }];
  148. }
  149. } faliure:^(NSError * _Nonnull error) {
  150. [self startScan];
  151. }];
  152. }
  153. - (GRScanManager *)scanManager {
  154. if (!_scanManager) {
  155. _scanManager = [[GRScanManager alloc] init];
  156. _scanManager.supportBarCode = YES;
  157. _scanManager.supportQRCode = YES;
  158. }
  159. return _scanManager;
  160. }
  161. - (ScanOpenAlert *)openAlert {
  162. if (!_openAlert) {
  163. _openAlert = [ScanOpenAlert shareInstance];
  164. MJWeakSelf;
  165. [_openAlert alertActionCallback:^(BOOL openLink, NSString * _Nullable linkUrl) {
  166. [weakSelf scanAlertAction:openLink linkUrl:linkUrl];
  167. }];
  168. }
  169. return _openAlert;
  170. }
  171. - (void)scanAlertAction:(BOOL)isOpen linkUrl:(NSString *)linkUrl {
  172. if (isOpen) { // 关闭页面, 打开外部页面
  173. if (![NSString isEmptyString:linkUrl]) {
  174. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:linkUrl] options: @{} completionHandler: nil];
  175. }
  176. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  177. [self backAction];
  178. });
  179. }
  180. else { // 重新开启扫码
  181. [self startScan];
  182. }
  183. }
  184. - (void)backAction {
  185. [self.view endEditing:YES];
  186. // 根据需要返回到不同页面
  187. [self.navigationController popViewControllerAnimated:YES];
  188. }
  189. - (ScanNavView *)navView {
  190. if (!_navView) {
  191. _navView = [ScanNavView shareInstance];
  192. MJWeakSelf;
  193. [_navView scanActionCallback:^(SCANNAV_ACTION action) {
  194. [weakSelf topNavAction:action];
  195. }];
  196. }
  197. return _navView;
  198. }
  199. - (void)topNavAction:(SCANNAV_ACTION)action {
  200. if (action == SCANNAV_ACTION_BACK) {
  201. [self.navigationController popViewControllerAnimated:YES];
  202. }
  203. else { // 选择相册
  204. // 判断是否有权限
  205. [RecordCheckManager checkPhotoLibraryPremissionAvaiableCallback:^(PREMISSIONTYPE type) {
  206. if (type == PREMISSIONTYPE_YES) {
  207. [self choosePhoneScan];
  208. }
  209. else {
  210. [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
  211. }
  212. }];
  213. }
  214. }
  215. - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
  216. [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
  217. } confirm:^{
  218. [self openSettingView];
  219. }];
  220. }
  221. - (void)openSettingView {
  222. if (@available(iOS 10, *)) {
  223. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
  224. } else {
  225. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
  226. }
  227. }
  228. - (void)choosePhoneScan {
  229. // 调用相册
  230. self.mediaManager = [[KSMediaManager alloc] init];
  231. self.mediaManager.mediaType = MEDIATYPE_PHOTO;
  232. self.mediaManager.maxPhotoNumber = 1;
  233. self.mediaManager.baseCtrl = self;
  234. self.mediaManager.imageArray = [self.imageArray mutableCopy];
  235. self.mediaManager.imageAsset = [self.imageAsset mutableCopy];
  236. self.mediaManager.needCropImage = NO;
  237. MJWeakSelf;
  238. [self.mediaManager noAlertCallback:^(NSString * _Nullable videoUrl, NSMutableArray * _Nullable imageArray, NSMutableArray * _Nullable imageAsset) {
  239. dispatch_main_async_safe(^{
  240. [weakSelf scanImage:[imageArray lastObject]];
  241. });
  242. }];
  243. [self.mediaManager pushImagePickerController];
  244. }
  245. - (void)scanImage:(UIImage *)image {
  246. CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
  247. NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
  248. if (features.count > 0) {
  249. CIQRCodeFeature *feature = [features objectAtIndex:0];
  250. NSString *scannedResult = feature.messageString;
  251. NSLog(@"result:%@",scannedResult);
  252. [self dealWithCheckSource:scannedResult];
  253. }
  254. else {
  255. [LOADING_MANAGER MBShowAUTOHidingInWindow:@"无法识别"];
  256. }
  257. }
  258. /*
  259. #pragma mark - Navigation
  260. // In a storyboard-based application, you will often want to do a little preparation before navigation
  261. - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  262. // Get the new view controller using [segue destinationViewController].
  263. // Pass the selected object to the new view controller.
  264. }
  265. */
  266. @end