Implement token-based root routing, Android-matched login screen, five-slot MainTabBar with scan action, and placeholder tab pages. Co-authored-by: Cursor <cursoragent@cursor.com>
62 lines
1.4 KiB
Swift
62 lines
1.4 KiB
Swift
//
|
||
// LoginViewModel.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// 登录页 ViewModel,UI 状态与 Android `LoginViewModel` 对齐。
|
||
final class LoginViewModel {
|
||
|
||
private(set) var account = ""
|
||
private(set) var password = ""
|
||
private(set) var isPrivacyChecked = false
|
||
private(set) var enableRegister = false
|
||
|
||
var isLoginEnabled: Bool {
|
||
!account.isEmpty && !password.isEmpty
|
||
}
|
||
|
||
var onStateChange: (() -> Void)?
|
||
|
||
func updateAccount(_ value: String) {
|
||
account = value
|
||
notifyStateChange()
|
||
}
|
||
|
||
func updatePassword(_ value: String) {
|
||
password = value
|
||
notifyStateChange()
|
||
}
|
||
|
||
func togglePrivacyChecked() {
|
||
isPrivacyChecked.toggle()
|
||
notifyStateChange()
|
||
}
|
||
|
||
func updateEnableRegister(_ enabled: Bool) {
|
||
enableRegister = enabled
|
||
notifyStateChange()
|
||
}
|
||
|
||
func login() {
|
||
guard isPrivacyChecked else {
|
||
onShowMessage?("请先阅读并同意用户协议与隐私政策")
|
||
return
|
||
}
|
||
guard isLoginEnabled else { return }
|
||
onLogin?()
|
||
}
|
||
|
||
var onShowMessage: ((String) -> Void)?
|
||
var onLogin: (() -> Void)?
|
||
var onLoginByCode: (() -> Void)?
|
||
var onRegister: (() -> Void)?
|
||
var onUserAgreement: (() -> Void)?
|
||
var onPrivacyPolicy: (() -> Void)?
|
||
|
||
private func notifyStateChange() {
|
||
onStateChange?()
|
||
}
|
||
}
|