feat: 添加新的登录模块及相关组件
主要变更: 1. 新增 EPLoginViewController 和 EPLoginTypesViewController,提供新的登录界面和功能。 2. 引入 EPLoginInputView 和 EPLoginButton 组件,支持输入框和按钮的自定义。 3. 实现 EPLoginService 和 EPLoginManager,封装登录逻辑和 API 请求。 4. 添加 EPLoginConfig 和 EPLoginState,统一配置和状态管理。 5. 更新 Bridging Header,确保 Swift 和 Objective-C 代码的互操作性。 此更新旨在提升用户登录体验,简化登录流程,并提供更好的代码结构和可维护性。
This commit is contained in:
277
YuMi/E-P/NewLogin/Services/EPLoginService.swift
Normal file
277
YuMi/E-P/NewLogin/Services/EPLoginService.swift
Normal file
@@ -0,0 +1,277 @@
|
||||
//
|
||||
// EPLoginService.swift
|
||||
// YuMi
|
||||
//
|
||||
// Created by AI on 2025-01-27.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// 登录服务封装(Swift 现代化版本)
|
||||
/// 统一封装所有登录相关 API,完全替代 OC 版本的 LoginPresenter
|
||||
@objc class EPLoginService: NSObject {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private let clientSecret = EPLoginConfig.API.clientSecret
|
||||
private let clientId = EPLoginConfig.API.clientId
|
||||
private let grantType = EPLoginConfig.API.grantType
|
||||
private let version = EPLoginConfig.API.version
|
||||
|
||||
// MARK: - Private Helper Methods
|
||||
|
||||
/// 解析并保存 AccountModel
|
||||
/// - Parameters:
|
||||
/// - data: API 返回的数据
|
||||
/// - code: 状态码
|
||||
/// - completion: 成功回调
|
||||
/// - failure: 失败回调
|
||||
private func parseAndSaveAccount(data: BaseModel?,
|
||||
code: Int64,
|
||||
completion: @escaping (AccountModel) -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
if code == 200 {
|
||||
if let accountDict = data?.data as? NSDictionary,
|
||||
let accountModel = AccountModel.mj_object(withKeyValues: accountDict) {
|
||||
// 保存账号信息
|
||||
AccountInfoStorage.instance().saveAccountInfo(accountModel)
|
||||
completion(accountModel)
|
||||
} else {
|
||||
failure(Int(code), "账号信息解析失败")
|
||||
}
|
||||
} else {
|
||||
failure(Int(code), "操作失败")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Request Ticket
|
||||
|
||||
/// 请求 Ticket(登录成功后调用)
|
||||
/// - Parameters:
|
||||
/// - accessToken: 访问令牌
|
||||
/// - completion: 成功回调 (ticket)
|
||||
/// - failure: 失败回调 (错误码, 错误信息)
|
||||
@objc func requestTicket(accessToken: String,
|
||||
completion: @escaping (String) -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.requestTicket({ (data, code, msg) in
|
||||
if code == 200, let dict = data?.data as? NSDictionary {
|
||||
if let tickets = dict["tickets"] as? NSArray,
|
||||
let firstTicket = tickets.firstObject as? NSDictionary,
|
||||
let ticket = firstTicket["ticket"] as? String {
|
||||
completion(ticket)
|
||||
} else {
|
||||
failure(Int(code), "Ticket 解析失败")
|
||||
}
|
||||
} else {
|
||||
failure(Int(code), msg ?? "请求 Ticket 失败")
|
||||
}
|
||||
}, access_token: accessToken, issue_type: "multi")
|
||||
}
|
||||
|
||||
// MARK: - Send Verification Code
|
||||
|
||||
/// 发送邮箱验证码
|
||||
/// - Parameters:
|
||||
/// - email: 邮箱地址
|
||||
/// - type: 类型 (1=登录, 2=找回密码)
|
||||
/// - completion: 成功回调
|
||||
/// - failure: 失败回调
|
||||
@objc func sendEmailCode(email: String,
|
||||
type: Int,
|
||||
completion: @escaping () -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.emailGetCode({ (data, code, msg) in
|
||||
if code == 200 {
|
||||
completion()
|
||||
} else {
|
||||
failure(Int(code), msg ?? "发送邮箱验证码失败")
|
||||
}
|
||||
}, emailAddress: email, type: NSNumber(value: type))
|
||||
}
|
||||
|
||||
/// 发送手机验证码
|
||||
/// - Parameters:
|
||||
/// - phone: 手机号
|
||||
/// - areaCode: 区号
|
||||
/// - type: 类型 (1=登录, 2=找回密码)
|
||||
/// - completion: 成功回调
|
||||
/// - failure: 失败回调
|
||||
@objc func sendPhoneCode(phone: String,
|
||||
areaCode: String,
|
||||
type: Int,
|
||||
completion: @escaping () -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
// 注意:这里需要根据实际的 Api+Login 接口调用
|
||||
// 当前 Api+Login.h 中没有直接的手机验证码接口,可能需要通过其他方式
|
||||
print("[EPLoginService] sendPhoneCode - 需要确认实际的 API 接口")
|
||||
failure(-1, "手机验证码接口待确认")
|
||||
}
|
||||
|
||||
// MARK: - Login Methods
|
||||
|
||||
/// ID + 密码登录
|
||||
/// - Parameters:
|
||||
/// - id: 用户 ID
|
||||
/// - password: 密码
|
||||
/// - completion: 成功回调 (AccountModel)
|
||||
/// - failure: 失败回调
|
||||
@objc func loginWithID(id: String,
|
||||
password: String,
|
||||
completion: @escaping (AccountModel) -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.login(password: { [weak self] (data, code, msg) in
|
||||
self?.parseAndSaveAccount(
|
||||
data: data,
|
||||
code: Int64(code),
|
||||
completion: completion,
|
||||
failure: { errorCode, _ in
|
||||
failure(errorCode, msg ?? "登录失败")
|
||||
})
|
||||
},
|
||||
phone: id,
|
||||
password: password,
|
||||
client_secret: clientSecret,
|
||||
version: version,
|
||||
client_id: clientId,
|
||||
grant_type: grantType)
|
||||
}
|
||||
|
||||
/// 邮箱 + 验证码登录
|
||||
/// - Parameters:
|
||||
/// - email: 邮箱地址
|
||||
/// - code: 验证码
|
||||
/// - completion: 成功回调 (AccountModel)
|
||||
/// - failure: 失败回调
|
||||
@objc func loginWithEmail(email: String,
|
||||
code: String,
|
||||
completion: @escaping (AccountModel) -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.login(code: { [weak self] (data, code, msg) in
|
||||
self?.parseAndSaveAccount(
|
||||
data: data,
|
||||
code: Int64(code),
|
||||
completion: completion,
|
||||
failure: { errorCode, _ in
|
||||
failure(errorCode, msg ?? "登录失败")
|
||||
})
|
||||
},
|
||||
email: email,
|
||||
code: code,
|
||||
client_secret: clientSecret,
|
||||
version: version,
|
||||
client_id: clientId,
|
||||
grant_type: grantType)
|
||||
}
|
||||
|
||||
/// 手机号 + 验证码登录
|
||||
/// - Parameters:
|
||||
/// - phone: 手机号
|
||||
/// - code: 验证码
|
||||
/// - areaCode: 区号
|
||||
/// - completion: 成功回调 (AccountModel)
|
||||
/// - failure: 失败回调
|
||||
@objc func loginWithPhone(phone: String,
|
||||
code: String,
|
||||
areaCode: String,
|
||||
completion: @escaping (AccountModel) -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.login(code: { [weak self] (data, code, msg) in
|
||||
self?.parseAndSaveAccount(
|
||||
data: data,
|
||||
code: Int64(code),
|
||||
completion: completion,
|
||||
failure: { errorCode, _ in
|
||||
failure(errorCode, msg ?? "登录失败")
|
||||
})
|
||||
},
|
||||
phone: phone,
|
||||
code: code,
|
||||
client_secret: clientSecret,
|
||||
version: version,
|
||||
client_id: clientId,
|
||||
grant_type: grantType,
|
||||
phoneAreaCode: areaCode)
|
||||
}
|
||||
|
||||
// MARK: - Reset Password
|
||||
|
||||
/// 邮箱重置密码
|
||||
/// - Parameters:
|
||||
/// - email: 邮箱地址
|
||||
/// - code: 验证码
|
||||
/// - newPassword: 新密码
|
||||
/// - completion: 成功回调
|
||||
/// - failure: 失败回调
|
||||
@objc func resetEmailPassword(email: String,
|
||||
code: String,
|
||||
newPassword: String,
|
||||
completion: @escaping () -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.resetPassword(email: { (data, code, msg) in
|
||||
if code == 200 {
|
||||
completion()
|
||||
} else {
|
||||
failure(Int(code), msg ?? "重置密码失败")
|
||||
}
|
||||
}, email: email, newPwd: newPassword, code: code)
|
||||
}
|
||||
|
||||
/// 手机号重置密码
|
||||
/// - Parameters:
|
||||
/// - phone: 手机号
|
||||
/// - code: 验证码
|
||||
/// - areaCode: 区号
|
||||
/// - newPassword: 新密码
|
||||
/// - completion: 成功回调
|
||||
/// - failure: 失败回调
|
||||
@objc func resetPhonePassword(phone: String,
|
||||
code: String,
|
||||
areaCode: String,
|
||||
newPassword: String,
|
||||
completion: @escaping () -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.resetPassword(phone: { (data, code, msg) in
|
||||
if code == 200 {
|
||||
completion()
|
||||
} else {
|
||||
failure(Int(code), msg ?? "重置密码失败")
|
||||
}
|
||||
}, phone: phone, newPwd: newPassword, smsCode: code, phoneAreaCode: areaCode)
|
||||
}
|
||||
|
||||
// MARK: - Phone Quick Login (保留接口)
|
||||
|
||||
/// 手机快速登录(保留接口但 UI 暂不暴露)
|
||||
/// - Parameters:
|
||||
/// - accessToken: 访问令牌
|
||||
/// - token: 令牌
|
||||
/// - completion: 成功回调 (AccountModel)
|
||||
/// - failure: 失败回调
|
||||
@objc func phoneQuickLogin(accessToken: String,
|
||||
token: String,
|
||||
completion: @escaping (AccountModel) -> Void,
|
||||
failure: @escaping (Int, String) -> Void) {
|
||||
|
||||
Api.phoneQuickLogin({ [weak self] (data, code, msg) in
|
||||
self?.parseAndSaveAccount(
|
||||
data: data,
|
||||
code: Int64(code),
|
||||
completion: completion,
|
||||
failure: { errorCode, _ in
|
||||
failure(errorCode, msg ?? "快速登录失败")
|
||||
})
|
||||
},
|
||||
accessToken: accessToken,
|
||||
token: token)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user