// // ScanVC.swift // QuickLocation // import UIKit import AVFoundation import RxSwift class ScanVC: BaseViewController { override var isNavigationBarHidden: Bool { true } override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent } private var rootView: CameraCaptureView! private let scanDoneAction: ((String) -> Void)? private var isHandling = false override func loadView() { rootView = CameraCaptureView(mode: .scan) view = rootView } override func viewDidLoad() { super.viewDidLoad() rootView.onClose = { [weak self] in self?.closeCapture() } rootView.onScan = { [weak self] text in self?.handleScanResult(text: text) } rootView.onOpenAlbum = { [weak self] in self?.openAlbum() } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) isHandling = false rootView.startSession() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) rootView.stopSession() } init(scanDoneAction: ((String) -> Void)? = nil) { self.scanDoneAction = scanDoneAction super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func closeCapture() { if presentingViewController != nil { dismiss(animated: true) } else { navigationController?.popViewController(animated: true) } } private func handleScanResult(text: String) { guard !isHandling else { return } isHandling = true rootView.stopSession() if let scanDoneAction { scanDoneAction(text) closeCapture() return } requestJoinGroup(code: text) } private func requestJoinGroup(code: String) { DLToast.showLoading() GroupService.operate(opType: "join", requestData: ["share_code": code]).subscribe(onNext: { response in DLToast.showSuccess(text: response.message ?? "申请成功") { AppRouter.shared.popOrDismiss() } }, onError: { [weak self] _ in DLToast.showError(text: "无法识别该二维码") DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { self?.isHandling = false self?.rootView.startSession() } }).disposed(by: disposeBag) } private func openAlbum() { guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return } let picker = UIImagePickerController() picker.sourceType = .photoLibrary picker.delegate = self present(picker, animated: true) } private func decodeQR(from image: UIImage) { guard let ciImage = CIImage(image: image) else { DLToast.show(text: "无法识别二维码") isHandling = false return } let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) let features = detector?.features(in: ciImage) ?? [] if let qr = features.first as? CIQRCodeFeature, let text = qr.messageString, !text.isEmpty { handleScanResult(text: text) } else { DLToast.show(text: "未识别到二维码") isHandling = false } } } extension ScanVC: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { picker.dismiss(animated: true) if let image = info[.originalImage] as? UIImage { decodeQR(from: image) } } }