Parcourir la source

改进扫码功能

fancy il y a 5 ans
Parent
commit
506721ee32
20 fichiers modifiés avec 1289 ajouts et 286 suppressions
  1. 28 0
      o2ios/O2Platform.xcodeproj/project.pbxproj
  2. 165 0
      o2ios/O2Platform/App/Scan-二维码扫码/c/QRCodeResultViewController.swift
  3. 85 0
      o2ios/O2Platform/App/Scan-二维码扫码/c/QRCodeResultViewController.xib
  4. 29 15
      o2ios/O2Platform/App/Scan-二维码扫码/c/ScanHelper.swift
  5. 451 0
      o2ios/O2Platform/App/Scan-二维码扫码/c/ScanQRViewController.swift
  6. 15 0
      o2ios/O2Platform/App/Scan-二维码扫码/m/ScanRecoObj.swift
  7. 21 0
      o2ios/O2Platform/Assets.xcassets/login/scan_login.imageset/Contents.json
  8. BIN
      o2ios/O2Platform/Assets.xcassets/login/scan_login.imageset/scan_login_content_2.png
  9. 0 6
      o2ios/O2Platform/Assets.xcassets/whipster/Contents.json
  10. 21 0
      o2ios/O2Platform/Assets.xcassets/首页/QRCodeScanLine.imageset/Contents.json
  11. BIN
      o2ios/O2Platform/Assets.xcassets/首页/QRCodeScanLine.imageset/QRCodeScanLine@2x.png
  12. 21 0
      o2ios/O2Platform/Assets.xcassets/首页/photos_icon.imageset/Contents.json
  13. BIN
      o2ios/O2Platform/Assets.xcassets/首页/photos_icon.imageset/photos_icon@2x.png
  14. 21 0
      o2ios/O2Platform/Assets.xcassets/首页/right_arrow_icon.imageset/Contents.json
  15. BIN
      o2ios/O2Platform/Assets.xcassets/首页/right_arrow_icon.imageset/right@2x.png
  16. 21 0
      o2ios/O2Platform/Assets.xcassets/首页/scan_back.imageset/Contents.json
  17. BIN
      o2ios/O2Platform/Assets.xcassets/首页/scan_back.imageset/scan_back@2x.png
  18. 1 11
      o2ios/O2Platform/Framework/scan/LBXScanViewController.swift
  19. 315 254
      o2ios/O2Platform/Framework/scan/LBXScanWrapper.swift
  20. 95 0
      o2ios/O2Platform/UI/O2CanCopyUILabel.swift

+ 28 - 0
o2ios/O2Platform.xcodeproj/project.pbxproj

@@ -187,6 +187,11 @@
 		B167F7632362BFC200F182B8 /* CloudFileMoveFolderController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B167F7622362BFC200F182B8 /* CloudFileMoveFolderController.swift */; };
 		B167F7632362BFC200F182B8 /* CloudFileMoveFolderController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B167F7622362BFC200F182B8 /* CloudFileMoveFolderController.swift */; };
 		B167F7662362C60200F182B8 /* CloudFileMoveFolderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B167F7642362C60200F182B8 /* CloudFileMoveFolderCell.swift */; };
 		B167F7662362C60200F182B8 /* CloudFileMoveFolderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B167F7642362C60200F182B8 /* CloudFileMoveFolderCell.swift */; };
 		B167F7672362C60200F182B8 /* CloudFileMoveFolderCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B167F7652362C60200F182B8 /* CloudFileMoveFolderCell.xib */; };
 		B167F7672362C60200F182B8 /* CloudFileMoveFolderCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B167F7652362C60200F182B8 /* CloudFileMoveFolderCell.xib */; };
+		B168BDC724F5FFA10070329F /* ScanQRViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B168BDC624F5FFA10070329F /* ScanQRViewController.swift */; };
+		B168BDC924F5FFA80070329F /* ScanRecoObj.swift in Sources */ = {isa = PBXBuildFile; fileRef = B168BDC824F5FFA80070329F /* ScanRecoObj.swift */; };
+		B168BDCC24F607520070329F /* QRCodeResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B168BDCA24F607520070329F /* QRCodeResultViewController.swift */; };
+		B168BDCD24F607520070329F /* QRCodeResultViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B168BDCB24F607520070329F /* QRCodeResultViewController.xib */; };
+		B168BDCF24F62BA60070329F /* O2CanCopyUILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B168BDCE24F62BA60070329F /* O2CanCopyUILabel.swift */; };
 		B169E3D421095EC9007156B3 /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B169E3D321095EC9007156B3 /* Date+Extension.swift */; };
 		B169E3D421095EC9007156B3 /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B169E3D321095EC9007156B3 /* Date+Extension.swift */; };
 		B17126C121084A2F00369F15 /* calendar.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B17126C021084A2F00369F15 /* calendar.storyboard */; };
 		B17126C121084A2F00369F15 /* calendar.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B17126C021084A2F00369F15 /* calendar.storyboard */; };
 		B1750078233C6908003DA7B9 /* BlockPan.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1750072233C6907003DA7B9 /* BlockPan.swift */; };
 		B1750078233C6908003DA7B9 /* BlockPan.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1750072233C6907003DA7B9 /* BlockPan.swift */; };
@@ -1532,6 +1537,11 @@
 		B167F7622362BFC200F182B8 /* CloudFileMoveFolderController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudFileMoveFolderController.swift; sourceTree = "<group>"; };
 		B167F7622362BFC200F182B8 /* CloudFileMoveFolderController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudFileMoveFolderController.swift; sourceTree = "<group>"; };
 		B167F7642362C60200F182B8 /* CloudFileMoveFolderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudFileMoveFolderCell.swift; sourceTree = "<group>"; };
 		B167F7642362C60200F182B8 /* CloudFileMoveFolderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudFileMoveFolderCell.swift; sourceTree = "<group>"; };
 		B167F7652362C60200F182B8 /* CloudFileMoveFolderCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CloudFileMoveFolderCell.xib; sourceTree = "<group>"; };
 		B167F7652362C60200F182B8 /* CloudFileMoveFolderCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CloudFileMoveFolderCell.xib; sourceTree = "<group>"; };
+		B168BDC624F5FFA10070329F /* ScanQRViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanQRViewController.swift; sourceTree = "<group>"; };
+		B168BDC824F5FFA80070329F /* ScanRecoObj.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanRecoObj.swift; sourceTree = "<group>"; };
+		B168BDCA24F607520070329F /* QRCodeResultViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeResultViewController.swift; sourceTree = "<group>"; };
+		B168BDCB24F607520070329F /* QRCodeResultViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QRCodeResultViewController.xib; sourceTree = "<group>"; };
+		B168BDCE24F62BA60070329F /* O2CanCopyUILabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = O2CanCopyUILabel.swift; sourceTree = "<group>"; };
 		B169E3D321095EC9007156B3 /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
 		B169E3D321095EC9007156B3 /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
 		B17126C021084A2F00369F15 /* calendar.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = calendar.storyboard; sourceTree = "<group>"; };
 		B17126C021084A2F00369F15 /* calendar.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = calendar.storyboard; sourceTree = "<group>"; };
 		B1750072233C6907003DA7B9 /* BlockPan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockPan.swift; sourceTree = "<group>"; };
 		B1750072233C6907003DA7B9 /* BlockPan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockPan.swift; sourceTree = "<group>"; };
@@ -2869,6 +2879,14 @@
 			path = Presentr;
 			path = Presentr;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		B168BD9724F5FF410070329F /* m */ = {
+			isa = PBXGroup;
+			children = (
+				B168BDC824F5FFA80070329F /* ScanRecoObj.swift */,
+			);
+			path = m;
+			sourceTree = "<group>";
+		};
 		B18FFF3323756B24001B2887 /* JpushAPI */ = {
 		B18FFF3323756B24001B2887 /* JpushAPI */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -3020,6 +3038,7 @@
 				090253DD1F0E8BA6006B1609 /* O2LoadingView.swift */,
 				090253DD1F0E8BA6006B1609 /* O2LoadingView.swift */,
 				B1298EB323682C21006E9236 /* O2SlideImageAFSource.swift */,
 				B1298EB323682C21006E9236 /* O2SlideImageAFSource.swift */,
 				B1E95F4D2373DDC4004876B7 /* ZoomImageView.swift */,
 				B1E95F4D2373DDC4004876B7 /* ZoomImageView.swift */,
+				B168BDCE24F62BA60070329F /* O2CanCopyUILabel.swift */,
 			);
 			);
 			path = UI;
 			path = UI;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -3447,6 +3466,7 @@
 		E45CD4211DFE503C008F99AD /* Scan-二维码扫码 */ = {
 		E45CD4211DFE503C008F99AD /* Scan-二维码扫码 */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				B168BD9724F5FF410070329F /* m */,
 				E45CD4221DFE503C008F99AD /* c */,
 				E45CD4221DFE503C008F99AD /* c */,
 			);
 			);
 			path = "Scan-二维码扫码";
 			path = "Scan-二维码扫码";
@@ -3455,8 +3475,11 @@
 		E45CD4221DFE503C008F99AD /* c */ = {
 		E45CD4221DFE503C008F99AD /* c */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				B168BDC624F5FFA10070329F /* ScanQRViewController.swift */,
 				B1B21459216073B400D9CA7E /* ScanHelper.swift */,
 				B1B21459216073B400D9CA7E /* ScanHelper.swift */,
 				E457558C1E0BA26000EC44F4 /* NewScanViewController.swift */,
 				E457558C1E0BA26000EC44F4 /* NewScanViewController.swift */,
+				B168BDCA24F607520070329F /* QRCodeResultViewController.swift */,
+				B168BDCB24F607520070329F /* QRCodeResultViewController.xib */,
 			);
 			);
 			path = c;
 			path = c;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -5628,6 +5651,7 @@
 				E46E6CAE1DD41F5D00AB7561 /* ZSSundo@2x.png in Resources */,
 				E46E6CAE1DD41F5D00AB7561 /* ZSSundo@2x.png in Resources */,
 				E46E6C921DD41F5D00AB7561 /* ZSSlink@2x.png in Resources */,
 				E46E6C921DD41F5D00AB7561 /* ZSSlink@2x.png in Resources */,
 				E4C24B4920844F3C00E426B0 /* JCMessageImageCollectionViewCell.xib in Resources */,
 				E4C24B4920844F3C00E426B0 /* JCMessageImageCollectionViewCell.xib in Resources */,
+				B168BDCD24F607520070329F /* QRCodeResultViewController.xib in Resources */,
 				E4C24C1820844F5200E426B0 /* yh_image_picked@2x.png in Resources */,
 				E4C24C1820844F5200E426B0 /* yh_image_picked@2x.png in Resources */,
 				E45755A61E0BA72E00EC44F4 /* qrcode_scan_part_net.png in Resources */,
 				E45755A61E0BA72E00EC44F4 /* qrcode_scan_part_net.png in Resources */,
 				B1489B52248E192D009EE9FD /* IMChatMessageViewCell.xib in Resources */,
 				B1489B52248E192D009EE9FD /* IMChatMessageViewCell.xib in Resources */,
@@ -6236,6 +6260,7 @@
 				B12FD1D42283D5B700E636BA /* ThemeStatePicker.swift in Sources */,
 				B12FD1D42283D5B700E636BA /* ThemeStatePicker.swift in Sources */,
 				E4B888FF1D9D48F1002E1A46 /* MainTodoTaskCell.swift in Sources */,
 				E4B888FF1D9D48F1002E1A46 /* MainTodoTaskCell.swift in Sources */,
 				B1B6A8F9217710C800C10F3C /* FaceRecognizeAPI.swift in Sources */,
 				B1B6A8F9217710C800C10F3C /* FaceRecognizeAPI.swift in Sources */,
+				B168BDCF24F62BA60070329F /* O2CanCopyUILabel.swift in Sources */,
 				B1EE2CD02281771600842F48 /* O2JsApiUtil.swift in Sources */,
 				B1EE2CD02281771600842F48 /* O2JsApiUtil.swift in Sources */,
 				E4B6975020762EA00062F6E8 /* OOPasswordTextField.swift in Sources */,
 				E4B6975020762EA00062F6E8 /* OOPasswordTextField.swift in Sources */,
 				E491664C1E03C09C006133C5 /* O2Account.swift in Sources */,
 				E491664C1E03C09C006133C5 /* O2Account.swift in Sources */,
@@ -6385,6 +6410,7 @@
 				E4B6982E207B5BC30062F6E8 /* UIViewController+Extension.swift in Sources */,
 				E4B6982E207B5BC30062F6E8 /* UIViewController+Extension.swift in Sources */,
 				E4C24B8B20844F3C00E426B0 /* JCBusinessCardContent.swift in Sources */,
 				E4C24B8B20844F3C00E426B0 /* JCBusinessCardContent.swift in Sources */,
 				E491664E1E03D2C1006133C5 /* O2CountdownButton.swift in Sources */,
 				E491664E1E03D2C1006133C5 /* O2CountdownButton.swift in Sources */,
+				B168BDC724F5FFA10070329F /* ScanQRViewController.swift in Sources */,
 				E4E212491E74F96400B1544D /* MainTaskSecondViewController.swift in Sources */,
 				E4E212491E74F96400B1544D /* MainTaskSecondViewController.swift in Sources */,
 				09E02E021F12736C00579887 /* PersonV2.swift in Sources */,
 				09E02E021F12736C00579887 /* PersonV2.swift in Sources */,
 				B1B0102F23586B34002BF874 /* CFFileTableViewCell.swift in Sources */,
 				B1B0102F23586B34002BF874 /* CFFileTableViewCell.swift in Sources */,
@@ -6436,6 +6462,7 @@
 				09E02E971F16319600579887 /* UIImageView+Haneke.swift in Sources */,
 				09E02E971F16319600579887 /* UIImageView+Haneke.swift in Sources */,
 				E4B8887D1D9D48F1002E1A46 /* FileMyDownloadViewController.swift in Sources */,
 				E4B8887D1D9D48F1002E1A46 /* FileMyDownloadViewController.swift in Sources */,
 				E4C24B6620844F3C00E426B0 /* DLFixedTabbarView.m in Sources */,
 				E4C24B6620844F3C00E426B0 /* DLFixedTabbarView.m in Sources */,
+				B168BDCC24F607520070329F /* QRCodeResultViewController.swift in Sources */,
 				B18398B3249B4154001C6FAA /* IMShowLocationViewController.swift in Sources */,
 				B18398B3249B4154001C6FAA /* IMShowLocationViewController.swift in Sources */,
 				E4C24B3520844F3C00E426B0 /* NSLayoutConstraint+JChat.swift in Sources */,
 				E4C24B3520844F3C00E426B0 /* NSLayoutConstraint+JChat.swift in Sources */,
 				E45DA9121DAF7EBE00E0735D /* SZKCleanCache.m in Sources */,
 				E45DA9121DAF7EBE00E0735D /* SZKCleanCache.m in Sources */,
@@ -6494,6 +6521,7 @@
 				E4C24C0E20844F4400E426B0 /* JCAddFriendViewController.swift in Sources */,
 				E4C24C0E20844F4400E426B0 /* JCAddFriendViewController.swift in Sources */,
 				E428AF6720AEA5E300D964B9 /* OOAttandanceSettingDataView.swift in Sources */,
 				E428AF6720AEA5E300D964B9 /* OOAttandanceSettingDataView.swift in Sources */,
 				E40502C520722208009A8D30 /* ImagePickerController.swift in Sources */,
 				E40502C520722208009A8D30 /* ImagePickerController.swift in Sources */,
+				B168BDC924F5FFA80070329F /* ScanRecoObj.swift in Sources */,
 				E4C24B7320844F3C00E426B0 /* JCCEmoticonGroup.swift in Sources */,
 				E4C24B7320844F3C00E426B0 /* JCCEmoticonGroup.swift in Sources */,
 				E4C24BB720844F3C00E426B0 /* JCEmoticonPreviewer.swift in Sources */,
 				E4C24BB720844F3C00E426B0 /* JCEmoticonPreviewer.swift in Sources */,
 				8840A992248CDC9D005970A5 /* OOCalendarEditRemarkViewController.swift in Sources */,
 				8840A992248CDC9D005970A5 /* OOCalendarEditRemarkViewController.swift in Sources */,

+ 165 - 0
o2ios/O2Platform/App/Scan-二维码扫码/c/QRCodeResultViewController.swift

@@ -0,0 +1,165 @@
+//
+//  QRCodeResultViewController.swift
+//  O2Platform
+//
+//  Created by FancyLou on 2020/8/26.
+//  Copyright © 2020 zoneland. All rights reserved.
+//
+
+import UIKit
+import Alamofire
+import AlamofireImage
+import AlamofireObjectMapper
+import ObjectMapper
+import CocoaLumberjack
+import O2OA_Auth_SDK
+
+class QRCodeResultViewController: UIViewController {
+    
+    ///打开扫码结果
+    static func openQRResult(result: String, vc: UIViewController) {
+        let resultVC = QRCodeResultViewController()
+        resultVC.scanResult = result
+        vc.navigationController?.pushViewController(resultVC, animated: false)
+    }
+    
+    @IBOutlet weak var loginStackView: UIStackView!
+    @IBOutlet weak var loginImage: UIImageView!
+    @IBOutlet weak var loginBtn: UIButton!
+    @IBOutlet weak var resultLabel: O2CanCopyUILabel!
+    
+    //扫码结果
+    var scanResult: String?
+    
+    //登录url
+    private var loginURL: String?
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        if let result = scanResult {
+            self.showLoading()
+            //开始解析结果
+            //todo 判断url还是其他
+            self.resolveResult(result: result)
+        }else {
+            self.title = "扫码结果"
+            self.resultLabel.isHidden = false
+            self.resultLabel.text = "扫码结果为空"
+        }
+    }
+
+    @IBAction func tap2Login(_ sender: UIButton) {
+        //点击登陆
+        if let login = self.loginURL {
+            self.showLoading()
+            let account = O2AuthSDK.shared.myInfo()
+            Alamofire.request(login, method: .post, parameters: nil, encoding: JSONEncoding.default, headers: ["x-token":(account?.token)!]).responseJSON(completionHandler: { (response) in
+                switch response.result {
+                case .success(let val):
+                    DispatchQueue.main.async {
+                        DDLogDebug(String(describing:val))
+                        self.hideLoading()
+                        let alertController = UIAlertController(title: "扫描结果", message: "PC端登录成功", preferredStyle: .alert)
+                        let okAction = UIAlertAction(title: "确定", style: .default) {
+                            action in
+                            self.popVC()
+                        }
+                        alertController.addAction(okAction)
+                        self.presentVC(alertController)
+                    }
+                case .failure(let err):
+                    DispatchQueue.main.async {
+                        self.hideLoading()
+                        DDLogError(err.localizedDescription)
+                        let alertController = UIAlertController(title: "扫描结果", message: "PC端登录失败", preferredStyle: .alert)
+                        let okAction = UIAlertAction(title: "确定", style: .destructive) {
+                            action in
+                            self.popVC()
+                        }
+                        alertController.addAction(okAction)
+                        self.presentVC(alertController)
+                    }
+                }
+            })
+        }
+    }
+    
+    ///解析扫码结果
+    private func resolveResult(result: String) {
+        let url = NSURL(string: result)
+       //会议签到功能
+       var isMeetingCheck = false
+       let allU = url?.absoluteString
+       if allU != nil && allU!.contains("/checkin") && allU!.contains("x_meeting_assemble_control") {
+           isMeetingCheck = true
+       }
+        if(isMeetingCheck) {//会议签到
+            self.meetingCheck(url: allU!)
+        }else {
+            self.hideLoading()
+            self.title = "扫码登录"
+            let query = url?.query
+            let querys = query?.split("&")
+            var meta = ""
+            querys?.forEach { (e) in
+                let name = e.split("=")[0]
+                if name == "meta" {
+                    meta = e.split("=")[1]
+                }
+            }
+            if meta != "" {//登录O2OA
+                self.loginURL = AppDelegate.o2Collect.generateURLWithAppContextKey(LoginContext.loginContextKey, query: LoginContext.scanCodeAuthActionQuery, parameter: ["##meta##":meta as AnyObject])
+                self.loginStackView.isHidden = false
+                self.loginBtn.isHidden = false
+                
+            }else {//其他扫描结果
+//                let alertController = UIAlertController(title: "扫描结果", message: result, preferredStyle: .alert)
+//                let okAction = UIAlertAction(title: "确定", style: .default) {
+//                    action in
+//                    self.popVC()
+//                }
+//                alertController.addAction(okAction)
+//                self.presentVC(alertController)
+                self.resultLabel.isHidden = false
+                self.resultLabel.text = result
+            }
+        }
+    }
+    
+    
+    //会议签到
+    private func meetingCheck(url: String) {
+        self.title = "会议签到"
+        let account = O2AuthSDK.shared.myInfo()
+        Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: ["x-token":(account?.token)!]).responseJSON(completionHandler: {(response) in
+            switch response.result {
+            case .success(let val):
+                DispatchQueue.main.async {
+                    self.hideLoading()
+                    DDLogDebug(String(describing:val))
+                    let alertController = UIAlertController(title: "提示", message: "签到成功", preferredStyle: .alert)
+                    let okAction = UIAlertAction(title: "确定", style: .default) {
+                        action in
+                        self.popVC()
+                    }
+                    alertController.addAction(okAction)
+                    self.presentVC(alertController)
+                }
+            case .failure(let err):
+                DispatchQueue.main.async {
+                    self.hideLoading()
+                    DDLogError(err.localizedDescription)
+                    let alertController = UIAlertController(title: "提示", message: "签到失败", preferredStyle: .alert)
+                    let okAction = UIAlertAction(title: "确定", style: .destructive) {
+                        action in
+                        self.popVC()
+                    }
+                    alertController.addAction(okAction)
+                    self.presentVC(alertController)
+                }
+            }
+        })
+    }
+    
+
+}

+ 85 - 0
o2ios/O2Platform/App/Scan-二维码扫码/c/QRCodeResultViewController.xib

@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="QRCodeResultViewController" customModule="O2Platform" customModuleProvider="target">
+            <connections>
+                <outlet property="loginBtn" destination="Mlx-RO-T3c" id="HM9-OP-5au"/>
+                <outlet property="loginImage" destination="olQ-EX-sHG" id="Yga-6S-bdU"/>
+                <outlet property="loginStackView" destination="shd-Ph-gXJ" id="dSK-Ke-Ii7"/>
+                <outlet property="resultLabel" destination="5Ld-tZ-JIj" id="lzN-Zq-00j"/>
+                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
+            <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <stackView hidden="YES" opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="24" translatesAutoresizingMaskIntoConstraints="NO" id="shd-Ph-gXJ">
+                    <rect key="frame" x="20" y="345" width="374" height="126.5"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="scan_login" translatesAutoresizingMaskIntoConstraints="NO" id="olQ-EX-sHG">
+                            <rect key="frame" x="137" y="0.0" width="100" height="82"/>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="即将在电脑上登录O2网页版" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fjt-Bn-lCd">
+                            <rect key="frame" x="80.5" y="106" width="213.5" height="20.5"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                            <nil key="textColor"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                    </subviews>
+                </stackView>
+                <button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Mlx-RO-T3c">
+                    <rect key="frame" x="20" y="555.5" width="374" height="44"/>
+                    <color key="backgroundColor" red="0.98431372549999996" green="0.2784313725" blue="0.2784313725" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="44" id="qEv-jR-Lo4"/>
+                    </constraints>
+                    <state key="normal" title="确认登陆">
+                        <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </state>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="22"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="tap2Login:" destination="-1" eventType="touchUpInside" id="sKR-oX-f12"/>
+                    </connections>
+                </button>
+                <label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="扫码结果显示区域" textAlignment="center" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5Ld-tZ-JIj" customClass="O2CanCopyUILabel" customModule="O2Platform" customModuleProvider="target">
+                    <rect key="frame" x="20" y="438" width="374" height="20.5"/>
+                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                    <nil key="textColor"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+            <constraints>
+                <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="shd-Ph-gXJ" secondAttribute="trailing" constant="20" id="3cR-iT-orK"/>
+                <constraint firstItem="5Ld-tZ-JIj" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="5pd-eX-10e"/>
+                <constraint firstItem="shd-Ph-gXJ" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" constant="-40" id="B5u-rm-amT"/>
+                <constraint firstItem="Mlx-RO-T3c" firstAttribute="top" secondItem="shd-Ph-gXJ" secondAttribute="bottom" constant="84" id="VSJ-Pd-VE4"/>
+                <constraint firstItem="5Ld-tZ-JIj" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="llV-Ck-pyb"/>
+                <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="Mlx-RO-T3c" secondAttribute="trailing" constant="20" id="p6E-wY-2NL"/>
+                <constraint firstItem="Mlx-RO-T3c" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="20" id="pTq-4b-LGf"/>
+                <constraint firstItem="5Ld-tZ-JIj" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="20" id="qWY-1X-zHf"/>
+                <constraint firstItem="shd-Ph-gXJ" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="tpJ-8n-4jM"/>
+                <constraint firstAttribute="trailing" secondItem="5Ld-tZ-JIj" secondAttribute="trailing" constant="20" id="u4R-Tu-M6E"/>
+                <constraint firstItem="shd-Ph-gXJ" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="20" id="wzP-ep-TKF"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
+            <point key="canvasLocation" x="132" y="153"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="scan_login" width="100" height="82"/>
+    </resources>
+</document>

+ 29 - 15
o2ios/O2Platform/App/Scan-二维码扫码/c/ScanHelper.swift

@@ -12,30 +12,44 @@ class ScanHelper {
     
     
     
     
     static func openScan(vc: UIViewController, callbackResult: ((String)->Void)? = nil) {
     static func openScan(vc: UIViewController, callbackResult: ((String)->Void)? = nil) {
-        LBXPermissions.authorizeCameraWith { (result) in
-            if result {
-                if let scanVC = self.initScanViewController(callbackResult: callbackResult) {
-                    vc.pushVC(scanVC)
-                }else {
-                    vc.gotoApplicationSettings(alertMessage: "是否跳转到手机设置页面开启相机权限?")
-                }
+        //新版本 仿新版微信 全屏扫码
+        let scanVC = ScanQRViewController()
+        scanVC.resultBlock = { result in
+            if let callback = callbackResult  {
+                callback(result)
             }else {
             }else {
-                vc.showError(title: "没有摄像头权限,请先开启!")
+                //打开O2业务vc 目前两个功能 扫码登录O2和会议签到
+                QRCodeResultViewController.openQRResult(result: result, vc: vc)
             }
             }
         }
         }
+        scanVC.modalPresentationStyle = .fullScreen
+        vc.present(scanVC, animated: true, completion: nil)
+        
+        //老版本
+//        LBXPermissions.authorizeCameraWith { (result) in
+//            if result {
+//                if let scanVC = self.initScanViewController(callbackResult: callbackResult) {
+//                    vc.navigationController?.pushViewController(scanVC, animated: false)
+//                }else {
+//                    vc.gotoApplicationSettings(alertMessage: "是否跳转到手机设置页面开启相机权限?")
+//                }
+//            }else {
+//                vc.showError(title: "没有摄像头权限,请先开启!")
+//            }
+//        }
     }
     }
     
     
     /// 生成扫码的ViewController 如果没有权限就返回nil
     /// 生成扫码的ViewController 如果没有权限就返回nil
     static private func initScanViewController(callbackResult: ((String)->Void)? = nil) -> NewScanViewController? {
     static private func initScanViewController(callbackResult: ((String)->Void)? = nil) -> NewScanViewController? {
         let scanVC = NewScanViewController()
         let scanVC = NewScanViewController()
         var scanStyle = LBXScanViewStyle()
         var scanStyle = LBXScanViewStyle()
-        scanStyle.centerUpOffset = 44;
-        scanStyle.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner;
-        scanStyle.photoframeLineW = 2;
-        scanStyle.photoframeAngleW = 18;
-        scanStyle.photoframeAngleH = 18;
-        scanStyle.isNeedShowRetangle = false;
-        scanStyle.anmiationStyle = LBXScanViewAnimationStyle.LineMove;
+        scanStyle.centerUpOffset = 44
+        scanStyle.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.Inner
+        scanStyle.photoframeLineW = 2
+        scanStyle.photoframeAngleW = 18
+        scanStyle.photoframeAngleH = 18
+        scanStyle.isNeedShowRetangle = false
+        scanStyle.anmiationStyle = LBXScanViewAnimationStyle.LineMove
         //scanStyle.colorAngle = UIColor(red: 0.0/255, green: 200.0/255.0, blue: 20.0/255.0, alpha: 1.0)
         //scanStyle.colorAngle = UIColor(red: 0.0/255, green: 200.0/255.0, blue: 20.0/255.0, alpha: 1.0)
         scanStyle.colorAngle = O2ThemeManager.color(for: "Base.base_color") ?? UIColor.init(hex: "#fb47474")
         scanStyle.colorAngle = O2ThemeManager.color(for: "Base.base_color") ?? UIColor.init(hex: "#fb47474")
         scanStyle.animationImage = UIImage(named: "qrcode_scan_part_net.png")
         scanStyle.animationImage = UIImage(named: "qrcode_scan_part_net.png")

+ 451 - 0
o2ios/O2Platform/App/Scan-二维码扫码/c/ScanQRViewController.swift

@@ -0,0 +1,451 @@
+//
+//  ScanQRViewController.swift
+//  ScanQRCodeLikeWeChat
+//
+//  Created by FancyLou on 2020/8/25.
+//  Copyright © 2020 muliba. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+import Photos
+
+typealias ScanResultBlock = (String) -> Void
+
+///仿微信 扫码功能 全屏版本
+class ScanQRViewController: UIViewController {
+
+    // MARK: - 返回结果
+    var resultBlock: ScanResultBlock?
+
+    // MARK: - private 参数
+    ///摄像头输出
+    private var output: AVCaptureMetadataOutput?
+    private var session: AVCaptureSession?
+    private var videoDataOutput: AVCaptureVideoDataOutput?
+    private var videoPreviewLayer: AVCaptureVideoPreviewLayer?
+    ///识别结果绘制图集
+    private var reconizationViews: [ScanRecoObj] = []
+    ///定时器
+    private var animationTimeInterval: TimeInterval = 0.02
+    private var timer: Timer?
+
+    private var hasEntered = false
+
+    private var scanBorderW: CGFloat = 0
+    private var scanBorderX: CGFloat = 0
+    private var scanBorderY: CGFloat = 0
+
+    // MARK: - UI
+    private var backBtn: UIButton!
+    private var scanningline: UIImageView?
+
+
+    // MARK: - system lifecycle func
+    override func viewDidAppear(_ animated: Bool) {
+        super.viewDidAppear(animated)
+        self.addTimer()
+    }
+
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        self.removeTimer()
+    }
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.view.backgroundColor = UIColor.black
+        self.scanBorderW = 0.9 * self.view.frame.size.width
+        self.scanBorderX = 0.5 * (1 - 0.9) * self.view.frame.size.width
+        self.scanBorderY = 0.25 * self.view.frame.size.height
+        self.initUI()
+
+        self.prepareScanQRCodeWithResult { (_) in
+            self.scanSessionStart()
+        }
+    }
+
+
+    // MARK: - private func
+    private func initUI() {
+        //返回按钮
+        self.backBtn = UIButton(type: .custom)
+        self.backBtn.frame = CGRect(x: 15, y: 44, width: 44, height: 44)
+        self.backBtn.setImage(UIImage(named: "scan_back"), for: .normal)
+        self.backBtn.addTarget(self, action: #selector(closeSelf), for: .touchUpInside)
+        self.view.addSubview(self.backBtn)
+        //选择相册按钮
+        let photosBtn = UIButton(type: .custom)
+        photosBtn.frame = CGRect(x: (self.view.bounds.size.width - 44) / 2, y: self.view.bounds.size.height - 44 - 34 - 40, width: 44, height: 44)
+        photosBtn.setImage(UIImage(named: "photos_icon"), for: .normal)
+        photosBtn.addTarget(self, action: #selector(photosAction), for: .touchUpInside)
+        self.view.addSubview(photosBtn)
+
+    }
+
+    ///开始扫描
+    private func prepareScanQRCodeWithResult(block: @escaping (String) -> Void) {
+        //判断设备权限
+        guard let _ = AVCaptureDevice.default(for: .video) else {
+            print("没有检测到摄像头,请在真机上测试!")
+            return
+        }
+        let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
+        if authStatus == .restricted {
+            let alertC = UIAlertController(title: "提示", message: "无法访问相机,请检查权限", preferredStyle: .alert)
+            let okAction = UIAlertAction(title: "确定", style: .default, handler: { action in
+
+            })
+            alertC.addAction(okAction)
+            DispatchQueue.main.async {
+                self.present(alertC, animated: true, completion: nil)
+            }
+        } else if authStatus == .denied { //拒绝相机访问权限
+            var name: String? = ""
+            if let dic = Bundle.main.infoDictionary {
+                name = dic["CFBundleDisplayName"] as? String
+                if name == nil {
+                    name = dic["CFBundleName"] as? String
+                }
+            }
+            let message = "[前往:设置 - 隐私 - 相机 - \(name ?? "")] 允许应用访问"
+            let alertC = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
+            let okAction = UIAlertAction(title: "确定", style: .default, handler: { action in
+
+            })
+            alertC.addAction(okAction)
+            DispatchQueue.main.async {
+                self.present(alertC, animated: true, completion: nil)
+            }
+        } else if authStatus == .authorized { //已经允许
+            DispatchQueue.main.async { block("") }
+        } else if authStatus == .notDetermined { //初始未选择
+            AVCaptureDevice.requestAccess(for: .video) { (granted) in
+                if granted {
+                    DispatchQueue.main.async { block("") }
+                } else {
+                    //todo 拒绝访问。。。。
+                }
+            }
+        }
+    }
+
+    ///准备摄像头,正式开始扫描
+    private func scanSessionStart() {
+        // 获取摄像头
+        guard let device = AVCaptureDevice.default(for: .video) else {
+            print("没有检测到摄像头,请在真机上测试!")
+            return
+        }
+        var input: AVCaptureDeviceInput?
+        do {
+            input = try AVCaptureDeviceInput(device: device)
+        } catch {
+            print("err: \(error.localizedDescription)")
+        }
+        guard let deviceInput = input else {
+            print("输入流创建失败")
+            return
+        }
+        //输出流
+        self.output = AVCaptureMetadataOutput()
+        self.output?.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
+        // 注:微信二维码的扫描范围是整个屏幕,这里并没有做处理(可不用设置);
+        // 如需限制扫描框范围,如下
+        //    if !cropRect.equalTo(CGRect.zero)
+//        {
+        //启动相机后,直接修改该参数无效
+//            output.rectOfInterest = cropRect
+//        }
+        //创建session
+        self.session = AVCaptureSession()
+        self.session?.sessionPreset = .high
+        //添加元数据输出流到会话对象
+        self.session?.addOutput(self.output!)
+        //创建摄像数据输出流并将其添加到会话对象上,  --> 用于识别光线强弱
+        self.videoDataOutput = AVCaptureVideoDataOutput()
+        self.videoDataOutput?.setSampleBufferDelegate(self, queue: DispatchQueue.main)
+        self.session?.addOutput(self.videoDataOutput!)
+        //添加摄像设备输入流到会话对象
+        self.session?.addInput(deviceInput)
+        //识别类型
+        self.output?.metadataObjectTypes = [.qr, .ean13, .ean8, .code128]
+        self.videoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session!)
+        self.videoPreviewLayer?.videoGravity = .resizeAspectFill
+        self.videoPreviewLayer?.frame = self.view.bounds
+        self.view.layer.insertSublayer(self.videoPreviewLayer!, at: 0)
+
+        self.session?.startRunning()
+
+    }
+
+    ///添加定时器
+    private func addTimer() {
+        if self.session != nil && self.session?.isRunning != true && hasEntered {
+            self.session?.startRunning()
+        }
+        hasEntered = true
+        //扫描的时候绿色线条
+        self.scanningline = UIImageView(image: UIImage(named: "QRCodeScanLine"))
+        self.view.addSubview(self.scanningline!)
+
+        self.scanningline?.frame = CGRect(x: self.scanBorderX, y: self.scanBorderY, width: self.scanBorderW, height: 12)
+        self.scanningline?.isHidden = true
+        self.timer = Timer.scheduledTimer(timeInterval: self.animationTimeInterval, target: self, selector: #selector(beginRefreshUI), userInfo: nil, repeats: true)
+        self.timer?.fire()
+    }
+
+    ///移除定时器
+    private func removeTimer() {
+        self.timer?.invalidate()
+        self.timer = nil
+        self.scanningline?.removeFromSuperview()
+        self.scanningline = nil
+        if self.session?.isRunning == true {
+            self.session?.stopRunning()
+        }
+    }
+
+    //开始动画
+    @objc private func beginRefreshUI() {
+        //防止还没开始执行定时器就扫描到码,导致扫描动画一直进行
+        if self.session?.isRunning != true {
+            self.removeTimer()
+            return
+        }
+        self.scanningline?.isHidden = false
+        var frame = self.scanningline?.frame
+        if self.scanningline?.frame.origin.y ?? self.scanBorderY >= self.scanBorderY {
+            let maxY = self.view.frame.size.height - self.scanBorderY
+            if self.scanningline?.frame.origin.y ?? self.scanBorderY >= maxY - 10 {
+                frame?.origin.y = self.scanBorderY
+                self.scanningline?.frame = frame!
+            } else {
+                UIView.animate(withDuration: self.animationTimeInterval) {
+                    frame?.origin.y += 2
+                    self.scanningline?.frame = frame!
+                }
+            }
+        }
+
+    }
+
+
+    ///返回结果 关闭页面
+    private func processWithResult(result: String) {
+        self.resultBlock?(result)
+        self.dismiss(animated: true, completion: nil)
+    }
+
+    ///关闭当前扫描页面
+    @objc private func closeSelf() {
+        if self.session?.isRunning == true {
+            self.session?.stopRunning()
+        }
+        self.dismiss(animated: true, completion: nil)
+    }
+
+    //取消扫描出来的结果 继续扫描
+    @objc private func cancelResult() {
+        if self.session?.isRunning == true {
+            self.session?.stopRunning()
+        }
+        self.reconizationViews.forEach { (obj) in
+            obj.codeView.removeFromSuperview()
+        }
+        self.reconizationViews.removeAll()
+        if self.session?.isRunning == false {
+            self.addTimer()
+        }
+        self.backBtn.isHidden = false
+    }
+
+    ///从相册选择照片
+    @objc private func photosAction() {
+        let authStatus = PHPhotoLibrary.authorizationStatus()
+        if authStatus == .restricted {
+            let alertC = UIAlertController(title: "提示", message: "无法访问相册,请检查权限", preferredStyle: .alert)
+            let okAction = UIAlertAction(title: "确定", style: .default, handler: { action in
+
+            })
+            alertC.addAction(okAction)
+            DispatchQueue.main.async {
+                self.present(alertC, animated: true, completion: nil)
+            }
+        } else if authStatus == .denied { //拒绝相机访问权限
+            var name: String? = ""
+            if let dic = Bundle.main.infoDictionary {
+                name = dic["CFBundleDisplayName"] as? String
+                if name == nil {
+                    name = dic["CFBundleName"] as? String
+                }
+            }
+            let message = "[前往:设置 - 隐私 - 照片 - \(name ?? "")] 允许应用访问"
+            let alertC = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
+            let okAction = UIAlertAction(title: "确定", style: .default, handler: { action in
+
+            })
+            alertC.addAction(okAction)
+            DispatchQueue.main.async {
+                self.present(alertC, animated: true, completion: nil)
+            }
+        } else if authStatus == .authorized { //已经允许
+            DispatchQueue.main.async { self.enterPhotos() }
+        } else if authStatus == .notDetermined { //初始未选择
+            PHPhotoLibrary.requestAuthorization { (status) in
+                if status == .authorized {
+                    DispatchQueue.main.async { self.enterPhotos() }
+                } else {
+                    //todo 拒绝访问。。。。
+                }
+            }
+        }
+    }
+
+    @objc private func clickCurrentCode(btn: UIButton) {
+        let obj = self.reconizationViews[btn.tag]
+        self.processWithResult(result: obj.codeString)
+    }
+
+
+    ///打开相册
+    private func enterPhotos() {
+        let imagePicker = UIImagePickerController()
+        imagePicker.sourceType = .photoLibrary
+        imagePicker.delegate = self
+        imagePicker.modalPresentationStyle = .fullScreen
+        self.present(imagePicker, animated: true, completion: nil)
+    }
+
+    ///生成遮障层
+    private func getMaskView(showTips: Bool) -> UIView {
+        let maskView = UIView(frame: self.view.bounds)
+        maskView.backgroundColor = UIColor(displayP3Red: 0, green: 0, blue: 0, alpha: 0.6)
+        if showTips {
+            let cancel = UIButton(type: .custom)
+            cancel.frame = CGRect(x: 15, y: 44, width: 50, height: 44)
+            cancel.setTitle("取消", for: .normal)
+            cancel.setTitleColor(.white, for: .normal)
+            cancel.addTarget(self, action: #selector(cancelResult), for: .touchUpInside)
+            maskView.addSubview(cancel)
+            let tips = UILabel(frame: CGRect(x: 20, y: self.view.bounds.size.height - 64 - 50, width: self.view.bounds.size.width - 40, height: 50))
+            tips.text = "轻触小蓝点,选中识别二维码"
+            tips.font = UIFont.boldSystemFont(ofSize: 14)
+            tips.textAlignment = .center
+            tips.textColor = UIColor(displayP3Red: 1, green: 1, blue: 1, alpha: 0.6)
+            maskView.addSubview(tips)
+        }
+        return maskView
+    }
+
+    //动画
+    private func getAnimation() -> CAKeyframeAnimation {
+        let ani = CAKeyframeAnimation(keyPath: "transform.scale")
+        ani.duration = 2.8
+        ani.isRemovedOnCompletion = false
+        ani.repeatCount = HUGE
+        ani.fillMode = .forwards
+        ani.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
+        let v1 = NSNumber(value: 1.0)
+        let v2 = NSNumber(value: 0.8)
+        ani.values = [v1, v2, v1, v2, v1, v1, v1, v1]
+        return ani
+    }
+
+    ///生成扫码结果提示按钮
+    private func getScanResultCode(bounds: CGRect, icon: Bool) -> UIButton {
+        let btn = UIButton(type: .custom)
+        btn.frame = bounds
+        btn.backgroundColor = UIColor(displayP3Red: 54 / 255.0, green: 85 / 255.0, blue: 230 / 255.0, alpha: 1)
+        btn.addTarget(self, action: #selector(clickCurrentCode(btn:)), for: .touchUpInside)
+        if icon {
+            btn.setImage(UIImage(named: "right_arrow_icon"), for: .normal)
+            btn.layer.add(self.getAnimation(), forKey: "scale-layer")
+        }
+        var rect = btn.frame
+        let center = btn.center
+        rect.size.width = 40
+        rect.size.height = 40
+        btn.frame = rect
+        btn.center = center
+        btn.layer.cornerRadius = 20
+        btn.clipsToBounds = true
+        btn.layer.borderColor = UIColor.white.cgColor
+        btn.layer.borderWidth = 3
+        return btn
+    }
+}
+
+// MARK: - 摄像头识别代理
+extension ScanQRViewController: AVCaptureMetadataOutputObjectsDelegate, AVCaptureVideoDataOutputSampleBufferDelegate {
+    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
+        if metadataObjects.count > 0 {
+            self.removeTimer()
+            if #available(iOS 10, *) {
+                let impact = UIImpactFeedbackGenerator(style: .light)
+                impact.impactOccurred()
+            }
+            let maskView = self.getMaskView(showTips: metadataObjects.count > 1)
+            maskView.alpha = 0
+            self.view.addSubview(maskView)
+            UIView.animate(withDuration: 0.6) {
+                maskView.alpha = 1
+            }
+            let obj = ScanRecoObj(codeView: maskView, codeString: "")
+            self.reconizationViews.append(obj)
+
+            var indx = 0
+            for meta in metadataObjects {
+                if meta.isKind(of: AVMetadataMachineReadableCodeObject.self) {
+                    let code = self.videoPreviewLayer?.transformedMetadataObject(for: meta) as! AVMetadataMachineReadableCodeObject
+                    let codeBtn = self.getScanResultCode(bounds: code.bounds, icon: metadataObjects.count > 1)
+                    codeBtn.tag = indx + 1
+                    self.view.addSubview(codeBtn)
+                    let codeObj = ScanRecoObj(codeView: codeBtn, codeString: code.stringValue ?? "")
+                    self.reconizationViews.append(codeObj)
+                }
+                indx += 1
+            }
+            self.backBtn.isHidden = true
+            if metadataObjects.count == 1 { //只有一个直接返回结果 不需要点击
+                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.8) {
+                    self.processWithResult(result: self.reconizationViews[1].codeString)
+                }
+            }
+        }
+    }
+}
+
+// MARK: - 相册选择器代理
+extension ScanQRViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
+    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
+        self.dismiss(animated: true, completion: nil)
+    }
+
+    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
+        guard let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else {
+            return
+        }
+        let context = CIContext(options: nil)
+        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
+        guard let ciImage = CIImage(image: image) else {
+            return
+        }
+        let features = detector?.features(in: ciImage)
+        if features?.count == 0 {
+            DispatchQueue.main.async {
+                self.dismiss(animated: true) {
+                    self.processWithResult(result: "")
+                }
+            }
+        } else {
+            if let feature = features?.first as? CIQRCodeFeature, let result = feature.messageString {
+                DispatchQueue.main.async {
+                    self.dismiss(animated: true) {
+                        self.processWithResult(result: result)
+                    }
+                }
+            }
+        }
+    }
+}

+ 15 - 0
o2ios/O2Platform/App/Scan-二维码扫码/m/ScanRecoObj.swift

@@ -0,0 +1,15 @@
+//
+//  ScanRecoObj.swift
+//  ScanQRCodeLikeWeChat
+//
+//  Created by FancyLou on 2020/8/25.
+//  Copyright © 2020 muliba. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+struct ScanRecoObj {
+    var codeView: UIView
+    var codeString: String
+}

+ 21 - 0
o2ios/O2Platform/Assets.xcassets/login/scan_login.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "scan_login_content_2.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
o2ios/O2Platform/Assets.xcassets/login/scan_login.imageset/scan_login_content_2.png


+ 0 - 6
o2ios/O2Platform/Assets.xcassets/whipster/Contents.json

@@ -1,6 +0,0 @@
-{
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}

+ 21 - 0
o2ios/O2Platform/Assets.xcassets/首页/QRCodeScanLine.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "QRCodeScanLine@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
o2ios/O2Platform/Assets.xcassets/首页/QRCodeScanLine.imageset/QRCodeScanLine@2x.png


+ 21 - 0
o2ios/O2Platform/Assets.xcassets/首页/photos_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "photos_icon@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
o2ios/O2Platform/Assets.xcassets/首页/photos_icon.imageset/photos_icon@2x.png


+ 21 - 0
o2ios/O2Platform/Assets.xcassets/首页/right_arrow_icon.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "right@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
o2ios/O2Platform/Assets.xcassets/首页/right_arrow_icon.imageset/right@2x.png


+ 21 - 0
o2ios/O2Platform/Assets.xcassets/首页/scan_back.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "scan_back@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
o2ios/O2Platform/Assets.xcassets/首页/scan_back.imageset/scan_back@2x.png


+ 1 - 11
o2ios/O2Platform/Framework/scan/LBXScanViewController.swift

@@ -50,10 +50,8 @@ open class LBXScanViewController: UIViewController, UIImagePickerControllerDeleg
         // Do any additional setup after loading the view.
         // Do any additional setup after loading the view.
         
         
               // [self.view addSubview:_qRScanView];
               // [self.view addSubview:_qRScanView];
-        print("viewDidLoad...........")
         self.view.backgroundColor = UIColor.black
         self.view.backgroundColor = UIColor.black
         self.edgesForExtendedLayout = UIRectEdge(rawValue: 0)
         self.edgesForExtendedLayout = UIRectEdge(rawValue: 0)
-         print("viewDidLoad......end.....")
         
         
         drawScanView()
         drawScanView()
         
         
@@ -71,22 +69,18 @@ open class LBXScanViewController: UIViewController, UIImagePickerControllerDeleg
  
  
     override open func viewWillAppear(_ animated: Bool) {
     override open func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         super.viewWillAppear(animated)
-         print("viewWillAppear...........")
     }
     }
     
     
     override open func viewDidAppear(_ animated: Bool) {
     override open func viewDidAppear(_ animated: Bool) {
         
         
         super.viewDidAppear(animated)
         super.viewDidAppear(animated)
-        print("viewDidAppear...........")
         
         
     }
     }
     
     
     @objc open func startScan()
     @objc open func startScan()
     {
     {
-        print("startScan.     .................")
         if (scanObj == nil)
         if (scanObj == nil)
         {
         {
-            print("scanObj   oooo..................")
             var cropRect = CGRect.zero
             var cropRect = CGRect.zero
             if isOpenInterestRect
             if isOpenInterestRect
             {
             {
@@ -96,7 +90,7 @@ open class LBXScanViewController: UIViewController, UIImagePickerControllerDeleg
             //指定识别几种码
             //指定识别几种码
             if arrayCodeType == nil
             if arrayCodeType == nil
             {
             {
-                arrayCodeType = [AVMetadataObject.ObjectType.qr as NSString ,AVMetadataObject.ObjectType.ean13 as NSString ,AVMetadataObject.ObjectType.code128 as NSString] as [AVMetadataObject.ObjectType]
+                arrayCodeType = [AVMetadataObject.ObjectType.qr as NSString] as [AVMetadataObject.ObjectType]
             }
             }
             
             
             scanObj = LBXScanWrapper(videoPreView: self.view,objType:arrayCodeType!, isCaptureImg: isNeedCodeImage,cropRect:cropRect, success: { [weak self] (arrayResult) -> Void in
             scanObj = LBXScanWrapper(videoPreView: self.view,objType:arrayCodeType!, isCaptureImg: isNeedCodeImage,cropRect:cropRect, success: { [weak self] (arrayResult) -> Void in
@@ -113,20 +107,16 @@ open class LBXScanViewController: UIViewController, UIImagePickerControllerDeleg
         
         
         //结束相机等待提示
         //结束相机等待提示
         qRScanView?.deviceStopReadying()
         qRScanView?.deviceStopReadying()
-        print("qRScanView   deviceStopReadying..................")
         //开始扫描动画
         //开始扫描动画
         qRScanView?.startScanAnimation()
         qRScanView?.startScanAnimation()
-        print("qRScanView   startScanAnimation..................")
         //相机运行
         //相机运行
         scanObj?.start()
         scanObj?.start()
-        print("scanObj   start..................")
     }
     }
     
     
     open func drawScanView()
     open func drawScanView()
     {
     {
         if qRScanView == nil
         if qRScanView == nil
         {
         {
-            print("drawScanView..................")
             qRScanView = LBXScanView(frame: self.view.frame,vstyle:scanStyle! )
             qRScanView = LBXScanView(frame: self.view.frame,vstyle:scanStyle! )
             self.view.addSubview(qRScanView!)
             self.view.addSubview(qRScanView!)
             delegate?.drawwed()
             delegate?.drawwed()

+ 315 - 254
o2ios/O2Platform/Framework/scan/LBXScanWrapper.swift

@@ -9,19 +9,19 @@
 import UIKit
 import UIKit
 import AVFoundation
 import AVFoundation
 
 
-public struct  LBXScanResult {
-    
+public struct LBXScanResult {
+
     //码内容
     //码内容
-    public var strScanned:String? = ""
+    public var strScanned: String? = ""
     //扫描图像
     //扫描图像
-    public var imgScanned:UIImage?
+    public var imgScanned: UIImage?
     //码的类型
     //码的类型
-    public var strBarCodeType:String? = ""
-    
+    public var strBarCodeType: String? = ""
+
     //码在图像中的位置
     //码在图像中的位置
-    public var arrayCorner:[AnyObject]?
-    
-    public init(str:String?,img:UIImage?,barCodeType:String?,corner:[AnyObject]?)
+    public var arrayCorner: [AnyObject]?
+
+    public init(str: String?, img: UIImage?, barCodeType: String?, corner: [AnyObject]?)
     {
     {
         self.strScanned = str
         self.strScanned = str
         self.imgScanned = img
         self.imgScanned = img
@@ -32,28 +32,34 @@ public struct  LBXScanResult {
 
 
 
 
 
 
-open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
-    
+open class LBXScanWrapper: NSObject, AVCaptureMetadataOutputObjectsDelegate {
+
     let device = AVCaptureDevice.default(for: AVMediaType.video)
     let device = AVCaptureDevice.default(for: AVMediaType.video)
-    var input:AVCaptureDeviceInput?
-    var output:AVCaptureMetadataOutput
-    
+    var input: AVCaptureDeviceInput?
+    var output: AVCaptureMetadataOutput
+
     let session = AVCaptureSession()
     let session = AVCaptureSession()
-    var previewLayer:AVCaptureVideoPreviewLayer?
-    var stillImageOutput:AVCaptureStillImageOutput?
+    var previewLayer: AVCaptureVideoPreviewLayer?
+    var stillImageOutput: AVCaptureStillImageOutput?
+
+    var videoPreView: UIView?
     
     
-    //存储返回结果
-    var arrayResult:[LBXScanResult] = [];
+    var scaleSize:CGFloat = 1
     
     
+    //存储返回结果
+    var arrayResult: [LBXScanResult] = [];
+
     //扫码结果返回block
     //扫码结果返回block
-    var successBlock:([LBXScanResult]) -> Void
-    
+    var successBlock: ([LBXScanResult]) -> Void
+
     //是否需要拍照
     //是否需要拍照
-    var isNeedCaptureImage:Bool
-    
+    var isNeedCaptureImage: Bool
+
     //当前扫码结果是否处理
     //当前扫码结果是否处理
-    var isNeedScanResult:Bool = true
+    var isNeedScanResult: Bool = true
     
     
+    
+
     /**
     /**
      初始化设备
      初始化设备
      - parameter videoPreView: 视频显示UIView
      - parameter videoPreView: 视频显示UIView
@@ -63,90 +69,92 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
      - parameter success:      返回识别信息
      - parameter success:      返回识别信息
      - returns:
      - returns:
      */
      */
-    init( videoPreView:UIView,objType:[AVMetadataObject.ObjectType] = [(AVMetadataObject.ObjectType.qr as NSString) as AVMetadataObject.ObjectType],isCaptureImg:Bool,cropRect:CGRect=CGRect.zero,success:@escaping ( ([LBXScanResult]) -> Void) )
+    init(videoPreView: UIView, objType: [AVMetadataObject.ObjectType] = [(AVMetadataObject.ObjectType.qr as NSString) as AVMetadataObject.ObjectType], isCaptureImg: Bool, cropRect: CGRect = CGRect.zero, success: @escaping (([LBXScanResult]) -> Void))
     {
     {
-        do{
+        self.videoPreView = videoPreView
+        
+        do {
             input = try AVCaptureDeviceInput(device: device!)
             input = try AVCaptureDeviceInput(device: device!)
         }
         }
         catch let error as NSError {
         catch let error as NSError {
             print("AVCaptureDeviceInput(): \(error)")
             print("AVCaptureDeviceInput(): \(error)")
         }
         }
-        
+
         successBlock = success
         successBlock = success
-        
+
         // Output
         // Output
         output = AVCaptureMetadataOutput()
         output = AVCaptureMetadataOutput()
-        
+
         isNeedCaptureImage = isCaptureImg
         isNeedCaptureImage = isCaptureImg
-        
+
         stillImageOutput = AVCaptureStillImageOutput();
         stillImageOutput = AVCaptureStillImageOutput();
-        
+
         super.init()
         super.init()
-        
+
         if device == nil || input == nil {
         if device == nil || input == nil {
             return
             return
         }
         }
-        
+
         if session.canAddInput(input!) {
         if session.canAddInput(input!) {
             session.addInput(input!)
             session.addInput(input!)
         }
         }
-        
+
         if session.canAddOutput(output) {
         if session.canAddOutput(output) {
             session.addOutput(output)
             session.addOutput(output)
         }
         }
-        
+
         if session.canAddOutput(stillImageOutput!) {
         if session.canAddOutput(stillImageOutput!) {
             session.addOutput(stillImageOutput!)
             session.addOutput(stillImageOutput!)
         }
         }
-        
-        let outputSettings:Dictionary = [AVVideoCodecJPEG:AVVideoCodecKey]
+
+        let outputSettings: Dictionary = [AVVideoCodecJPEG: AVVideoCodecKey]
         stillImageOutput?.outputSettings = outputSettings
         stillImageOutput?.outputSettings = outputSettings
-        
+
         session.sessionPreset = AVCaptureSession.Preset.high
         session.sessionPreset = AVCaptureSession.Preset.high
-        
+
         //参数设置
         //参数设置
         output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
         output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
-        
+
         output.metadataObjectTypes = objType
         output.metadataObjectTypes = objType
-        
-        //        output.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]
-        
+
         if !cropRect.equalTo(CGRect.zero)
         if !cropRect.equalTo(CGRect.zero)
         {
         {
             //启动相机后,直接修改该参数无效
             //启动相机后,直接修改该参数无效
             output.rectOfInterest = cropRect
             output.rectOfInterest = cropRect
         }
         }
-        
+
         previewLayer = AVCaptureVideoPreviewLayer(session: session)
         previewLayer = AVCaptureVideoPreviewLayer(session: session)
         previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
         previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
-        
-        var frame:CGRect = videoPreView.frame
+
+        var frame: CGRect = videoPreView.frame
         frame.origin = CGPoint.zero
         frame.origin = CGPoint.zero
         previewLayer?.frame = frame
         previewLayer?.frame = frame
+     
+        videoPreView.layer.insertSublayer(previewLayer!, at: 0)
         
         
-        videoPreView.layer .insertSublayer(previewLayer!, at: 0)
-        
-        if ( device!.isFocusPointOfInterestSupported && device!.isFocusModeSupported(AVCaptureDevice.FocusMode.continuousAutoFocus) )
-        {
-            do
+        do {
+            try input?.device.lockForConfiguration()
+
+            if device?.isWhiteBalanceModeSupported(.autoWhiteBalance) == true {
+                input?.device.whiteBalanceMode = .autoWhiteBalance
+            }
+
+            if (device!.isFocusPointOfInterestSupported && device!.isFocusModeSupported(AVCaptureDevice.FocusMode.continuousAutoFocus))
             {
             {
-                try input?.device.lockForConfiguration()
-                
                 input?.device.focusMode = AVCaptureDevice.FocusMode.continuousAutoFocus
                 input?.device.focusMode = AVCaptureDevice.FocusMode.continuousAutoFocus
-                
-                input?.device.unlockForConfiguration()
-            }
-            catch let error as NSError {
-                print("device.lockForConfiguration(): \(error)")
-                
             }
             }
+            
+            input?.device.unlockForConfiguration()
+        } catch let error as NSError {
+            print("device.lockForConfiguration(): \(error)")
         }
         }
+         
     }
     }
-    
+
     public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
     public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
         captureOutput(output, didOutputMetadataObjects: metadataObjects, from: connection)
         captureOutput(output, didOutputMetadataObjects: metadataObjects, from: connection)
     }
     }
-    
+
     func start()
     func start()
     {
     {
         if !session.isRunning
         if !session.isRunning
@@ -164,39 +172,92 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         }
         }
     }
     }
     
     
-    open func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
-        
+//    func setVideoScale(scale: CGFloat) {
+//        print("调整镜头................")
+//        do {
+//            try input?.device.lockForConfiguration()
+//            let videoConnection = self.connectionWithMediaType(mediaType: .video, connections: self.stillImageOutput?.connections ?? [])
+//            let maxScaleAndCropFactor = self.stillImageOutput?.connection(with: .video)?.videoMaxScaleAndCropFactor ?? 0 / 16
+//            var newScale = scale
+//            if newScale > maxScaleAndCropFactor {
+//                newScale = maxScaleAndCropFactor
+//            }
+//            print("scale.....\(newScale)")
+//            let videoFactor = videoConnection?.videoScaleAndCropFactor ?? 1
+//            let zoom = newScale / videoFactor
+//            videoConnection?.videoScaleAndCropFactor = newScale
+//            input?.device.unlockForConfiguration()
+//            print("zoom.......\(zoom)")
+//            if let transform = self.videoPreView?.transform {
+//                self.videoPreView?.transform = transform.scaledBy(x: zoom, y: zoom)
+//            }
+//
+//        } catch let error as NSError {
+//           print("device.lockForConfiguration(): \(error)")
+//       }
+//    }
+//
+//    func changeVideoScale(obj: AVMetadataMachineReadableCodeObject?) {
+//        if let o = obj {
+//            let arr = o.corners
+//            if arr.count >= 3 {
+//                let point = arr[1]
+//                let point2 = arr[2]
+//                let scale = 150 / (point2.x -  point.x) //当二维码图片宽小于150,进行放大
+//                print("scale.......\(scale)")
+//                if scale > 1 {
+//                    for item in stride(from: 1, to: scale, by: 0.01) {
+//                        self.setVideoScale(scale: item)
+//                    }
+//                }
+//            }
+//        }
+//    }
+
+    open func captureOutput(_ captureOutput: AVCaptureOutput, didOutputMetadataObjects metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
+
         if !isNeedScanResult
         if !isNeedScanResult
         {
         {
             //上一帧处理中
             //上一帧处理中
             return
             return
         }
         }
-        
+
         isNeedScanResult = false
         isNeedScanResult = false
-        
+
         arrayResult.removeAll()
         arrayResult.removeAll()
+
+//        print(metadataObjects)
+        
+//        if metadataObjects.count < 1 {
+//            if self.scaleSize == 1 {
+//                self.scaleSize = 2
+//            }else {
+//                self.scaleSize = 1
+//            }
+//            self.setVideoScale(scale: self.scaleSize)
+//        }
         
         
         //识别扫码类型
         //识别扫码类型
-        for current:Any in metadataObjects
+        for current  in metadataObjects
         {
         {
-            if (current as AnyObject).isKind(of: AVMetadataMachineReadableCodeObject.self)
+            if (current).isKind(of: AVMetadataMachineReadableCodeObject.self)
             {
             {
                 let code = current as! AVMetadataMachineReadableCodeObject
                 let code = current as! AVMetadataMachineReadableCodeObject
-                
+
                 //码类型
                 //码类型
                 let codeType = code.type
                 let codeType = code.type
                 //                print("code type:%@",codeType)
                 //                print("code type:%@",codeType)
                 //码内容
                 //码内容
                 let codeContent = code.stringValue
                 let codeContent = code.stringValue
                 //                print("code string:%@",codeContent)
                 //                print("code string:%@",codeContent)
-                
+
                 //4个字典,分别 左上角-右上角-右下角-左下角的 坐标百分百,可以使用这个比例抠出码的图像
                 //4个字典,分别 左上角-右上角-右下角-左下角的 坐标百分百,可以使用这个比例抠出码的图像
                 // let arrayRatio = code.corners
                 // let arrayRatio = code.corners
-                
+
                 arrayResult.append(LBXScanResult(str: codeContent, img: UIImage(), barCodeType: codeType.rawValue, corner: code.corners as [AnyObject]?))
                 arrayResult.append(LBXScanResult(str: codeContent, img: UIImage(), barCodeType: codeType.rawValue, corner: code.corners as [AnyObject]?))
             }
             }
         }
         }
-        
+
         if arrayResult.count > 0
         if arrayResult.count > 0
         {
         {
             if isNeedCaptureImage
             if isNeedCaptureImage
@@ -208,52 +269,52 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
                 stop()
                 stop()
                 successBlock(arrayResult)
                 successBlock(arrayResult)
             }
             }
-            
+
         }
         }
         else
         else
         {
         {
             isNeedScanResult = true
             isNeedScanResult = true
         }
         }
-        
+
     }
     }
-    
+
     //MARK: ----拍照
     //MARK: ----拍照
     open func captureImage()
     open func captureImage()
     {
     {
-        let stillImageConnection:AVCaptureConnection? = connectionWithMediaType(mediaType: AVMediaType.video as AVMediaType, connections: (stillImageOutput?.connections)! as [AnyObject])
-        
-        
+        let stillImageConnection: AVCaptureConnection? = connectionWithMediaType(mediaType: AVMediaType.video as AVMediaType, connections: (stillImageOutput?.connections)! as [AnyObject])
+
+
         stillImageOutput?.captureStillImageAsynchronously(from: stillImageConnection!, completionHandler: { (imageDataSampleBuffer, error) -> Void in
         stillImageOutput?.captureStillImageAsynchronously(from: stillImageConnection!, completionHandler: { (imageDataSampleBuffer, error) -> Void in
-            
+
             self.stop()
             self.stop()
             if imageDataSampleBuffer != nil
             if imageDataSampleBuffer != nil
             {
             {
                 let imageData: Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer!)!
                 let imageData: Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer!)!
-                let scanImg:UIImage? = UIImage(data: imageData)
-                
-                
-                for idx in 0...self.arrayResult.count-1
+                let scanImg: UIImage? = UIImage(data: imageData)
+
+
+                for idx in 0...self.arrayResult.count - 1
                 {
                 {
                     self.arrayResult[idx].imgScanned = scanImg
                     self.arrayResult[idx].imgScanned = scanImg
                 }
                 }
             }
             }
-            
+
             self.successBlock(self.arrayResult)
             self.successBlock(self.arrayResult)
-            
+
         })
         })
     }
     }
-    
-    open func connectionWithMediaType(mediaType:AVMediaType, connections:[AnyObject]) -> AVCaptureConnection?
+
+    open func connectionWithMediaType(mediaType: AVMediaType, connections: [AnyObject]) -> AVCaptureConnection?
     {
     {
-        for connection:AnyObject in connections
+        for connection: AnyObject in connections
         {
         {
-            let connectionTmp:AVCaptureConnection = connection as! AVCaptureConnection
-            
-            for port:Any in connectionTmp.inputPorts
+            let connectionTmp: AVCaptureConnection = connection as! AVCaptureConnection
+
+            for port: Any in connectionTmp.inputPorts
             {
             {
                 if (port as AnyObject).isKind(of: AVCaptureInput.Port.self)
                 if (port as AnyObject).isKind(of: AVCaptureInput.Port.self)
                 {
                 {
-                    let portTmp:AVCaptureInput.Port = port as! AVCaptureInput.Port
+                    let portTmp: AVCaptureInput.Port = port as! AVCaptureInput.Port
                     if portTmp.mediaType == mediaType
                     if portTmp.mediaType == mediaType
                     {
                     {
                         return connectionTmp
                         return connectionTmp
@@ -263,58 +324,58 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         }
         }
         return nil
         return nil
     }
     }
-    
-    
+
+
     //MARK:切换识别区域
     //MARK:切换识别区域
-    open func changeScanRect(cropRect:CGRect)
+    open func changeScanRect(cropRect: CGRect)
     {
     {
         //待测试,不知道是否有效
         //待测试,不知道是否有效
         stop()
         stop()
         output.rectOfInterest = cropRect
         output.rectOfInterest = cropRect
         start()
         start()
     }
     }
-    
+
     //MARK: 切换识别码的类型
     //MARK: 切换识别码的类型
-    open func changeScanType(objType:[AVMetadataObject.ObjectType])
+    open func changeScanType(objType: [AVMetadataObject.ObjectType])
     {
     {
         //待测试中途修改是否有效
         //待测试中途修改是否有效
         output.metadataObjectTypes = objType
         output.metadataObjectTypes = objType
     }
     }
-    
-    open func isGetFlash()->Bool
+
+    open func isGetFlash() -> Bool
     {
     {
-        if (device != nil &&  device!.hasFlash && device!.hasTorch)
+        if (device != nil && device!.hasFlash && device!.hasTorch)
         {
         {
             return true
             return true
         }
         }
         return false
         return false
     }
     }
-    
+
     /**
     /**
      打开或关闭闪关灯
      打开或关闭闪关灯
      - parameter torch: true:打开闪关灯 false:关闭闪光灯
      - parameter torch: true:打开闪关灯 false:关闭闪光灯
      */
      */
-    open func setTorch(torch:Bool)
+    open func setTorch(torch: Bool)
     {
     {
         if isGetFlash()
         if isGetFlash()
         {
         {
             do
             do
             {
             {
                 try input?.device.lockForConfiguration()
                 try input?.device.lockForConfiguration()
-                
+
                 input?.device.torchMode = torch ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
                 input?.device.torchMode = torch ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
-                
+
                 input?.device.unlockForConfiguration()
                 input?.device.unlockForConfiguration()
             }
             }
             catch let error as NSError {
             catch let error as NSError {
                 print("device.lockForConfiguration(): \(error)")
                 print("device.lockForConfiguration(): \(error)")
-                
+
             }
             }
         }
         }
-        
+
     }
     }
-    
-    
+
+
     /**
     /**
      ------闪光灯打开或关闭
      ------闪光灯打开或关闭
      */
      */
@@ -325,9 +386,9 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
             do
             do
             {
             {
                 try input?.device.lockForConfiguration()
                 try input?.device.lockForConfiguration()
-                
+
                 var torch = false
                 var torch = false
-                
+
                 if input?.device.torchMode == AVCaptureDevice.TorchMode.on
                 if input?.device.torchMode == AVCaptureDevice.TorchMode.on
                 {
                 {
                     torch = false
                     torch = false
@@ -336,52 +397,52 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
                 {
                 {
                     torch = true
                     torch = true
                 }
                 }
-                
+
                 input?.device.torchMode = torch ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
                 input?.device.torchMode = torch ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
-                
+
                 input?.device.unlockForConfiguration()
                 input?.device.unlockForConfiguration()
             }
             }
             catch let error as NSError {
             catch let error as NSError {
                 print("device.lockForConfiguration(): \(error)")
                 print("device.lockForConfiguration(): \(error)")
-                
+
             }
             }
         }
         }
     }
     }
-    
+
     //MARK: ------获取系统默认支持的码的类型
     //MARK: ------获取系统默认支持的码的类型
-    static func defaultMetaDataObjectTypes() ->[AVMetadataObject.ObjectType]
+    static func defaultMetaDataObjectTypes() -> [AVMetadataObject.ObjectType]
     {
     {
         var types =
         var types =
             [AVMetadataObject.ObjectType.qr,
             [AVMetadataObject.ObjectType.qr,
-             AVMetadataObject.ObjectType.upce,
-             AVMetadataObject.ObjectType.code39,
-             AVMetadataObject.ObjectType.code39Mod43,
-             AVMetadataObject.ObjectType.ean13,
-             AVMetadataObject.ObjectType.ean8,
-             AVMetadataObject.ObjectType.code93,
-             AVMetadataObject.ObjectType.code128,
-             AVMetadataObject.ObjectType.pdf417,
-             AVMetadataObject.ObjectType.aztec
-        ]
+                AVMetadataObject.ObjectType.upce,
+                AVMetadataObject.ObjectType.code39,
+                AVMetadataObject.ObjectType.code39Mod43,
+                AVMetadataObject.ObjectType.ean13,
+                AVMetadataObject.ObjectType.ean8,
+                AVMetadataObject.ObjectType.code93,
+                AVMetadataObject.ObjectType.code128,
+                AVMetadataObject.ObjectType.pdf417,
+                AVMetadataObject.ObjectType.aztec
+            ]
         //if #available(iOS 8.0, *)
         //if #available(iOS 8.0, *)
-        
+
         types.append(AVMetadataObject.ObjectType.interleaved2of5)
         types.append(AVMetadataObject.ObjectType.interleaved2of5)
         types.append(AVMetadataObject.ObjectType.itf14)
         types.append(AVMetadataObject.ObjectType.itf14)
         types.append(AVMetadataObject.ObjectType.dataMatrix)
         types.append(AVMetadataObject.ObjectType.dataMatrix)
         return types as [AVMetadataObject.ObjectType]
         return types as [AVMetadataObject.ObjectType]
     }
     }
-    
-    
-    static func isSysIos8Later()->Bool
+
+
+    static func isSysIos8Later() -> Bool
     {
     {
         //        return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_8_0
         //        return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_8_0
-        
+
         if #available(iOS 8, *) {
         if #available(iOS 8, *) {
             return true;
             return true;
         }
         }
         return false
         return false
     }
     }
-    
+
     /**
     /**
      识别二维码码图像
      识别二维码码图像
      
      
@@ -389,74 +450,74 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
      
      
      - returns: 返回识别结果
      - returns: 返回识别结果
      */
      */
-    static public func recognizeQRImage(image:UIImage) ->[LBXScanResult]
+    static public func recognizeQRImage(image: UIImage) -> [LBXScanResult]
     {
     {
-        var returnResult:[LBXScanResult]=[]
-        
+        var returnResult: [LBXScanResult] = []
+
         if LBXScanWrapper.isSysIos8Later()
         if LBXScanWrapper.isSysIos8Later()
         {
         {
             //if #available(iOS 8.0, *)
             //if #available(iOS 8.0, *)
-            
-            let detector:CIDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])!
-            
+
+            let detector: CIDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])!
+
             let img = CIImage(cgImage: (image.cgImage)!)
             let img = CIImage(cgImage: (image.cgImage)!)
-            
-            let features:[CIFeature]? = detector.features(in: img, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
-            
-            if( features != nil && (features?.count)! > 0)
+
+            let features: [CIFeature]? = detector.features(in: img, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
+
+            if(features != nil && (features?.count)! > 0)
             {
             {
                 let feature = features![0]
                 let feature = features![0]
-                
+
                 if feature.isKind(of: CIQRCodeFeature.self)
                 if feature.isKind(of: CIQRCodeFeature.self)
                 {
                 {
-                    let featureTmp:CIQRCodeFeature = feature as! CIQRCodeFeature
-                    
+                    let featureTmp: CIQRCodeFeature = feature as! CIQRCodeFeature
+
                     let scanResult = featureTmp.messageString
                     let scanResult = featureTmp.messageString
-                    
-                    
-                    let result = LBXScanResult(str: scanResult, img: image, barCodeType: AVMetadataObject.ObjectType.qr.rawValue,corner: nil)
-                    
+
+
+                    let result = LBXScanResult(str: scanResult, img: image, barCodeType: AVMetadataObject.ObjectType.qr.rawValue, corner: nil)
+
                     returnResult.append(result)
                     returnResult.append(result)
                 }
                 }
             }
             }
-            
+
         }
         }
-        
+
         return returnResult
         return returnResult
     }
     }
-    
-    
+
+
     //MARK: -- - 生成二维码,背景色及二维码颜色设置
     //MARK: -- - 生成二维码,背景色及二维码颜色设置
-    static public func createCode( codeType:String, codeString:String, size:CGSize,qrColor:UIColor,bkColor:UIColor )->UIImage?
+    static public func createCode(codeType: String, codeString: String, size: CGSize, qrColor: UIColor, bkColor: UIColor) -> UIImage?
     {
     {
         //if #available(iOS 8.0, *)
         //if #available(iOS 8.0, *)
-        
+
         let stringData = codeString.data(using: String.Encoding.utf8)
         let stringData = codeString.data(using: String.Encoding.utf8)
-        
-        
+
+
         //系统自带能生成的码
         //系统自带能生成的码
         //        CIAztecCodeGenerator
         //        CIAztecCodeGenerator
         //        CICode128BarcodeGenerator
         //        CICode128BarcodeGenerator
         //        CIPDF417BarcodeGenerator
         //        CIPDF417BarcodeGenerator
         //        CIQRCodeGenerator
         //        CIQRCodeGenerator
         let qrFilter = CIFilter(name: codeType)
         let qrFilter = CIFilter(name: codeType)
-        
-        
+
+
         qrFilter?.setValue(stringData, forKey: "inputMessage")
         qrFilter?.setValue(stringData, forKey: "inputMessage")
-        
+
         qrFilter?.setValue("H", forKey: "inputCorrectionLevel")
         qrFilter?.setValue("H", forKey: "inputCorrectionLevel")
-        
-        
+
+
         //上色
         //上色
-        let colorFilter = CIFilter(name: "CIFalseColor", parameters: ["inputImage":qrFilter!.outputImage!,"inputColor0":CIColor(cgColor: qrColor.cgColor),"inputColor1":CIColor(cgColor: bkColor.cgColor)])
-        
-        
+        let colorFilter = CIFilter(name: "CIFalseColor", parameters: ["inputImage": qrFilter!.outputImage!, "inputColor0": CIColor(cgColor: qrColor.cgColor), "inputColor1": CIColor(cgColor: bkColor.cgColor)])
+
+
         let qrImage = colorFilter!.outputImage!;
         let qrImage = colorFilter!.outputImage!;
-        
+
         //绘制
         //绘制
         let cgImage = CIContext().createCGImage(qrImage, from: qrImage.extent)!
         let cgImage = CIContext().createCGImage(qrImage, from: qrImage.extent)!
-        
-        
+
+
         UIGraphicsBeginImageContext(size);
         UIGraphicsBeginImageContext(size);
         let context = UIGraphicsGetCurrentContext()!;
         let context = UIGraphicsGetCurrentContext()!;
         context.interpolationQuality = CGInterpolationQuality.none;
         context.interpolationQuality = CGInterpolationQuality.none;
@@ -464,16 +525,16 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         context.draw(cgImage, in: context.boundingBoxOfClipPath)
         context.draw(cgImage, in: context.boundingBoxOfClipPath)
         let codeImage = UIGraphicsGetImageFromCurrentImageContext();
         let codeImage = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
         UIGraphicsEndImageContext();
-        
+
         return codeImage
         return codeImage
-        
+
     }
     }
-    
-    static public func createCode128(  codeString:String, size:CGSize,qrColor:UIColor,bkColor:UIColor )->UIImage?
+
+    static public func createCode128(codeString: String, size: CGSize, qrColor: UIColor, bkColor: UIColor) -> UIImage?
     {
     {
         let stringData = codeString.data(using: String.Encoding.utf8)
         let stringData = codeString.data(using: String.Encoding.utf8)
-        
-        
+
+
         //系统自带能生成的码
         //系统自带能生成的码
         //        CIAztecCodeGenerator 二维码
         //        CIAztecCodeGenerator 二维码
         //        CICode128BarcodeGenerator 条形码
         //        CICode128BarcodeGenerator 条形码
@@ -482,36 +543,36 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         let qrFilter = CIFilter(name: "CICode128BarcodeGenerator")
         let qrFilter = CIFilter(name: "CICode128BarcodeGenerator")
         qrFilter?.setDefaults()
         qrFilter?.setDefaults()
         qrFilter?.setValue(stringData, forKey: "inputMessage")
         qrFilter?.setValue(stringData, forKey: "inputMessage")
-        
-        
-        
-        let outputImage:CIImage? = qrFilter?.outputImage
+
+
+
+        let outputImage: CIImage? = qrFilter?.outputImage
         let context = CIContext()
         let context = CIContext()
         let cgImage = context.createCGImage(outputImage!, from: outputImage!.extent)
         let cgImage = context.createCGImage(outputImage!, from: outputImage!.extent)
-        
+
         let image = UIImage(cgImage: cgImage!, scale: 1.0, orientation: UIImage.Orientation.up)
         let image = UIImage(cgImage: cgImage!, scale: 1.0, orientation: UIImage.Orientation.up)
-        
-        
+
+
         // Resize without interpolating
         // Resize without interpolating
-        let scaleRate:CGFloat = 20.0
+        let scaleRate: CGFloat = 20.0
         let resized = resizeImage(image: image, quality: CGInterpolationQuality.none, rate: scaleRate)
         let resized = resizeImage(image: image, quality: CGInterpolationQuality.none, rate: scaleRate)
-        
+
         return resized;
         return resized;
     }
     }
-    
-    
+
+
     //MARK:根据扫描结果,获取图像中得二维码区域图像(如果相机拍摄角度故意很倾斜,获取的图像效果很差)
     //MARK:根据扫描结果,获取图像中得二维码区域图像(如果相机拍摄角度故意很倾斜,获取的图像效果很差)
-    static func getConcreteCodeImage(srcCodeImage:UIImage,codeResult:LBXScanResult)->UIImage?
+    static func getConcreteCodeImage(srcCodeImage: UIImage, codeResult: LBXScanResult) -> UIImage?
     {
     {
-        let rect:CGRect = getConcreteCodeRectFromImage(srcCodeImage: srcCodeImage, codeResult: codeResult)
-        
+        let rect: CGRect = getConcreteCodeRectFromImage(srcCodeImage: srcCodeImage, codeResult: codeResult)
+
         if rect.isEmpty
         if rect.isEmpty
         {
         {
             return nil
             return nil
         }
         }
-        
+
         let img = imageByCroppingWithStyle(srcImg: srcCodeImage, rect: rect)
         let img = imageByCroppingWithStyle(srcImg: srcCodeImage, rect: rect)
-        
+
         if img != nil
         if img != nil
         {
         {
             let imgRotation = imageRotation(image: img!, orientation: UIImage.Orientation.right)
             let imgRotation = imageRotation(image: img!, orientation: UIImage.Orientation.right)
@@ -520,15 +581,15 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         return nil
         return nil
     }
     }
     //根据二维码的区域截取二维码区域图像
     //根据二维码的区域截取二维码区域图像
-    static public func getConcreteCodeImage(srcCodeImage:UIImage,rect:CGRect)->UIImage?
+    static public func getConcreteCodeImage(srcCodeImage: UIImage, rect: CGRect) -> UIImage?
     {
     {
         if rect.isEmpty
         if rect.isEmpty
         {
         {
             return nil
             return nil
         }
         }
-        
+
         let img = imageByCroppingWithStyle(srcImg: srcCodeImage, rect: rect)
         let img = imageByCroppingWithStyle(srcImg: srcCodeImage, rect: rect)
-        
+
         if img != nil
         if img != nil
         {
         {
             let imgRotation = imageRotation(image: img!, orientation: UIImage.Orientation.right)
             let imgRotation = imageRotation(image: img!, orientation: UIImage.Orientation.right)
@@ -536,51 +597,51 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         }
         }
         return nil
         return nil
     }
     }
-    
+
     //获取二维码的图像区域
     //获取二维码的图像区域
-    static public func getConcreteCodeRectFromImage(srcCodeImage:UIImage,codeResult:LBXScanResult)->CGRect
+    static public func getConcreteCodeRectFromImage(srcCodeImage: UIImage, codeResult: LBXScanResult) -> CGRect
     {
     {
-        if (codeResult.arrayCorner == nil || (codeResult.arrayCorner?.count)! < 4  )
+        if (codeResult.arrayCorner == nil || (codeResult.arrayCorner?.count)! < 4)
         {
         {
             return CGRect.zero
             return CGRect.zero
         }
         }
-        
-        let corner:[[String:Float]] = codeResult.arrayCorner  as! [[String:Float]]
-        
-        let dicTopLeft     = corner[0]
-        let dicTopRight    = corner[1]
+
+        let corner: [[String: Float]] = codeResult.arrayCorner as! [[String: Float]]
+
+        let dicTopLeft = corner[0]
+        let dicTopRight = corner[1]
         let dicBottomRight = corner[2]
         let dicBottomRight = corner[2]
-        let dicBottomLeft  = corner[3]
-        
-        let xLeftTopRatio:Float = dicTopLeft["X"]!
-        let yLeftTopRatio:Float  = dicTopLeft["Y"]!
-        
-        let xRightTopRatio:Float = dicTopRight["X"]!
-        let yRightTopRatio:Float = dicTopRight["Y"]!
-        
-        let xBottomRightRatio:Float = dicBottomRight["X"]!
-        let yBottomRightRatio:Float = dicBottomRight["Y"]!
-        
-        let xLeftBottomRatio:Float = dicBottomLeft["X"]!
-        let yLeftBottomRatio:Float = dicBottomLeft["Y"]!
-        
+        let dicBottomLeft = corner[3]
+
+        let xLeftTopRatio: Float = dicTopLeft["X"]!
+        let yLeftTopRatio: Float = dicTopLeft["Y"]!
+
+        let xRightTopRatio: Float = dicTopRight["X"]!
+        let yRightTopRatio: Float = dicTopRight["Y"]!
+
+        let xBottomRightRatio: Float = dicBottomRight["X"]!
+        let yBottomRightRatio: Float = dicBottomRight["Y"]!
+
+        let xLeftBottomRatio: Float = dicBottomLeft["X"]!
+        let yLeftBottomRatio: Float = dicBottomLeft["Y"]!
+
         //由于截图只能矩形,所以截图不规则四边形的最大外围
         //由于截图只能矩形,所以截图不规则四边形的最大外围
-        let xMinLeft = CGFloat( min(xLeftTopRatio, xLeftBottomRatio) )
-        let xMaxRight = CGFloat( max(xRightTopRatio, xBottomRightRatio) )
-        
-        let yMinTop = CGFloat( min(yLeftTopRatio, yRightTopRatio) )
-        let yMaxBottom = CGFloat ( max(yLeftBottomRatio, yBottomRightRatio) )
-        
+        let xMinLeft = CGFloat(min(xLeftTopRatio, xLeftBottomRatio))
+        let xMaxRight = CGFloat(max(xRightTopRatio, xBottomRightRatio))
+
+        let yMinTop = CGFloat(min(yLeftTopRatio, yRightTopRatio))
+        let yMaxBottom = CGFloat (max(yLeftBottomRatio, yBottomRightRatio))
+
         let imgW = srcCodeImage.size.width
         let imgW = srcCodeImage.size.width
         let imgH = srcCodeImage.size.height
         let imgH = srcCodeImage.size.height
-        
+
         //宽高反过来计算
         //宽高反过来计算
-        let rect = CGRect(x: xMinLeft * imgH, y: yMinTop*imgW, width: (xMaxRight-xMinLeft)*imgH, height: (yMaxBottom-yMinTop)*imgW)
+        let rect = CGRect(x: xMinLeft * imgH, y: yMinTop * imgW, width: (xMaxRight - xMinLeft) * imgH, height: (yMaxBottom - yMinTop) * imgW)
         return rect
         return rect
     }
     }
-    
+
     //MARK: ----图像处理
     //MARK: ----图像处理
-    
+
     /**
     /**
 
 
     @brief  图像中间加logo图片
     @brief  图像中间加logo图片
@@ -589,72 +650,72 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
     @param logoSize  logo图像尺寸
     @param logoSize  logo图像尺寸
     @return 加Logo的图像
     @return 加Logo的图像
     */
     */
-    static public func addImageLogo(srcImg:UIImage,logoImg:UIImage,logoSize:CGSize )->UIImage
+    static public func addImageLogo(srcImg: UIImage, logoImg: UIImage, logoSize: CGSize) -> UIImage
 
 
     {
     {
         UIGraphicsBeginImageContext(srcImg.size);
         UIGraphicsBeginImageContext(srcImg.size);
         srcImg.draw(in: CGRect(x: 0, y: 0, width: srcImg.size.width, height: srcImg.size.height))
         srcImg.draw(in: CGRect(x: 0, y: 0, width: srcImg.size.width, height: srcImg.size.height))
-        let rect = CGRect(x: srcImg.size.width/2 - logoSize.width/2, y: srcImg.size.height/2-logoSize.height/2, width:logoSize.width, height: logoSize.height);
+        let rect = CGRect(x: srcImg.size.width / 2 - logoSize.width / 2, y: srcImg.size.height / 2 - logoSize.height / 2, width: logoSize.width, height: logoSize.height);
         logoImg.draw(in: rect)
         logoImg.draw(in: rect)
         let resultingImage = UIGraphicsGetImageFromCurrentImageContext();
         let resultingImage = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
         UIGraphicsEndImageContext();
         return resultingImage!;
         return resultingImage!;
     }
     }
-    
+
     //图像缩放
     //图像缩放
-    static func resizeImage(image:UIImage,quality:CGInterpolationQuality,rate:CGFloat)->UIImage?
+    static func resizeImage(image: UIImage, quality: CGInterpolationQuality, rate: CGFloat) -> UIImage?
     {
     {
-        var resized:UIImage?;
-        let width    = image.size.width * rate;
-        let height   = image.size.height * rate;
-        
+        var resized: UIImage?;
+        let width = image.size.width * rate;
+        let height = image.size.height * rate;
+
         UIGraphicsBeginImageContext(CGSize(width: width, height: height));
         UIGraphicsBeginImageContext(CGSize(width: width, height: height));
         let context = UIGraphicsGetCurrentContext();
         let context = UIGraphicsGetCurrentContext();
         context!.interpolationQuality = quality;
         context!.interpolationQuality = quality;
         image.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
         image.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
-        
+
         resized = UIGraphicsGetImageFromCurrentImageContext();
         resized = UIGraphicsGetImageFromCurrentImageContext();
         UIGraphicsEndImageContext();
         UIGraphicsEndImageContext();
-        
+
         return resized;
         return resized;
     }
     }
-    
-    
+
+
     //图像裁剪
     //图像裁剪
-    static func imageByCroppingWithStyle(srcImg:UIImage,rect:CGRect)->UIImage?
+    static func imageByCroppingWithStyle(srcImg: UIImage, rect: CGRect) -> UIImage?
     {
     {
         let imageRef = srcImg.cgImage
         let imageRef = srcImg.cgImage
         let imagePartRef = imageRef!.cropping(to: rect)
         let imagePartRef = imageRef!.cropping(to: rect)
         let cropImage = UIImage(cgImage: imagePartRef!)
         let cropImage = UIImage(cgImage: imagePartRef!)
-        
+
         return cropImage
         return cropImage
     }
     }
     //图像旋转
     //图像旋转
-    static func imageRotation(image:UIImage,orientation:UIImage.Orientation)->UIImage
+    static func imageRotation(image: UIImage, orientation: UIImage.Orientation) -> UIImage
     {
     {
-        var rotate:Double = 0.0;
-        var rect:CGRect;
-        var translateX:CGFloat = 0.0;
-        var translateY:CGFloat = 0.0;
-        var scaleX:CGFloat = 1.0;
-        var scaleY:CGFloat = 1.0;
-        
+        var rotate: Double = 0.0;
+        var rect: CGRect;
+        var translateX: CGFloat = 0.0;
+        var translateY: CGFloat = 0.0;
+        var scaleX: CGFloat = 1.0;
+        var scaleY: CGFloat = 1.0;
+
         switch (orientation) {
         switch (orientation) {
         case UIImage.Orientation.left:
         case UIImage.Orientation.left:
-            rotate = .pi/2;
+            rotate = .pi / 2;
             rect = CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width);
             rect = CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width);
             translateX = 0;
             translateX = 0;
             translateY = -rect.size.width;
             translateY = -rect.size.width;
-            scaleY = rect.size.width/rect.size.height;
-            scaleX = rect.size.height/rect.size.width;
+            scaleY = rect.size.width / rect.size.height;
+            scaleX = rect.size.height / rect.size.width;
             break;
             break;
         case UIImage.Orientation.right:
         case UIImage.Orientation.right:
-            rotate = 3 * .pi/2;
+            rotate = 3 * .pi / 2;
             rect = CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width);
             rect = CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width);
             translateX = -rect.size.height;
             translateX = -rect.size.height;
             translateY = 0;
             translateY = 0;
-            scaleY = rect.size.width/rect.size.height;
-            scaleX = rect.size.height/rect.size.width;
+            scaleY = rect.size.width / rect.size.height;
+            scaleX = rect.size.height / rect.size.width;
             break;
             break;
         case UIImage.Orientation.down:
         case UIImage.Orientation.down:
             rotate = .pi;
             rotate = .pi;
@@ -669,7 +730,7 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
             translateY = 0;
             translateY = 0;
             break;
             break;
         }
         }
-        
+
         UIGraphicsBeginImageContext(rect.size);
         UIGraphicsBeginImageContext(rect.size);
         let context = UIGraphicsGetCurrentContext()!;
         let context = UIGraphicsGetCurrentContext()!;
         //做CTM变换
         //做CTM变换
@@ -677,15 +738,15 @@ open class LBXScanWrapper: NSObject,AVCaptureMetadataOutputObjectsDelegate {
         context.scaleBy(x: 1.0, y: -1.0);
         context.scaleBy(x: 1.0, y: -1.0);
         context.rotate(by: CGFloat(rotate));
         context.rotate(by: CGFloat(rotate));
         context.translateBy(x: translateX, y: translateY);
         context.translateBy(x: translateX, y: translateY);
-        
+
         context.scaleBy(x: scaleX, y: scaleY);
         context.scaleBy(x: scaleX, y: scaleY);
         //绘制图片
         //绘制图片
         context.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
         context.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
         let newPic = UIGraphicsGetImageFromCurrentImageContext();
         let newPic = UIGraphicsGetImageFromCurrentImageContext();
-        
+
         return newPic!;
         return newPic!;
     }
     }
-    
+
     deinit
     deinit
     {
     {
         //        print("LBXScanWrapper deinit")
         //        print("LBXScanWrapper deinit")

+ 95 - 0
o2ios/O2Platform/UI/O2CanCopyUILabel.swift

@@ -0,0 +1,95 @@
+//
+//  O2CanCopyUILabel.swift
+//  O2Platform
+//
+//  Created by FancyLou on 2020/8/26.
+//  Copyright © 2020 zoneland. All rights reserved.
+//
+
+import UIKit
+
+// MARK: - 能够复制的UILabel
+class O2CanCopyUILabel: UILabel {
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setEvent()
+    }
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+    }
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        addLongPressGesture()
+    }
+    
+    //必须实现的两个方法
+    override var canBecomeFirstResponder: Bool  {
+        return true
+    }
+    
+    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
+        if action == #selector(copyText) {
+            return true
+        }
+        return false
+    }
+    
+    private func setEvent() {
+        addLongPressGesture()
+        NotificationCenter.default.addObserver(forName: UIMenuController.willHideMenuNotification, object: nil, queue: nil) { (note) in
+            self.backgroundColor = UIColor.white
+        }
+    }
+    
+    
+    private func addLongPressGesture() {
+        self.isUserInteractionEnabled = true
+        let longTap = UILongPressGestureRecognizer.init(target: self, action: #selector(longTapRecognizer))
+        // 长按手势最小触发时间
+        longTap.minimumPressDuration = 1.0
+        // 长按手势需要的同时敲击触碰数(手指数)
+        longTap.numberOfTouchesRequired = 1
+        // 长按有效移动范围(从点击开始,长按移动的允许范围 单位 px
+//        longTap.allowableMovement = 15
+        self.addGestureRecognizer(longTap)
+    }
+    
+    private func setMenuItems(){
+        self.becomeFirstResponder()
+        // 如果 Menu 已经被创建那就不再重复创建 menu
+        if (UIMenuController.shared.isMenuVisible){
+            return
+        }
+        let item1 = UIMenuItem.init(title: "复制", action: #selector(copyText))
+        // 单例的形式获取menu
+        let menu = UIMenuController.shared
+        // 设置箭头方向
+        menu.arrowDirection = .default
+        // 设置 Menu 所显示的 items
+        menu.menuItems = [item1]
+        // 设置添加上 menu 的目标控件的 rect 和目标控件
+        menu.setTargetRect(self.frame, in: self.superview!)
+        // 令 Menu 可见
+        menu.setMenuVisible(true, animated: true)
+    }
+
+    
+    @objc private func longTapRecognizer(recognizer: UIGestureRecognizer) {
+        if recognizer.state == .ended{
+            self.backgroundColor = UIColor.white
+            return
+        }else if recognizer.state == .began{
+            self.backgroundColor = UIColor.lightGray
+            setMenuItems()
+        }
+    }
+    
+    @objc private func copyText() {
+        let pboard = UIPasteboard.general
+        pboard.string = self.text
+    }
+    
+}