Initial commit

This commit is contained in:
2026-06-22 11:28:01 +08:00
commit ace9c94359
84 changed files with 8899 additions and 0 deletions

View File

@ -0,0 +1,157 @@
//
// ProfileViewModel.swift
// suixinkan
//
// Created by Codex on 2026/6/20.
//
import Foundation
import Observation
@MainActor
@Observable
/// ViewModel
final class ProfileViewModel {
var userInfo: UserInfoResponse?
var realNameInfo: RealNameInfo?
var isLoading = false
var isSaving = false
var isEditingProfile = false
var editingNickname = ""
var displayNickname: String {
nonEmpty(userInfo?.nickname) ?? "未设置昵称"
}
var displayRealName: String {
nonEmpty(userInfo?.realName) ?? "--"
}
var displayPhone: String {
nonEmpty(userInfo?.phone) ?? "--"
}
var displayAvatarURL: String {
nonEmpty(userInfo?.avatar) ?? ""
}
var accountStatusText: String {
nonEmpty(userInfo?.statusName) ?? "--"
}
var realNameStatusText: String {
guard let realNameInfo else { return "点击去实名认证" }
switch realNameInfo.auditStatus {
case 2:
return "已实名认证"
case 3:
return "审核不通过"
default:
return "审核中"
}
}
///
func reload(api: ProfileAPI) async throws {
guard !isLoading else { return }
isLoading = true
defer { isLoading = false }
async let user = api.userInfo()
async let realName = api.realNameInfo()
let result = try await (user, realName)
userInfo = result.0
realNameInfo = result.1.realNameInfo
}
///
func beginEditing() {
editingNickname = displayNickname == "未设置昵称" ? "" : displayNickname
isEditingProfile = true
}
/// 退
func cancelEditing() {
editingNickname = ""
isEditingProfile = false
}
/// userInfo
func saveProfile(api: ProfileAPI) async throws {
let nextNickname = editingNickname.trimmingCharacters(in: .whitespacesAndNewlines)
guard !nextNickname.isEmpty else {
throw ProfileValidationError.emptyNickname
}
let nicknameChanged = nextNickname != displayNickname
guard nicknameChanged else {
cancelEditing()
return
}
guard !isSaving else { return }
isSaving = true
defer { isSaving = false }
try await api.updateUserInfo(nickname: nextNickname)
var nextUser = userInfo ?? UserInfoResponse()
nextUser = UserInfoResponse(
avatar: nextUser.avatar,
realName: nextUser.realName,
phone: nextUser.phone,
nickname: nextNickname,
roleName: nextUser.roleName,
status: nextUser.status,
statusName: nextUser.statusName
)
userInfo = nextUser
cancelEditing()
}
///
func updatePassword(_ password: String, api: ProfileAPI) async throws {
let nextPassword = password.trimmingCharacters(in: .whitespacesAndNewlines)
guard nextPassword.count >= 6 else {
throw ProfileValidationError.shortPassword
}
guard !isSaving else { return }
isSaving = true
defer { isSaving = false }
try await api.updateUserInfo(password: nextPassword)
}
/// userInfo AccountProfile userId
func accountProfileFallback(_ fallback: AccountProfile?) -> AccountProfile? {
guard let userInfo else { return fallback }
return AccountProfile(
userId: fallback?.userId ?? "",
displayName: nonEmpty(userInfo.nickname) ?? nonEmpty(userInfo.realName) ?? fallback?.displayName ?? "未设置昵称",
phone: nonEmpty(userInfo.phone) ?? fallback?.phone,
avatarURL: nonEmpty(userInfo.avatar) ?? fallback?.avatarURL
)
}
///
private func nonEmpty(_ value: String?) -> String? {
let text = value?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
return text.isEmpty ? nil : text
}
}
///
enum ProfileValidationError: LocalizedError {
case emptyNickname
case shortPassword
var errorDescription: String? {
switch self {
case .emptyNickname:
"请输入昵称"
case .shortPassword:
"密码至少 6 位"
}
}
}