feat: 增强邮箱登录功能和密码恢复流程
- 更新邮箱登录相关功能,新增邮箱验证码获取和登录API端点。 - 添加AccountModel以管理用户认证信息,支持会话票据的存储和更新。 - 实现密码恢复功能,支持通过邮箱获取验证码和重置密码。 - 增加本地化支持,更新相关字符串以适应新功能。 - 引入ValidationHelper以验证邮箱和密码格式,确保用户输入的有效性。 - 更新视图以支持邮箱登录和密码恢复的用户交互。
This commit is contained in:
@@ -35,6 +35,10 @@ enum APIError: Error, Equatable {
|
||||
case httpError(statusCode: Int, message: String?)
|
||||
case timeout
|
||||
case resourceTooLarge
|
||||
case encryptionFailed // 新增:加密失败
|
||||
case invalidResponse // 新增:无效响应
|
||||
case ticketFailed // 新增:票据获取失败
|
||||
case custom(String) // 新增:自定义错误信息
|
||||
case unknown(String)
|
||||
|
||||
var localizedDescription: String {
|
||||
@@ -53,6 +57,14 @@ enum APIError: Error, Equatable {
|
||||
return "请求超时"
|
||||
case .resourceTooLarge:
|
||||
return "响应数据过大"
|
||||
case .encryptionFailed:
|
||||
return "数据加密失败"
|
||||
case .invalidResponse:
|
||||
return "服务器响应无效"
|
||||
case .ticketFailed:
|
||||
return "获取会话票据失败"
|
||||
case .custom(let message):
|
||||
return message
|
||||
case .unknown(let message):
|
||||
return "未知错误: \(message)"
|
||||
}
|
||||
@@ -233,6 +245,7 @@ struct UserInfoManager {
|
||||
static let accessToken = "access_token"
|
||||
static let ticket = "user_ticket"
|
||||
static let userInfo = "user_info"
|
||||
static let accountModel = "account_model" // 新增:AccountModel存储键
|
||||
}
|
||||
|
||||
// MARK: - User ID Management
|
||||
@@ -337,6 +350,7 @@ struct UserInfoManager {
|
||||
userDefaults.removeObject(forKey: StorageKeys.userId)
|
||||
userDefaults.removeObject(forKey: StorageKeys.accessToken)
|
||||
userDefaults.removeObject(forKey: StorageKeys.userInfo)
|
||||
clearAccountModel() // 新增:清除 AccountModel
|
||||
clearTicket()
|
||||
userDefaults.synchronize()
|
||||
|
||||
@@ -356,6 +370,76 @@ struct UserInfoManager {
|
||||
// 实际实现中应该调用 TicketHelper.createTicketRequest
|
||||
return false
|
||||
}
|
||||
|
||||
// MARK: - Account Model Management
|
||||
/// 保存 AccountModel
|
||||
/// - Parameter accountModel: 要保存的账户模型
|
||||
static func saveAccountModel(_ accountModel: AccountModel) {
|
||||
do {
|
||||
let data = try JSONEncoder().encode(accountModel)
|
||||
userDefaults.set(data, forKey: StorageKeys.accountModel)
|
||||
userDefaults.synchronize()
|
||||
|
||||
// 同时更新各个独立字段(向后兼容)
|
||||
if let uid = accountModel.uid {
|
||||
saveUserId(uid)
|
||||
}
|
||||
if let accessToken = accountModel.accessToken {
|
||||
saveAccessToken(accessToken)
|
||||
}
|
||||
if let ticket = accountModel.ticket {
|
||||
saveTicket(ticket)
|
||||
}
|
||||
|
||||
print("💾 AccountModel 保存成功")
|
||||
} catch {
|
||||
print("❌ AccountModel 保存失败: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取 AccountModel
|
||||
/// - Returns: 存储的账户模型,如果不存在或解析失败返回 nil
|
||||
static func getAccountModel() -> AccountModel? {
|
||||
guard let data = userDefaults.data(forKey: StorageKeys.accountModel) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
do {
|
||||
return try JSONDecoder().decode(AccountModel.self, from: data)
|
||||
} catch {
|
||||
print("❌ AccountModel 解析失败: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// 更新 AccountModel 中的 ticket
|
||||
/// - Parameter ticket: 新的票据
|
||||
static func updateAccountModelTicket(_ ticket: String) {
|
||||
guard var accountModel = getAccountModel() else {
|
||||
print("❌ 无法更新 ticket:AccountModel 不存在")
|
||||
return
|
||||
}
|
||||
|
||||
accountModel.ticket = ticket
|
||||
saveAccountModel(accountModel)
|
||||
saveTicket(ticket) // 同时更新内存中的 ticket
|
||||
}
|
||||
|
||||
/// 检查是否有有效的 AccountModel
|
||||
/// - Returns: 是否存在有效的账户模型
|
||||
static func hasValidAccountModel() -> Bool {
|
||||
guard let accountModel = getAccountModel() else {
|
||||
return false
|
||||
}
|
||||
return accountModel.hasValidAuthentication
|
||||
}
|
||||
|
||||
/// 清除 AccountModel
|
||||
static func clearAccountModel() {
|
||||
userDefaults.removeObject(forKey: StorageKeys.accountModel)
|
||||
userDefaults.synchronize()
|
||||
print("🗑️ AccountModel 已清除")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API Request Protocol
|
||||
|
Reference in New Issue
Block a user