| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- //
- // LoginViewController.swift
- // VenusKitto
- //
- // Created by Neoa on 2025/8/21.
- //
- import Foundation
- import UIKit
- import WebKit
- class LoginViewController: UIViewController {
- // UI Elements
- var logoImageView: UIImageView!
- var phoneNumberTextField: UITextField!
- var verificationCodeTextField: UITextField!
- var getVerificationCodeButton: UIButton!
- var termsCheckboxButton: UIButton!
- var loginButton: UIButton!
- var termsLabel: UILabel!
-
- // State
- var isTermsAccepted: Bool = false
- var customAlertView: UIView!
- var alertBackground: UIView!
-
- // State
- var isCountdownActive: Bool = false
- var countdownTimer: Timer?
- var remainingTime: Int = 60
- var uuid: String?
- override func viewDidLoad() {
- super.viewDidLoad()
-
- // Set up the view background color
- view.backgroundColor = .white
-
- if let backImage = UIImage(named: "AddPet385") {
- let backButton = UIBarButtonItem(image: backImage.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(tapCancel))
- navigationItem.leftBarButtonItem = backButton
- }
-
- let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
- view.addGestureRecognizer(tapGesture)
-
- // Set up the logo
- logoImageView = UIImageView()
- logoImageView.image = UIImage(named: "cats378")
- logoImageView.contentMode = .scaleAspectFit
- logoImageView.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(logoImageView)
-
- // Set up phone number text field
- phoneNumberTextField = UITextField()
- phoneNumberTextField.placeholder = "请输入手机号码"
- phoneNumberTextField.keyboardType = .numberPad
- phoneNumberTextField.borderStyle = .roundedRect
- phoneNumberTextField.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(phoneNumberTextField)
-
- // Set up verification code text field
- verificationCodeTextField = UITextField()
- verificationCodeTextField.placeholder = "请输入验证码"
- verificationCodeTextField.keyboardType = .numberPad
- verificationCodeTextField.borderStyle = .roundedRect
- verificationCodeTextField.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(verificationCodeTextField)
-
- // Set up get verification code button
- getVerificationCodeButton = UIButton(type: .system)
- getVerificationCodeButton.setTitle("获取验证码", for: .normal)
- getVerificationCodeButton.titleLabel?.font = UIFont.systemFont(ofSize: 13)
- getVerificationCodeButton.setTitleColor(UIColor(hex: "#000000"), for: .normal)
- getVerificationCodeButton.translatesAutoresizingMaskIntoConstraints = false
- getVerificationCodeButton.addTarget(self, action: #selector(getVerificationCode), for: .touchUpInside)
- view.addSubview(getVerificationCodeButton)
-
- // Set up terms checkbox button
- termsCheckboxButton = UIButton(type: .custom)
- termsCheckboxButton.setImage(UIImage(named: "cats370"), for: .normal)
- termsCheckboxButton.setImage(UIImage(named: "cats371"), for: .selected)
- termsCheckboxButton.addTarget(self, action: #selector(toggleTermsAcceptance), for: .touchUpInside)
- termsCheckboxButton.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(termsCheckboxButton)
-
- // Set up terms label with clickable links
- termsLabel = UILabel()
- termsLabel.font = UIFont.systemFont(ofSize: 12)
- termsLabel.textColor = .gray
- termsLabel.numberOfLines = 0
- termsLabel.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(termsLabel)
-
- // Set up the clickable parts of the text with specific color and links
- let fullText = "我已阅读并同意《中国认证服务条款》以及《用户协议》和《隐私政策》"
- let attributedText = NSMutableAttributedString(string: fullText)
-
- // Define ranges
- let range1 = (fullText as NSString).range(of: "中国认证服务条款")
- let range2 = (fullText as NSString).range(of: "用户协议")
- let range3 = (fullText as NSString).range(of: "隐私政策")
-
- let linkColor = UIColor(hex: "#FFE059")
-
- // Set color and underline for clickable text
- attributedText.addAttribute(.foregroundColor, value: linkColor, range: range1)
- attributedText.addAttribute(.foregroundColor, value: linkColor, range: range2)
- attributedText.addAttribute(.foregroundColor, value: linkColor, range: range3)
-
- // Add underline style to indicate clickable
- attributedText.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range1)
- attributedText.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range2)
- attributedText.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: range3)
-
- // Add link attribute with custom scheme for tap detection
- attributedText.addAttribute(.link, value: "terms://service", range: range1)
- attributedText.addAttribute(.link, value: "terms://user", range: range2)
- attributedText.addAttribute(.link, value: "terms://privacy", range: range3)
-
- // Use UITextView instead of UILabel to support clickable links
- let termsTextView = UITextView()
- termsTextView.attributedText = attributedText
- termsTextView.font = UIFont.systemFont(ofSize: 12)
- termsTextView.textColor = .gray
- termsTextView.isEditable = false
- termsTextView.isScrollEnabled = false
- termsTextView.backgroundColor = .clear
- termsTextView.translatesAutoresizingMaskIntoConstraints = false
- termsTextView.dataDetectorTypes = []
- termsTextView.delegate = self
- termsTextView.textContainerInset = .zero
- termsTextView.textContainer.lineFragmentPadding = 0
- termsTextView.linkTextAttributes = [
- .foregroundColor: UIColor(hex: "#000000"),
- .underlineStyle: NSUnderlineStyle.single.rawValue
- ]
- view.addSubview(termsTextView)
- self.termsLabel = nil // Remove the UILabel reference since using UITextView
-
- // Set up login button
- loginButton = UIButton(type: .system)
- loginButton.setTitle("登录", for: .normal)
- loginButton.backgroundColor = UIColor(hex: "#FFE059")
- loginButton.setTitleColor(.black, for: .normal)
- loginButton.layer.cornerRadius = 25
- loginButton.addTarget(self, action: #selector(login), for: .touchUpInside)
- loginButton.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(loginButton)
-
- // Set up constraints
- NSLayoutConstraint.activate([
- logoImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40),
- logoImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
- logoImageView.widthAnchor.constraint(equalToConstant: 100),
- logoImageView.heightAnchor.constraint(equalToConstant: 100),
-
- phoneNumberTextField.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 40),
- phoneNumberTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
- phoneNumberTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
- phoneNumberTextField.heightAnchor.constraint(equalToConstant: 40),
-
- verificationCodeTextField.topAnchor.constraint(equalTo: phoneNumberTextField.bottomAnchor, constant: 20),
- verificationCodeTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
- verificationCodeTextField.trailingAnchor.constraint(equalTo: getVerificationCodeButton.leadingAnchor, constant: -10),
- verificationCodeTextField.heightAnchor.constraint(equalToConstant: 40),
-
- getVerificationCodeButton.centerYAnchor.constraint(equalTo: verificationCodeTextField.centerYAnchor),
- getVerificationCodeButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
- getVerificationCodeButton.widthAnchor.constraint(equalToConstant: 100),
- getVerificationCodeButton.heightAnchor.constraint(equalToConstant: 40),
-
- termsCheckboxButton.topAnchor.constraint(equalTo: verificationCodeTextField.bottomAnchor, constant: 20),
- termsCheckboxButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
- termsCheckboxButton.widthAnchor.constraint(equalToConstant: 20),
- termsCheckboxButton.heightAnchor.constraint(equalToConstant: 20),
-
- termsTextView.topAnchor.constraint(equalTo: verificationCodeTextField.bottomAnchor, constant: 20),
- termsTextView.leadingAnchor.constraint(equalTo: termsCheckboxButton.trailingAnchor, constant: 10),
- termsTextView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
- termsTextView.heightAnchor.constraint(greaterThanOrEqualToConstant: 40),
-
- loginButton.topAnchor.constraint(equalTo: termsTextView.bottomAnchor, constant: 30),
- loginButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
- loginButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
- loginButton.heightAnchor.constraint(equalToConstant: 50)
- ])
- }
-
- @objc private func tapCancel() {
- self.dismiss(animated: true)
- }
-
- @objc func dismissKeyboard() {
- // Dismiss the keyboard when tapping outside the text fields
- view.endEditing(true)
- }
-
- // MARK: - Actions
- @objc func getVerificationCode() {
- // Logic to handle verification code request
- print("获取验证码")
-
- if isCountdownActive {
- return // If countdown is already active, do nothing
- }
-
- // Validate phone number
- guard let phoneNumber = phoneNumberTextField.text, !phoneNumber.isEmpty else {
- // Show error if phone number is empty
- showError("请输入手机号码")
- return
- }
-
- guard isValidPhoneNumber(phoneNumber) else {
- showAlert(title: "提示", message: "手机号格式不正确")
- return
- }
-
-
- // Send POST request to the server with phone number
- let url = URL(string: "\(baseURL)/petRecordApUser/sendSmsCode")!
- var request = URLRequest(url: url)
- request.httpMethod = "POST"
- request.setValue("application/json", forHTTPHeaderField: "Content-Type")
- let parameters = ["phonenumber": phoneNumber]
- request.httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: .fragmentsAllowed)
-
-
- print("Request URL: \(url)")
- print("Request Parameters: \(parameters)")
- // Make the network request
- URLSession.shared.dataTask(with: request) { data, response, error in
- if let error = error {
- DispatchQueue.main.async {
- self.showError("请求失败: \(error.localizedDescription)")
- }
- return
- }
-
-
- // Log the response status code
- if let response = response as? HTTPURLResponse {
- print("Response Status Code: \(response.statusCode)")
- }
- // Handle the response here (e.g., check the status code or response)
- DispatchQueue.main.async {
- if let data = data {
- print("ssss \(data)")
- // Example response handling (customize this part as per your API response)
- if let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
-
-
- // 验证码发送成功
- if let dataDict = json["data"] as? [String: Any],
- let uuid = dataDict["uuid"] as? String {
- print("验证码发送成功,UUID: \(uuid)")
- // 保存uuid到属性中
- self.uuid = uuid
- // Start the countdown
- self.startCountdown()
- } else {
- self.uuid = "uuidstring"
- let errorMsg = json["msg"] as? String ?? "登录失败,未知错误"
- self.showAlert(title: "发送失败", message: errorMsg)
- }
- // Print the entire JSON object
- print("Response JSON: \(json)")
-
- // If you want to print specific values from the JSON, you can access them like this:
- // if let uuid = json["uuid"] as? String {
- // print("UUID received: \(uuid)")
- // self.uuid = uuid
- // }
- // You can also print other parts of the response
- if let message = json["msg"] as? String {
- print("Server Message: \(message)")
- }
- } }
- }
-
- }.resume()
- }
-
- @objc private func loginTapped() {
- guard let phone = phoneNumberTextField.text, !phone.isEmpty else {
- showAlert(title: "提示", message: "请输入手机号")
- return
- }
-
- guard isValidPhoneNumber(phone) else {
- showAlert(title: "提示", message: "手机号格式不正确")
- return
- }
-
- guard let code = verificationCodeTextField.text, !code.isEmpty else {
- showAlert(title: "提示", message: "请输入验证码")
- return
- }
-
- // Ensure UUID is available (it should be set when the SMS code was requested)
- guard let uuid = self.uuid else {
- showAlert(title: "错误", message: "请先获取验证码")
- return
- }
-
- // Prepare the request parameters
- let parameters: [String: Any] = [
- "phonenumber": phone,
- "smsCode": code,
- "uuid": uuid // Pass the uuid received during the SMS request
- ]
-
- // Create the URL for the login API
- guard let url = URL(string: "\(baseURL)/petRecordApUser/phoneLogin") else {
- showAlert(title: "错误", message: "无效的URL")
- return
- }
-
- // Create the request
- var request = URLRequest(url: url)
- request.httpMethod = "POST"
- request.setValue("application/json", forHTTPHeaderField: "Content-Type")
-
- // Log the request URL and parameters
- print("Login Request URL: \(url)")
- print("Login Request Parameters: \(parameters)")
- // Add the JSON body to the request
- do {
- request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
- } catch {
- showAlert(title: "错误", message: "参数编码失败: \(error.localizedDescription)")
- return
- }
-
- // Show activity indicator while making the network request
- let activityIndicator = UIActivityIndicatorView(style: .medium)
- activityIndicator.center = view.center
- view.addSubview(activityIndicator)
- activityIndicator.startAnimating()
-
- // Send the request using URLSession
- let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
- // Ensure UI updates happen on the main thread
- DispatchQueue.main.async {
- activityIndicator.stopAnimating()
- activityIndicator.removeFromSuperview()
-
- guard let self = self else { return }
-
- if let error = error {
- self.showAlert(title: "网络错误", message: error.localizedDescription)
- return
- }
-
- guard let data = data else {
- self.showAlert(title: "错误", message: "未收到响应数据")
- return
- }
-
- // 解析JSON响应
- // In the response handler for the login request:
- do {
- if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
- // Check the response code
-
- if let code = json["code"] as? String, code == "200" {
- // Login successful
- print("登录成功: \(json)")
- UserDefaults.standard.set(true, forKey: "isLogggedIn")
- // Check if the token is present in the data
- if let dataDict = json["data"] as? [String: Any], let token = dataDict["token"] as? String {
- // Save the token and proceed with login
- print("Token received: \(token)")
- UserDefaults.standard.set(token, forKey: "userToken") // Store the token
-
- // Navigate to the main interface
- let mainVC = HomeViewController()
- let navController = UINavigationController(rootViewController: mainVC)
- // Replace with your actual main screen controller
- // self.navigationController?.setViewControllers([mainVC], animated: true)
- // 获取当前窗口
- guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
- return
- }
- // 设置根视图控制器为登录界面
- window.rootViewController = navController
- // 添加切换动画
- UIView.transition(with: window,
- duration: 0.4,
- options: .transitionCrossDissolve,
- animations: nil,
- completion: nil)
- } else {
- // Handle missing token error
- self.showAlert(title: "错误", message: "Token 不存在")
- }
- } else {
- // Log the error message from the server if code isn't 200
- print("登录失败: \(json)")
- if let msg = json["msg"] as? String {
- print("Login failed with message: \(msg)")
- self.showAlert(title: "登录失败", message: msg)
- } else {
- // Handle case where msg is not returned
- self.showAlert(title: "登录失败", message: "未知错误")
- }
- }
- } else {
- // Handle invalid JSON response format
- self.showAlert(title: "错误", message: "无效的响应格式")
- }
- } catch {
- // Handle JSON parsing errors
- self.showAlert(title: "解析错误", message: "无法解析响应: \(error.localizedDescription)")
- }
- }
- }
-
- task.resume()
- }
-
- func isValidPhoneNumber(_ phoneNumber: String) -> Bool {
- let phoneRegex = "^1[3-9]\\d{9}$" // This is a basic regex for validating Chinese phone numbers
- let phoneTest = NSPredicate(format: "SELF MATCHES %@", phoneRegex)
- return phoneTest.evaluate(with: phoneNumber)
- }
-
- func showAlert(title: String, message: String) {
- let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
- alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
- present(alert, animated: true, completion: nil)
- }
-
- func startCountdown() {
- // Disable the button and start the countdown
- isCountdownActive = true
- getVerificationCodeButton.isEnabled = false
- countdownTimer?.invalidate() // Invalidate previous timer if any
- remainingTime = 60
- updateButtonTitle()
-
- // Create a new timer to update the button every second
- countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
- }
-
- @objc func updateCountdown() {
- remainingTime -= 1
- updateButtonTitle()
-
- if remainingTime <= 0 {
- // Countdown is complete, reset everything
- countdownTimer?.invalidate()
- isCountdownActive = false
- getVerificationCodeButton.isEnabled = true
- getVerificationCodeButton.setTitle("获取验证码", for: .normal)
- }
- }
-
- func updateButtonTitle() {
- let title = "重新获取 (\(remainingTime)s)"
- getVerificationCodeButton.setTitle(title, for: .normal)
- }
-
- func showError(_ message: String) {
- let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
- alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
- present(alert, animated: true, completion: nil)
- }
-
- @objc func toggleTermsAcceptance() {
- // Toggle the acceptance of terms
- isTermsAccepted.toggle()
- termsCheckboxButton.isSelected = isTermsAccepted
- }
-
- @objc func login() {
- // Logic to handle login
- if !isTermsAccepted {
- showCustomAlert()
- } else {
- // Proceed with login if terms are accepted
- print("登录")
- loginTapped()
- }
- }
-
- // MARK: - Custom Alert
- func showCustomAlert() {
- // Create a custom alert background (semi-transparent)
- alertBackground = UIView(frame: view.bounds)
- alertBackground.backgroundColor = UIColor.black.withAlphaComponent(0.5)
- alertBackground.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(alertBackground)
-
- // Create the alert view (popup window)
- customAlertView = UIView()
- customAlertView.backgroundColor = .white
- customAlertView.layer.cornerRadius = 10
- customAlertView.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(customAlertView)
-
- // Add title label
- let titleLabel = UILabel()
- titleLabel.text = "温馨提示"
- titleLabel.font = UIFont.boldSystemFont(ofSize: 18)
- titleLabel.textAlignment = .center
- titleLabel.translatesAutoresizingMaskIntoConstraints = false
- customAlertView.addSubview(titleLabel)
-
- // Add message label with colored text
- let alertFullText = "已阅读并同意《用户协议》和《隐私政策》"
- let alertAttributedText = NSMutableAttributedString(string: alertFullText)
- // Set all text to gray first
- alertAttributedText.addAttribute(.foregroundColor, value: UIColor.gray, range: NSRange(location: 0, length: alertFullText.count))
- // Find and set black color for "用户协议" and "隐私政策"
- let alertRange1 = (alertFullText as NSString).range(of: "用户协议")
- let alertRange2 = (alertFullText as NSString).range(of: "隐私政策")
- alertAttributedText.addAttribute(.foregroundColor, value: UIColor.black, range: alertRange1)
- alertAttributedText.addAttribute(.foregroundColor, value: UIColor.black, range: alertRange2)
- let messageLabel = UILabel()
- messageLabel.attributedText = alertAttributedText
- messageLabel.font = UIFont.systemFont(ofSize: 14)
- messageLabel.textAlignment = .center
- messageLabel.numberOfLines = 0
- messageLabel.translatesAutoresizingMaskIntoConstraints = false
- customAlertView.addSubview(messageLabel)
-
- // Add Agree Button
- let agreeButton = UIButton(type: .system)
- agreeButton.setTitle("同意并登录", for: .normal)
- agreeButton.backgroundColor = UIColor(hex: "#FFE059")
- agreeButton.setTitleColor(.black, for: .normal)
- agreeButton.layer.cornerRadius = 20
- agreeButton.addTarget(self, action: #selector(agreeAction), for: .touchUpInside)
- agreeButton.translatesAutoresizingMaskIntoConstraints = false
- customAlertView.addSubview(agreeButton)
-
- // Add Disagree Button
- let disagreeButton = UIButton(type: .system)
- disagreeButton.setTitle("不同意", for: .normal)
- disagreeButton.setTitleColor(.gray, for: .normal)
- disagreeButton.addTarget(self, action: #selector(disagreeAction), for: .touchUpInside)
- disagreeButton.translatesAutoresizingMaskIntoConstraints = false
- customAlertView.addSubview(disagreeButton)
-
- // Set up constraints for alert view
- NSLayoutConstraint.activate([
- // Alert background (full screen, semi-transparent)
- alertBackground.topAnchor.constraint(equalTo: view.topAnchor),
- alertBackground.leadingAnchor.constraint(equalTo: view.leadingAnchor),
- alertBackground.trailingAnchor.constraint(equalTo: view.trailingAnchor),
- alertBackground.bottomAnchor.constraint(equalTo: view.bottomAnchor),
-
- // Custom alert view (popup)
- customAlertView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
- customAlertView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
- customAlertView.widthAnchor.constraint(equalToConstant: 300),
- customAlertView.heightAnchor.constraint(equalToConstant: 180),
-
- // Title label
- titleLabel.topAnchor.constraint(equalTo: customAlertView.topAnchor, constant: 20),
- titleLabel.leadingAnchor.constraint(equalTo: customAlertView.leadingAnchor, constant: 20),
- titleLabel.trailingAnchor.constraint(equalTo: customAlertView.trailingAnchor, constant: -20),
-
- // Message label
- messageLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 10),
- messageLabel.leadingAnchor.constraint(equalTo: customAlertView.leadingAnchor, constant: 20),
- messageLabel.trailingAnchor.constraint(equalTo: customAlertView.trailingAnchor, constant: -20),
-
- // Agree button
- agreeButton.topAnchor.constraint(equalTo: messageLabel.bottomAnchor, constant: 20),
- agreeButton.leadingAnchor.constraint(equalTo: customAlertView.leadingAnchor, constant: 20),
- agreeButton.trailingAnchor.constraint(equalTo: customAlertView.trailingAnchor, constant: -20),
- agreeButton.heightAnchor.constraint(equalToConstant: 40),
-
- // Disagree button
- disagreeButton.topAnchor.constraint(equalTo: agreeButton.bottomAnchor, constant: 10),
- disagreeButton.leadingAnchor.constraint(equalTo: customAlertView.leadingAnchor, constant: 20),
- disagreeButton.trailingAnchor.constraint(equalTo: customAlertView.trailingAnchor, constant: -20),
- disagreeButton.heightAnchor.constraint(equalToConstant: 40)
- ])
- }
-
- @objc func agreeAction() {
- // Handle the "Agree" action (e.g., proceed with login)
- print("用户同意协议,继续登录")
- customAlertView.removeFromSuperview()
- alertBackground.removeFromSuperview()
- loginTapped()
- }
-
- @objc func disagreeAction() {
- // Handle the "Disagree" action (e.g., close the alert)
- print("用户不同意协议,取消登录")
- customAlertView.removeFromSuperview()
- alertBackground.removeFromSuperview()
- }
-
-
- }
- extension LoginViewController: UITextViewDelegate {
- func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
- var urlString = ""
- switch URL.absoluteString {
- case "terms://service":
- urlString = "https://ytwljs.github.io/gl-us.html"
- case "terms://user":
- urlString = "https://ytwljs.github.io/gl-user.html"
- case "terms://privacy":
- urlString = "https://ytwljs.github.io/gl-policy.html"
- default:
- return false
- }
-
- let webVC = WebViewController()
- webVC.urlString = urlString
- navigationController?.pushViewController(webVC, animated: true)
- return false
- }
- }
- class WebViewController: UIViewController, WKNavigationDelegate {
- var urlString: String?
- var webView: WKWebView!
-
- override func viewDidLoad() {
- super.viewDidLoad()
- view.backgroundColor = .white
-
- webView = WKWebView(frame: view.bounds)
- webView.navigationDelegate = self
- webView.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(webView)
-
- NSLayoutConstraint.activate([
- webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
- webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
- webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
- webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
- ])
-
- if let urlString = urlString, let url = URL(string: urlString) {
- let request = URLRequest(url: url)
- webView.load(request)
- }
- }
-
-
- }
- extension UIColor {
- convenience init(hex: String) {
- var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
- hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
-
- var rgb: UInt64 = 0
- Scanner(string: hexSanitized).scanHexInt64(&rgb)
-
- self.init(
- red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
- green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
- blue: CGFloat(rgb & 0x0000FF) / 255.0,
- alpha: 1.0
- )
- }
- }
|