// // LoginViewController.swift // QuickLocation // // Created based on Lanhu design: 登录-一键登录 // import UIKit import SnapKit import RxSwift import RxCocoa import AuthenticationServices #if !targetEnvironment(simulator) import GeYanSdk #endif class LoginViewController: BaseViewController { override var isNavigationBarHidden: Bool { true } override var preferredStatusBarStyle: UIStatusBarStyle { .default } // MARK: - Properties fileprivate var rootView: LoginView! private let viewModel = LoginViewModel() private var isAgreed = false private var countDownService = CountDownService(countDownTime: 60) // MARK: - Lifecycle override func loadView() { rootView = LoginView(frame: UIScreen.main.bounds) view = rootView } override func viewDidLoad() { super.viewDidLoad() rootView.agreementTV.delegate = self bindViewModel() reactiveAction() } private func reactiveAction() { rootView.smsCodeBtn.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in guard let self = self else { return } self.requestSmsCodeAPI() }.disposed(by: rootView.disposeBag) } // MARK: - Bindings private func bindViewModel() { rootView.checkBox.rx.tap .subscribe(onNext: { [weak self] in self?.isAgreed.toggle() self?.rootView.checkBox.isSelected = self?.isAgreed ?? false }) .disposed(by: disposeBag) rootView.loginButton.rx.tap .subscribe(onNext: { [weak self] in guard let self = self else { return } if !self.isAgreed { DLToast.showError(text: "请先同意用户协议") return } guard let phone = self.rootView.phoneInputTF.text, !phone.isEmpty else { DLToast.showError(text: "请输入手机号码") return } guard let smsCode = self.rootView.smsCodeTF.text, !smsCode.isEmpty else { DLToast.showError(text: "请输入验证码") return } let requestData = ["timestamp": self.viewModel.timestamp, "phone": phone, "code": smsCode] self.viewModel.loginAction(type: "phone", data: requestData) }) .disposed(by: disposeBag) rootView.guestLoginButton.rx.tap .subscribe(onNext: { _ in AppDelegate.shared.showMainViewController() }) .disposed(by: disposeBag) rootView.wechatLoginBtn.rx.tap .subscribe(onNext: { [weak self] in guard self?.isAgreed == true else { DLToast.showError(text: "请先同意用户协议") return } self?.viewModel.performWechatLogin() }) .disposed(by: disposeBag) rootView.appleLoginBtn.rx.tap .subscribe(onNext: { [weak self] in guard self?.isAgreed == true else { DLToast.showError(text: "请先同意用户协议") return } self?.viewModel.performAppleLogin() }) .disposed(by: disposeBag) viewModel.onAppleLoginRequest = { [weak self] controller in guard let self = self else { return } controller.delegate = self controller.presentationContextProvider = self controller.performRequests() } rootView.phoneLoginBtn.rx.tap .subscribe(onNext: { [weak self] in #if !targetEnvironment(simulator) if GeYanSdk.getCurrentCarrierCount() == 0 { DLToast.show(text: "请插入SIM卡后重试") return } if GeYanSdk.isPreGettedTokenValidate() { //预登录有效,启动登录授权页 let oneTapView = OneTapLoginView(frame: UIScreen.main.bounds) self?.viewModel.performOneTapLogin(from: self!, contentView: oneTapView) return } // 预登录 GeYanSdk.preGetToken { preDic in guard GeYanSdk.isPreGettedTokenValidate() else { var message = "" if let dict = preDic as? [String: Any] { message = dict["msg"] as? String ?? "获取手机号失败,请使用验证码登录" } DLToast.show(text: message) return } let oneTapView = OneTapLoginView(frame: UIScreen.main.bounds) self?.viewModel.performOneTapLogin(from: self!, contentView: oneTapView) } #endif }) .disposed(by: disposeBag) // viewModel.loginSuccess // .subscribe(onNext: { [weak self] in // // }) // .disposed(by: disposeBag) } // MARK: - API 验证码 func requestSmsCodeAPI() { DLToast.showLoading() SystemService.sendSmsCode(phone: rootView.phoneInputTF.text ?? "").subscribe(onNext: { [weak self] response in DLToast.showSuccess(text: "发送成功") guard let self = self, let responseData = response.result as? [String : Any] else { return } self.startCountDown(self.rootView.smsCodeBtn, self.countDownService) if let timestamp = responseData["timestamp"] as? String { self.viewModel.timestamp = timestamp } }, onError: { _ in }).disposed(by: disposeBag) } } extension LoginViewController: UITextViewDelegate { func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { // if URL.absoluteString == "Carrier", let model = GyContentModel.current(), let link = model.link { // AppRouter.push(Route.web, userInfo: ["url": link]) // } if URL.absoluteString == "UserAgreement" { AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.userAgreementUrl]) } if URL.absoluteString == "PrivacyPolicy" { AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.privacyPolicyUrl]) } return true } func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { false } private func openURL(_ url: String) {} } // MARK: - Apple Sign In extension LoginViewController: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding { func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { view.window ?? UIWindow() } func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return } let userId = credential.user let userName: String = { if let name = credential.fullName { let parts = [name.givenName, name.familyName].compactMap { $0 } if !parts.isEmpty { return parts.joined(separator: " ") } } return "" }() let identityToken = credential.identityToken.flatMap { String(data: $0, encoding: .utf8) } ?? "" let authCode = credential.authorizationCode.flatMap { String(data: $0, encoding: .utf8) } ?? "" viewModel.loginAction(type: "apple", data: [ "user_id": userId, "user_name": userName, "identify_code": authCode, "identify_token": identityToken ]) } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { NotificationCenter.default.post(name: .resumePopupQueue, object: nil) DLToast.showError(text: "Apple 登录失败") } }