//
|
// LoginVC.swift
|
// XQMuse
|
//
|
// Created by 无故事王国 on 2024/8/13.
|
//
|
|
import UIKit
|
import JQTools
|
import RxRelay
|
import QMUIKit
|
import AuthenticationServices
|
|
|
let LoginSuccess_Noti = Notification.Name.init("LoginSuccess_Noti")
|
let LoginQuit_Noti = Notification.Name.init("LoginQuit_Noti")
|
|
class LoginViewModel{
|
var loginType = BehaviorRelay<LoginType>(value:.pwd)
|
var loginPhone = BehaviorRelay<String>(value:"")
|
var loginContent = BehaviorRelay<String>(value:"")
|
|
|
func checkSafe()->Bool{
|
if loginPhone.value.isEmpty{
|
alert(msg: "请输入您的手机号");return false
|
}
|
|
if loginContent.value.isEmpty{
|
switch loginType.value {
|
case .code:alert(msg: "请输入您的验证码")
|
case .pwd:alert(msg: "请输入您的密码")
|
}
|
return false
|
}
|
|
if !loginPhone.value.jq_isPhone{
|
alert(msg: "请输入正确的手机号");return false
|
}
|
|
if loginContent.value.count != 6 && loginType.value == .code{
|
alertError(msg: "请输入6位验证码");return false
|
}
|
|
return true
|
}
|
}
|
|
let LoginDismiss_Noti = Notification.Name.init("LoginDismiss_Noti")
|
|
class LoginVC: BaseVC {
|
|
@IBOutlet weak var btn_loginByPwd: UIButton!
|
@IBOutlet weak var btn_loginByCode: UIButton!
|
@IBOutlet weak var tf_phone: QMUITextField!
|
@IBOutlet weak var tf_content: QMUITextField!
|
@IBOutlet weak var btn_eye: UIButton!
|
@IBOutlet weak var view_content: UIView!
|
@IBOutlet weak var btn_register: UIButton!
|
@IBOutlet weak var btn_login: UIButton!
|
@IBOutlet weak var btn_sendCode: UIButton!
|
@IBOutlet weak var btn_isRead: UIButton!
|
@IBOutlet weak var btn_wechat: UIButton!
|
@IBOutlet weak var image_security: UIImageView!
|
|
|
|
private var viewModel = LoginViewModel()
|
|
private let unlineImageView = UIImageView(image: UIImage(named: "icon_unline"))
|
|
override func viewDidLoad() {
|
super.viewDidLoad()
|
}
|
|
override func setRx() {
|
tf_phone.rx.text.orEmpty.bind(to: viewModel.loginPhone).disposed(by: disposeBag)
|
tf_content.rx.text.orEmpty.bind(to: viewModel.loginContent).disposed(by: disposeBag)
|
|
viewModel.loginType.subscribe(onNext: { type in
|
UIView.animate(withDuration: 0.3) {[unowned self] in
|
self.tf_content.text = ""
|
self.tf_content.resignFirstResponder()
|
self.btn_eye.isHidden = type == .code
|
self.btn_sendCode.isHidden = type == .pwd
|
switch type {
|
case .code:
|
self.tf_content.placeholder = "请输入验证码"
|
self.tf_content.keyboardType = .numberPad
|
self.tf_content.maximumTextLength = 6
|
self.tf_content.isSecureTextEntry = false
|
self.btn_loginByPwd.transform = .init(scaleX: 0.8, y: 0.8)
|
self.btn_loginByPwd.alpha = 0.5
|
self.btn_loginByCode.transform = .init(scaleX: 1, y: 1)
|
self.btn_loginByCode.alpha = 1
|
self.unlineImageView.snp.remakeConstraints { make in
|
make.top.equalTo(self.btn_loginByPwd.snp.bottom).offset(6)
|
make.centerX.equalTo(self.btn_loginByCode)
|
}
|
case .pwd:
|
self.tf_content.placeholder = "请输入密码"
|
self.tf_content.maximumTextLength = 30
|
self.tf_content.isSecureTextEntry = true
|
self.tf_content.keyboardType = .asciiCapable
|
self.btn_loginByPwd.transform = .init(scaleX: 1, y: 1)
|
self.btn_loginByPwd.alpha = 1
|
self.btn_loginByCode.transform = .init(scaleX: 0.8, y: 0.8)
|
self.btn_loginByCode.alpha = 0.5
|
self.unlineImageView.snp.remakeConstraints { make in
|
make.top.equalTo(self.btn_loginByPwd.snp.bottom).offset(6)
|
make.centerX.equalTo(self.btn_loginByPwd)
|
}
|
}
|
|
self.view.layoutIfNeeded()
|
}
|
}).disposed(by: disposeBag)
|
|
NotificationCenter.default.rx.notification(LoginDismiss_Noti).take(until: self.rx.deallocated).subscribe(onNext: { _ in
|
self.backAction()
|
}).disposed(by: disposeBag)
|
}
|
|
override func setUI() {
|
|
btn_wechat.isHidden = !WXApi.isWXAppInstalled()
|
|
navigationItem.leftBarButtonItem = UIBarButtonItem.jq_creat(image: nav_back_img, target: self, alignment:.left, action: #selector(backAction)).item
|
|
btn_eye.isSelected = true
|
view.addSubview(unlineImageView)
|
unlineImageView.snp.makeConstraints { make in
|
make.top.equalTo(self.btn_loginByPwd.snp.bottom).offset(6)
|
make.centerX.equalTo(self.btn_loginByPwd)
|
make.width.equalTo(21)
|
make.height.equalTo(8)
|
}
|
|
let btn_attribute = AttributedStringbuilder.build().add(string: "注册账号", withFont: .systemFont(ofSize: 12, weight: .medium), withColor: UIColor(hexStr: "#003809")).underLine(color: UIColor(hexStr: "#003809")).mutableAttributedString
|
|
btn_register.setAttributedTitle(btn_attribute, for: .normal)
|
}
|
|
@objc fileprivate func backAction() {
|
self.dismiss(animated: true)
|
}
|
|
|
@IBAction func loginTypeAction(_ sender: UIButton) {
|
sender.tag == 10 ? viewModel.loginType.accept(.pwd):viewModel.loginType.accept(.code)
|
|
switch viewModel.loginType.value{
|
case .code:
|
tf_content.isSecureTextEntry = false
|
image_security.image = UIImage(named: "icon_code")
|
#if DEBUG
|
tf_content.text = "220125"
|
#endif
|
case .pwd:
|
tf_content.isSecureTextEntry = btn_eye.isSelected
|
image_security.image = UIImage(named: "icon_pwd")
|
}
|
}
|
|
@IBAction func eyeAction(_ sender: UIButton) {
|
sender.isSelected = !sender.isSelected
|
tf_content.isSecureTextEntry = sender.isSelected
|
}
|
|
@IBAction func isReadAction(_ sender: UIButton) {
|
sender.isSelected = !sender.isSelected
|
}
|
|
|
@IBAction func sendCodeAction(_ sender: UIButton) {
|
|
guard !viewModel.loginPhone.value.isEmpty else {alert(msg: "请输入手机号");return}
|
guard viewModel.loginPhone.value.jq_isPhone else {alert(msg: "请输入正确手机号");return}
|
|
Services.sendCode(phone:tf_phone.text!,type: .codeLogin).subscribe(onNext: {data in
|
if data.code == 200{
|
sender.jq_openCountDown(60, defultTitle: "获取验证码") {
|
sender.titleLabel?.font = UIFont.systemFont(ofSize: 12)
|
sender.setTitleColor(.black.withAlphaComponent(0.3), for: .normal)
|
} completeClouse: {
|
sender.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
|
sender.setTitleColor(UIColor(hexStr: "#96AD81"), for: .normal)
|
}
|
}
|
}).disposed(by: disposeBag)
|
}
|
|
@IBAction func loginAction(_ sender: UIButton) {
|
|
guard viewModel.checkSafe() else {return}
|
guard btn_isRead.isSelected else {
|
alert(msg: "请阅读并同意《用户注册协议》和《用户隐私协议》");return
|
}
|
|
Services.loginBy(phone: viewModel.loginPhone.value, content: viewModel.loginContent.value, type: viewModel.loginType.value, device: UserViewModel.DeviceUUID).subscribe(onNext: { data in
|
if let model = data.data{
|
self.dismiss(animated: true)
|
|
UserViewModel.saveLoginInfo(model)
|
|
Services.getUserInfo().subscribe(onNext: {data in
|
if let model = data.data{
|
sceneDelegate?.loginSuccess()
|
UserViewModel.saveAvatarInfo(model)
|
}
|
}).disposed(by: self.disposeBag)
|
}
|
}).disposed(by: disposeBag)
|
}
|
|
@IBAction func userRegisterTreatyAction(_ sender: UIButton) {
|
|
// let vc = WebVC(type: .user)
|
// vc.title = "用户注册协议"
|
// push(vc: vc)
|
|
let vc = LoginTreatyVC()
|
vc.topIndex = 0
|
vc.clickHandle {[unowned self] state in
|
self.btn_isRead.isSelected = state
|
}
|
vc.modalPresentationStyle = .custom
|
present(vc, animated: true)
|
}
|
|
@IBAction func userPrivateTreatyAction(_ sender: UIButton) {
|
let vc = LoginTreatyVC()
|
vc.topIndex = 1
|
vc.clickHandle {[unowned self] state in
|
self.btn_isRead.isSelected = state
|
}
|
vc.modalPresentationStyle = .custom
|
present(vc, animated: true)
|
// let vc = WebVC(type: .privacy)
|
// vc.title = "用户隐私协议"
|
// push(vc: vc)
|
}
|
|
@IBAction func registerAction(_ sender: UIButton) {
|
let vc = RegisterVC()
|
push(vc: vc)
|
}
|
|
@IBAction func loginByWechatAction(_ sender: UIButton) {
|
guard btn_isRead.isSelected else {
|
alert(msg: "请阅读并同意《用户注册协议》和《用户隐私协议》");return
|
}
|
WeChatTools.sendAuthRequest()
|
}
|
|
@IBAction func loginByAppleAction(_ sender: UIButton) {
|
guard btn_isRead.isSelected else {
|
alert(msg: "请阅读并同意《用户注册协议》和《用户隐私协议》");return
|
}
|
|
let provider = ASAuthorizationAppleIDProvider() //主要作用是用创建相应的请求,查询用户授权状态
|
let request = provider.createRequest() //授权请求,可以设置具体的请求信息
|
request.requestedScopes = [.fullName,.email]
|
let vc = ASAuthorizationController(authorizationRequests: [request]) //发送请求控制器,可以设置相应的协议
|
vc.delegate = self
|
vc.presentationContextProvider = self
|
vc.performRequests()
|
}
|
|
@IBAction func forgotPwdAction(_ sender: UIButton) {
|
let vc = ForgotPasswordVC()
|
push(vc: vc)
|
}
|
|
override func viewDidLayoutSubviews() {
|
super.viewDidLayoutSubviews()
|
view_content.jq_gradientColor(colorArr: [UIColor(hexStr: "#F3FFF8").cgColor,UIColor.white.cgColor], cornerRadius: 30, startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: 1), bounds: nil, locations: [0.01,0.5])
|
|
|
btn_login.jq_gradientNibColor(colorArr: [UIColor(hexStr: "#8EA47A").cgColor,UIColor(hexStr: "#AFCA98").cgColor], cornerRadius: 20)
|
}
|
}
|
|
extension LoginVC:ASAuthorizationControllerPresentationContextProviding{
|
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
|
return self.view.window!
|
}
|
}
|
extension LoginVC:ASAuthorizationControllerDelegate{
|
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
|
if let credential = authorization.credential as? ASAuthorizationAppleIDCredential{
|
|
Services.loginByApple(appleId: credential.user,device: UserViewModel.DeviceUUID).subscribe(onNext: {data in
|
if var m = data.data{
|
if m.bindStatus == 2{
|
sceneDelegate?.loginSuccess()
|
m.loginByAppleToken = String(data: credential.identityToken!, encoding: .utf8)
|
m.appleId = credential.user
|
|
self.dismiss(animated: true)
|
|
UserViewModel.saveLoginInfo(m)
|
|
Services.getUserInfo().subscribe(onNext: {data in
|
if let model = data.data{
|
sceneDelegate?.loginSuccess()
|
UserViewModel.saveAvatarInfo(model)
|
}
|
}).disposed(by: self.disposeBag)
|
}else{
|
let vc = UpdatePhoneVC(credential: credential,firstAccessToken: m.accessToken)
|
self.jq_push(vc: vc)
|
}
|
}
|
}).disposed(by: disposeBag)
|
}
|
}
|
|
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
|
switch (error as! ASAuthorizationError).code {
|
case .canceled:print("用户取消")
|
case .failed:print("请求失败")
|
case .invalidResponse:print("无效响应")
|
case .notHandled:print("未处理")
|
case .unknown:print("未知错误")
|
case .notInteractive:print("未交互")
|
case .matchedExcludedCredential:print("排除的凭证匹配")
|
@unknown default:break
|
}
|
}
|
}
|