// // LoginView.swift // QuickLocation // // Created by 八条 on 2026/5/26. // import UIKit import RxSwift import RxCocoa #if !targetEnvironment(simulator) import GeYanSdk #endif class LoginView: UIView { var disposeBag = DisposeBag() var oneTapLogin = true private func setupRx() { backBtn.rx.tap.subscribe(onNext: { _ in AppRouter.shared.popOrDismiss() }).disposed(by: disposeBag) phoneInputTF.rx.text .map { text -> String? in guard let text = text else { return nil } return String(text.prefix(11)) }.bind(to: phoneInputTF.rx.text) .disposed(by: disposeBag) phoneInputTF.rx.text.orEmpty.map { phone -> Bool in if phone.count == 11 { return true } else { return false } } .bind(to: smsCodeBtn.rx.isEnabled) .disposed(by: disposeBag) } func setupAgreementTextWithCarrier(carrier: String) { let text = carrier.isEmpty ? "登录即同意《隐私政策》和《用户协议》" : "登录即同意\(carrier)、《隐私政策》和《用户协议》" agreementLabel.text = text // 创建段落样式 let paragraphStyle = NSMutableParagraphStyle() // 设置行距(lineSpacing 是行间距,lineHeightMultiple 是行高倍数) paragraphStyle.lineSpacing = 4.0 // 行间距 let attributedString = NSMutableAttributedString(string: text) attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#A4A7AE"), .paragraphStyle: paragraphStyle], range: NSRange(location: 0, length: text.length)) attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#16B3FF"), .link: "Carrier"], range: (text as NSString).range(of: carrier)) attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#16B3FF"), .link: "UserAgreement"], range: (text as NSString).range(of: "《用户协议》")) attributedString.addAttributes([.foregroundColor: UIColor(hexStr: "#16B3FF"), .link: "PrivacyPolicy"], range: (text as NSString).range(of: "《隐私政策》")) agreementTV.attributedText = attributedString } private func setupUI() { addSubview(bgMaskImage) addSubview(backBtn) addSubview(guestLoginButton) addSubview(welcomeLabel) addSubview(phoneNumberLabel) addSubview(carrierLabel) addSubview(otherPhoneView) otherPhoneView.addSubview(phoneInputView) otherPhoneView.addSubview(smsCodeInputView) addSubview(loginButton) addSubview(appleLoginBtn) addSubview(wechatLoginBtn) addSubview(phoneLoginBtn) addSubview(agreementView) agreementView.addSubview(checkBox) agreementView.addSubview(agreementTV) agreementView.addSubview(agreementLabel) bgMaskImage.layoutChain.edges() backBtn.layoutChain .top(54) .left(15) .width(24) .height(24) guestLoginButton.layoutChain .centerY(backBtn) .right(15) .width(85) .height(29) welcomeLabel.layoutChain .top(202 - kNaviHeight) .centerX() .edgesHorzontal() phoneNumberLabel.layoutChain .topToBottomOfView(welcomeLabel, offset: 78) .centerX() carrierLabel.layoutChain .topToBottomOfView(phoneNumberLabel, offset: 4) .centerX() otherPhoneView.layoutChain .topToBottomOfView(welcomeLabel, offset: 43) .centerX() phoneInputView.layoutChain .edges(excludingEdge: .bottom) .width(259) .height(50) phoneLineView.layoutChain .left(58) .centerY() .width(1) .height(25) areaCodeLab.layoutChain .left() .rightToView(phoneLineView) .centerY() phoneInputTF.layoutChain .leftToView(phoneLineView, offset: 13) .right() .edgesVertical() smsCodeInputView.layoutChain .topToBottomOfView(phoneInputView, offset: 20) .edges(excludingEdge: .top) .widthToView(phoneInputView) .heightToView(phoneInputView) smsCodeBtn.layoutChain .edgesVertical() .right() .width(100) smsCodeTF.layoutChain .edgesVertical() .left(20) .rightToLeftOfView(smsCodeBtn) loginButton.layoutChain .topToBottomOfView(otherPhoneView, offset: 63) .centerX() .width(247) .height(50) agreementView.layoutChain .leftToView(loginButton) .rightToView(loginButton) .bottom(55) .height(30) agreementLabel.layoutChain.edges() checkBox.layoutChain .left() .centerY() .width(12) .height(12) agreementTV.layoutChain .leftToRightOfView(checkBox, offset: 0) .right() .top() phoneLoginBtn.layoutChain .bottomToTopOfView(agreementView, offset: -81) .centerX() .width(38) .heightToWidth(1) appleLoginBtn.layoutChain .rightToLeftOfView(phoneLoginBtn, offset: -43) .centerY(phoneLoginBtn) .widthToView(phoneLoginBtn) .heightToView(phoneLoginBtn) wechatLoginBtn.layoutChain .leftToRightOfView(phoneLoginBtn, offset: 43) .centerY(phoneLoginBtn) .widthToView(phoneLoginBtn) .heightToView(phoneLoginBtn) } override init(frame: CGRect) { super.init(frame: .zero) backgroundColor = .white setupUI() setupRx() setupAgreementTextWithCarrier(carrier: "") } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } // MARK: - UI Components lazy var bgMaskImage: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "Login/bg") iv.contentMode = .scaleAspectFill return iv }() lazy var backBtn: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "Common/back"), for: .normal) btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 50, right: 50) return btn }() lazy var guestLoginButton: UIButton = { let btn = UIButton(type: .system) btn.setTitle("游客登录", for: .normal) btn.setTitleColor(.white, for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium) btn.setBackgroundImage(UIImage(named: "Login/visitor_bg"), for: .normal) return btn }() lazy var welcomeLabel: UILabel = { let label = UILabel() label.text = "欢迎登录" label.font = UIFont(name: "DOUYU Font", size: 24) label.textColor = UIColor(hexStr: "#030303") label.textAlignment = .center return label }() lazy var phoneNumberLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 20, weight: .medium) label.textColor = ThemeManager.shared.color.titleAuxColor label.textAlignment = .center return label }() lazy var carrierLabel: UILabel = { let label = UILabel() label.font = .systemFont(ofSize: 12) label.textColor = ThemeManager.shared.color.contentColor label.textAlignment = .center return label }() // 其他手机号登录 lazy var otherPhoneView: UIView = { let view = UIView() view.backgroundColor = .clear // view.isHidden = true return view }() // 手机号 lazy var phoneInputView: UIView = { let view = UIView() view.backgroundColor = .clear view.borderWidth = 1 view.borderColor = .white view.cornerRadius = 8 view.addSubview(areaCodeLab) view.addSubview(phoneLineView) view.addSubview(phoneInputTF) return view }() lazy var areaCodeLab: UILabel = { let label = UILabel() label.text = "+86" label.font = .systemFont(ofSize: 16, weight: .medium) label.textColor = .white label.textAlignment = .center return label }() lazy var phoneLineView: UIView = { let view = UIView() view.backgroundColor = .white return view }() lazy var phoneInputTF: UITextField = { let textField = UITextField() textField.font = .systemFont(ofSize: 16, weight: .medium) textField.placeholderColor(placeholder: "请输入手机号码", color: .white) // textField.tintColor = ThemeManager.shared.color.mainColor textField.clearButtonMode = .whileEditing textField.keyboardType = .numberPad return textField }() // 验证码 lazy var smsCodeInputView: UIView = { let view = UIView() view.backgroundColor = .clear view.borderWidth = 1 view.borderColor = .white view.cornerRadius = 8 view.addSubview(smsCodeTF) view.addSubview(smsCodeBtn) return view }() lazy var smsCodeTF: UITextField = { let textField = UITextField() textField.font = .systemFont(ofSize: 16, weight: .medium) textField.placeholderColor(placeholder: "请输入验证码", color: .white) textField.keyboardType = .numbersAndPunctuation return textField }() lazy var smsCodeBtn: UIButton = { let button = UIButton() button.setTitle("获取验证码", for: .normal) button.setTitleColor(UIColor(hexStr: "#030303"), for: .normal) button.setTitleColor(UIColor(hexStr: "#999999", alpha: 1.0), for: .disabled) button.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) return button }() lazy var loginButton: UIButton = { let btn = UIButton(type: .system) btn.setTitle("立即登录", for: .normal) btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal) btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) btn.setBackgroundImage(UIImage(named: "Login/login_bg"), for: .normal) return btn }() lazy var wechatLoginBtn: UIButton = { let btn = UIButton(type: .custom) btn.setBackgroundImage(UIImage(named: "Login/wechat"), for: .normal) btn.backgroundColor = .clear return btn }() lazy var appleLoginBtn: UIButton = { let btn = UIButton(type: .custom) btn.setBackgroundImage(UIImage(named: "Login/apple"), for: .normal) btn.backgroundColor = .clear return btn }() lazy var phoneLoginBtn: UIButton = { let btn = UIButton(type: .custom) btn.setBackgroundImage(UIImage(named: "Login/phone"), for: .normal) btn.backgroundColor = .clear return btn }() lazy var agreementView: UIView = { let view = UIView() view.backgroundColor = .clear return view }() lazy var checkBox: UIButton = { let btn = UIButton(type: .custom) btn.setImage(UIImage(named: "Login/checkbox"), for: .normal) btn.setImage(UIImage(named: "Login/selected"), for: .selected) btn.extendEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) return btn }() lazy var agreementLabel: UILabel = { let label = UILabel() label.textColor = .clear label.numberOfLines = 1 label.textAlignment = .center label.font = .systemFont(ofSize: 10) return label }() lazy var agreementTV: UITextView = { let textView = UITextView() textView.font = .systemFont(ofSize: 10, weight: .medium) textView.backgroundColor = .clear textView.isEditable = false textView.isScrollEnabled = false textView.isSelectable = false textView.linkTextAttributes = [:] return textView }() }