
主要变更: 1. 在 EPLoginTypesViewController 中添加了渐变背景到 actionButton,提升视觉效果。 2. 实现了输入框状态检查功能,确保在输入有效信息时启用登录按钮。 3. 更新了输入框配置,支持不同类型的键盘输入(如数字键盘和邮箱键盘)。 4. 在 EPLoginService 中添加了对手机号和邮箱的 DES 加密,增强安全性。 5. 更新了 EPLoginConfig,统一输入框和按钮的样式设置。 此更新旨在提升用户体验,确保登录过程的安全性和流畅性。
253 lines
8.8 KiB
Swift
253 lines
8.8 KiB
Swift
//
|
||
// EPLoginViewController.swift
|
||
// YuMi
|
||
//
|
||
// Created by AI on 2025-01-27.
|
||
//
|
||
|
||
import UIKit
|
||
|
||
@objc class EPLoginViewController: UIViewController {
|
||
|
||
// MARK: - Properties
|
||
|
||
private let backgroundImageView = UIImageView()
|
||
private let logoImageView = UIImageView()
|
||
private let epartiTitleLabel = UILabel()
|
||
|
||
private let idLoginButton = EPLoginButton()
|
||
private let emailLoginButton = EPLoginButton()
|
||
|
||
private let agreeCheckbox = UIButton(type: .custom)
|
||
private let policyLabel = EPPolicyLabel()
|
||
|
||
private let feedbackButton = UIButton(type: .custom)
|
||
|
||
#if DEBUG
|
||
private let debugButton = UIButton(type: .custom)
|
||
#endif
|
||
|
||
private let policySelectedKey = EPLoginConfig.Keys.policyAgreed
|
||
|
||
// MARK: - Lifecycle
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
navigationController?.setNavigationBarHidden(true, animated: false)
|
||
setupUI()
|
||
loadPolicyStatus()
|
||
}
|
||
|
||
override func viewWillAppear(_ animated: Bool) {
|
||
super.viewWillAppear(animated)
|
||
|
||
}
|
||
|
||
override func viewWillDisappear(_ animated: Bool) {
|
||
super.viewWillDisappear(animated)
|
||
}
|
||
|
||
// MARK: - Setup
|
||
|
||
private func setupUI() {
|
||
setupBackground()
|
||
setupLogo()
|
||
setupLoginButtons()
|
||
setupPolicyArea()
|
||
setupNavigationBar()
|
||
}
|
||
|
||
private func setupBackground() {
|
||
view.addSubview(backgroundImageView)
|
||
backgroundImageView.image = kImage(EPLoginConfig.Images.background)
|
||
backgroundImageView.contentMode = .scaleAspectFill
|
||
|
||
backgroundImageView.snp.makeConstraints { make in
|
||
make.edges.equalToSuperview()
|
||
}
|
||
}
|
||
|
||
private func setupLogo() {
|
||
view.addSubview(logoImageView)
|
||
logoImageView.image = kImage(EPLoginConfig.Images.loginBg)
|
||
|
||
logoImageView.snp.makeConstraints { make in
|
||
make.top.leading.trailing.equalTo(view)
|
||
make.height.equalTo(EPLoginConfig.Layout.logoHeight)
|
||
}
|
||
|
||
// E-PARTI 标题
|
||
view.addSubview(epartiTitleLabel)
|
||
epartiTitleLabel.text = "E-PARTI"
|
||
epartiTitleLabel.font = .systemFont(ofSize: EPLoginConfig.Layout.epartiTitleFontSize, weight: .bold)
|
||
epartiTitleLabel.textColor = EPLoginConfig.Colors.textLight
|
||
epartiTitleLabel.transform = CGAffineTransform(a: 1, b: 0, c: -0.2, d: 1, tx: 0, ty: 0) // 斜体效果
|
||
|
||
epartiTitleLabel.snp.makeConstraints { make in
|
||
make.leading.equalToSuperview().offset(EPLoginConfig.Layout.epartiTitleLeading)
|
||
make.bottom.equalTo(logoImageView.snp.bottom).offset(EPLoginConfig.Layout.epartiTitleBottomOffset)
|
||
}
|
||
}
|
||
|
||
private func setupLoginButtons() {
|
||
// 配置按钮
|
||
idLoginButton.configure(
|
||
icon: EPLoginConfig.Images.iconLoginId,
|
||
title: YMLocalizedString(EPLoginConfig.LocalizedKeys.idLogin)
|
||
)
|
||
idLoginButton.delegate = self
|
||
|
||
emailLoginButton.configure(
|
||
icon: EPLoginConfig.Images.iconLoginEmail,
|
||
title: YMLocalizedString(EPLoginConfig.LocalizedKeys.emailLogin)
|
||
)
|
||
emailLoginButton.delegate = self
|
||
|
||
// StackView 布局
|
||
let stackView = UIStackView(arrangedSubviews: [idLoginButton, emailLoginButton])
|
||
stackView.axis = .vertical
|
||
stackView.spacing = EPLoginConfig.Layout.loginButtonSpacing
|
||
stackView.distribution = .fillEqually
|
||
view.addSubview(stackView)
|
||
|
||
stackView.snp.makeConstraints { make in
|
||
make.leading.equalToSuperview().offset(EPLoginConfig.Layout.loginButtonHorizontalPadding)
|
||
make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.loginButtonHorizontalPadding)
|
||
make.top.equalTo(logoImageView.snp.bottom)
|
||
}
|
||
|
||
idLoginButton.snp.makeConstraints { make in
|
||
make.height.equalTo(EPLoginConfig.Layout.loginButtonHeight)
|
||
}
|
||
|
||
emailLoginButton.snp.makeConstraints { make in
|
||
make.height.equalTo(EPLoginConfig.Layout.loginButtonHeight)
|
||
}
|
||
}
|
||
|
||
private func setupPolicyArea() {
|
||
view.addSubview(agreeCheckbox)
|
||
view.addSubview(policyLabel)
|
||
|
||
agreeCheckbox.setImage(kImage("login_privace_select"), for: .selected)
|
||
agreeCheckbox.setImage(kImage("login_privace_unselect"), for: .normal)
|
||
agreeCheckbox.addTarget(self, action: #selector(togglePolicyCheckbox), for: .touchUpInside)
|
||
|
||
policyLabel.onUserAgreementTapped = { [weak self] in
|
||
self?.openPolicy(url: "https://example.com/user-agreement")
|
||
}
|
||
policyLabel.onPrivacyPolicyTapped = { [weak self] in
|
||
self?.openPolicy(url: "https://example.com/privacy-policy")
|
||
}
|
||
|
||
agreeCheckbox.snp.makeConstraints { make in
|
||
make.leading.equalToSuperview().offset(EPLoginConfig.Layout.horizontalPadding)
|
||
make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-30)
|
||
make.size.equalTo(EPLoginConfig.Layout.checkboxSize)
|
||
}
|
||
|
||
policyLabel.snp.makeConstraints { make in
|
||
make.leading.equalTo(agreeCheckbox.snp.trailing).offset(8)
|
||
make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.horizontalPadding)
|
||
make.centerY.equalTo(agreeCheckbox)
|
||
}
|
||
}
|
||
|
||
private func setupNavigationBar() {
|
||
view.addSubview(feedbackButton)
|
||
feedbackButton.setTitle(YMLocalizedString(EPLoginConfig.LocalizedKeys.feedback), for: .normal)
|
||
feedbackButton.titleLabel?.font = .systemFont(ofSize: EPLoginConfig.Layout.smallFontSize)
|
||
feedbackButton.backgroundColor = EPLoginConfig.Colors.backgroundTransparent
|
||
feedbackButton.layer.cornerRadius = EPLoginConfig.Layout.feedbackButtonCornerRadius
|
||
feedbackButton.addTarget(self, action: #selector(handleFeedback), for: .touchUpInside)
|
||
|
||
feedbackButton.snp.makeConstraints { make in
|
||
make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.compactHorizontalPadding)
|
||
make.top.equalTo(view.safeAreaLayoutGuide).offset(8)
|
||
make.height.equalTo(EPLoginConfig.Layout.feedbackButtonHeight)
|
||
}
|
||
|
||
#if DEBUG
|
||
view.addSubview(debugButton)
|
||
debugButton.setTitle("切换环境", for: .normal)
|
||
debugButton.setTitleColor(.blue, for: .normal)
|
||
debugButton.addTarget(self, action: #selector(handleDebug), for: .touchUpInside)
|
||
|
||
debugButton.snp.makeConstraints { make in
|
||
make.leading.equalToSuperview().offset(EPLoginConfig.Layout.compactHorizontalPadding)
|
||
make.top.equalTo(view.safeAreaLayoutGuide).offset(8)
|
||
}
|
||
#endif
|
||
}
|
||
|
||
// MARK: - Actions
|
||
|
||
private func handleIDLogin() {
|
||
let vc = EPLoginTypesViewController()
|
||
vc.displayType = .id
|
||
navigationController?.pushViewController(vc, animated: true)
|
||
}
|
||
|
||
private func handleEmailLogin() {
|
||
let vc = EPLoginTypesViewController()
|
||
vc.displayType = .email
|
||
navigationController?.pushViewController(vc, animated: true)
|
||
}
|
||
|
||
@objc private func togglePolicyCheckbox() {
|
||
agreeCheckbox.isSelected.toggle()
|
||
UserDefaults.standard.set(agreeCheckbox.isSelected, forKey: policySelectedKey)
|
||
}
|
||
|
||
@objc private func handleFeedback() {
|
||
print("[EPLogin] Feedback - 占位,Phase 2 实现")
|
||
}
|
||
|
||
#if DEBUG
|
||
@objc private func handleDebug() {
|
||
print("[EPLogin] Debug - 占位,Phase 2 实现")
|
||
}
|
||
#endif
|
||
|
||
private func openPolicy(url: String) {
|
||
let webVC = XPWebViewController(roomUID: nil)
|
||
webVC.url = url
|
||
navigationController?.pushViewController(webVC, animated: true)
|
||
}
|
||
|
||
// MARK: - Helpers
|
||
|
||
private func loadPolicyStatus() {
|
||
agreeCheckbox.isSelected = UserDefaults.standard.bool(forKey: policySelectedKey)
|
||
// 默认勾选
|
||
if !UserDefaults.standard.bool(forKey: EPLoginConfig.Keys.hasLaunchedBefore) {
|
||
agreeCheckbox.isSelected = true
|
||
UserDefaults.standard.set(true, forKey: policySelectedKey)
|
||
UserDefaults.standard.set(true, forKey: EPLoginConfig.Keys.hasLaunchedBefore)
|
||
}
|
||
}
|
||
|
||
private func checkPolicyAgreed() -> Bool {
|
||
if !agreeCheckbox.isSelected {
|
||
// Phase 2: 显示提示
|
||
print("[EPLogin] Please agree to policy first")
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
}
|
||
|
||
// MARK: - EPLoginButtonDelegate
|
||
|
||
extension EPLoginViewController: EPLoginButtonDelegate {
|
||
func loginButtonDidTap(_ button: EPLoginButton) {
|
||
guard checkPolicyAgreed() else { return }
|
||
|
||
if button == idLoginButton {
|
||
handleIDLogin()
|
||
} else if button == emailLoginButton {
|
||
handleEmailLogin()
|
||
}
|
||
}
|
||
}
|