feat: 更新登录模块以支持验证码和渐变背景

主要变更:
1. 在 EPLoginTypesViewController 中添加了渐变背景到 actionButton,提升视觉效果。
2. 实现了输入框状态检查功能,确保在输入有效信息时启用登录按钮。
3. 更新了输入框配置,支持不同类型的键盘输入(如数字键盘和邮箱键盘)。
4. 在 EPLoginService 中添加了对手机号和邮箱的 DES 加密,增强安全性。
5. 更新了 EPLoginConfig,统一输入框和按钮的样式设置。

此更新旨在提升用户体验,确保登录过程的安全性和流畅性。
This commit is contained in:
edwinQQQ
2025-10-13 17:49:09 +08:00
parent 809cc44ca5
commit 02a8335d70
8 changed files with 287 additions and 78 deletions

View File

@@ -27,6 +27,8 @@ class EPLoginTypesViewController: UIViewController {
private let actionButton = UIButton(type: .system)
private var forgotPasswordButton: UIButton?
private var hasAddedGradient = false
// MARK: - Lifecycle
override func viewDidLoad() {
@@ -40,6 +42,24 @@ class EPLoginTypesViewController: UIViewController {
navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// actionButton
if !hasAddedGradient && actionButton.bounds.width > 0 {
actionButton.addGradientBackground(
with: [
EPLoginConfig.Colors.gradientStart,
EPLoginConfig.Colors.gradientEnd
],
start: CGPoint(x: 0, y: 0.5),
end: CGPoint(x: 1, y: 0.5),
cornerRadius: EPLoginConfig.Layout.uniformCornerRadius
)
hasAddedGradient = true
}
}
// MARK: - Setup
private func setupUI() {
@@ -89,17 +109,16 @@ class EPLoginTypesViewController: UIViewController {
view.addSubview(secondInputView)
firstInputView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.leading.equalToSuperview().offset(EPLoginConfig.Layout.uniformHorizontalPadding)
make.trailing.equalToSuperview().offset(-EPLoginConfig.Layout.uniformHorizontalPadding)
make.top.equalTo(titleLabel.snp.bottom).offset(EPLoginConfig.Layout.inputTitleSpacing)
make.width.equalTo(EPLoginConfig.Layout.buttonWidth)
make.height.equalTo(EPLoginConfig.Layout.buttonHeight)
make.height.equalTo(EPLoginConfig.Layout.uniformHeight)
}
secondInputView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.leading.trailing.equalTo(firstInputView)
make.top.equalTo(firstInputView.snp.bottom).offset(EPLoginConfig.Layout.inputVerticalSpacing)
make.width.equalTo(EPLoginConfig.Layout.buttonWidth)
make.height.equalTo(EPLoginConfig.Layout.buttonHeight)
make.height.equalTo(EPLoginConfig.Layout.uniformHeight)
}
}
@@ -107,16 +126,18 @@ class EPLoginTypesViewController: UIViewController {
view.addSubview(actionButton)
actionButton.setTitle("Login", for: .normal)
actionButton.setTitleColor(EPLoginConfig.Colors.textLight, for: .normal)
actionButton.backgroundColor = EPLoginConfig.Colors.primary
actionButton.layer.cornerRadius = EPLoginConfig.Layout.cornerRadius
actionButton.layer.cornerRadius = EPLoginConfig.Layout.uniformCornerRadius
actionButton.titleLabel?.font = .systemFont(ofSize: EPLoginConfig.Layout.buttonFontSize, weight: .semibold)
actionButton.addTarget(self, action: #selector(handleAction), for: .touchUpInside)
//
actionButton.isEnabled = false
actionButton.alpha = 0.5
actionButton.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.leading.trailing.equalTo(firstInputView)
make.top.equalTo(secondInputView.snp.bottom).offset(EPLoginConfig.Layout.buttonTopSpacing)
make.width.equalTo(EPLoginConfig.Layout.buttonWidth)
make.height.equalTo(EPLoginConfig.Layout.buttonHeight)
make.height.equalTo(EPLoginConfig.Layout.uniformHeight)
}
}
@@ -130,16 +151,26 @@ class EPLoginTypesViewController: UIViewController {
showAreaCode: false,
showCodeButton: false,
isSecure: false,
icon: "person",
placeholder: "Please enter ID"
icon: "icon_login_id",
placeholder: "Please enter ID",
keyboardType: .numberPad // ID 使
))
firstInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.configure(with: EPLoginInputConfig(
showAreaCode: false,
showCodeButton: false,
isSecure: true,
icon: "lock",
placeholder: "Please enter password"
icon: "icon_login_id",
placeholder: "Please enter password",
keyboardType: .default // 使+
))
secondInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
actionButton.setTitle("Login", for: .normal)
//
@@ -152,15 +183,24 @@ class EPLoginTypesViewController: UIViewController {
showCodeButton: false,
isSecure: false,
icon: "envelope",
placeholder: "Please enter email"
placeholder: "Please enter email",
keyboardType: .emailAddress // Email 使
))
firstInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.configure(with: EPLoginInputConfig(
showAreaCode: false,
showCodeButton: true,
isSecure: false,
icon: "number",
placeholder: "Please enter verification code"
placeholder: "Please enter verification code",
keyboardType: .numberPad // 使
))
secondInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.delegate = self
actionButton.setTitle("Login", for: .normal)
@@ -171,15 +211,24 @@ class EPLoginTypesViewController: UIViewController {
showCodeButton: false,
isSecure: false,
icon: "phone",
placeholder: "Please enter phone"
placeholder: "Please enter phone",
keyboardType: .numberPad // 使
))
firstInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.configure(with: EPLoginInputConfig(
showAreaCode: false,
showCodeButton: true,
isSecure: false,
icon: "number",
placeholder: "Please enter verification code"
placeholder: "Please enter verification code",
keyboardType: .numberPad // 使
))
secondInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.delegate = self
actionButton.setTitle("Login", for: .normal)
@@ -190,15 +239,24 @@ class EPLoginTypesViewController: UIViewController {
showCodeButton: false,
isSecure: false,
icon: "envelope",
placeholder: "Please enter email"
placeholder: "Please enter email",
keyboardType: .emailAddress // Email 使
))
firstInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.configure(with: EPLoginInputConfig(
showAreaCode: false,
showCodeButton: true,
isSecure: false,
icon: "number",
placeholder: "Please enter verification code"
placeholder: "Please enter verification code",
keyboardType: .numberPad // 使
))
secondInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.delegate = self
//
@@ -212,15 +270,24 @@ class EPLoginTypesViewController: UIViewController {
showCodeButton: false,
isSecure: false,
icon: "phone",
placeholder: "Please enter phone"
placeholder: "Please enter phone",
keyboardType: .numberPad // 使
))
firstInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.configure(with: EPLoginInputConfig(
showAreaCode: false,
showCodeButton: true,
isSecure: false,
icon: "number",
placeholder: "Please enter verification code"
placeholder: "Please enter verification code",
keyboardType: .numberPad // 使
))
secondInputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
secondInputView.delegate = self
//
@@ -253,23 +320,25 @@ class EPLoginTypesViewController: UIViewController {
showCodeButton: false,
isSecure: true,
icon: EPLoginConfig.Images.iconLock,
placeholder: "6-16 Digits + English Letters"
placeholder: "6-16 Digits + English Letters",
keyboardType: .default // 使+
))
inputView.onTextChanged = { [weak self] _ in
self?.checkActionButtonStatus()
}
view.addSubview(inputView)
inputView.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.leading.trailing.equalTo(firstInputView)
make.top.equalTo(secondInputView.snp.bottom).offset(EPLoginConfig.Layout.inputVerticalSpacing)
make.width.equalTo(EPLoginConfig.Layout.buttonWidth)
make.height.equalTo(EPLoginConfig.Layout.buttonHeight)
make.height.equalTo(EPLoginConfig.Layout.uniformHeight)
}
// actionButton
actionButton.snp.remakeConstraints { make in
make.centerX.equalToSuperview()
make.leading.trailing.equalTo(firstInputView)
make.top.equalTo(inputView.snp.bottom).offset(EPLoginConfig.Layout.buttonTopSpacing)
make.width.equalTo(EPLoginConfig.Layout.buttonWidth)
make.height.equalTo(EPLoginConfig.Layout.buttonHeight)
make.height.equalTo(EPLoginConfig.Layout.uniformHeight)
}
thirdInputView = inputView
@@ -513,16 +582,21 @@ class EPLoginTypesViewController: UIViewController {
return
}
let type = (displayType == .phoneReset) ? 2 : 1 // 2=, 1=
loginService.sendPhoneCode(phone: phone, areaCode: "+86", type: type) { [weak self] in
DispatchQueue.main.async {
self?.secondInputView.startCountdown()
self?.showAlert("验证码已发送")
}
} failure: { [weak self] (code: Int, msg: String) in
DispatchQueue.main.async {
self?.showAlert("发送失败: \(msg)")
//
loadCaptchaWebView { [weak self] in
guard let self = self else { return }
let type = (self.displayType == .phoneReset) ? 2 : 1 // 2=, 1=
self.loginService.sendPhoneCode(phone: phone, areaCode: "+86", type: type) { [weak self] in
DispatchQueue.main.async {
self?.secondInputView.startCountdown()
self?.showAlert("验证码已发送")
}
} failure: { [weak self] (code: Int, msg: String) in
DispatchQueue.main.async {
self?.showAlert("发送失败: \(msg)")
}
}
}
}
@@ -538,8 +612,9 @@ class EPLoginTypesViewController: UIViewController {
// MARK: - UI Helpers
private func showLoading(_ show: Bool) {
actionButton.isEnabled = !show
if show {
actionButton.isEnabled = false
actionButton.alpha = 0.5
actionButton.setTitle("Loading...", for: .normal)
} else {
switch displayType {
@@ -548,9 +623,36 @@ class EPLoginTypesViewController: UIViewController {
case .emailReset, .phoneReset:
actionButton.setTitle("Confirm", for: .normal)
}
checkActionButtonStatus()
}
}
///
private func checkActionButtonStatus() {
let isEnabled: Bool
switch displayType {
case .id:
let hasId = !firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
let hasPassword = !secondInputView.text.isEmpty
isEnabled = hasId && hasPassword
case .email, .phone:
let hasAccount = !firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
let hasCode = !secondInputView.text.isEmpty
isEnabled = hasAccount && hasCode
case .emailReset, .phoneReset:
let hasAccount = !firstInputView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
let hasCode = !secondInputView.text.isEmpty
let hasPassword = !(thirdInputView?.text.isEmpty ?? true)
isEnabled = hasAccount && hasCode && hasPassword
}
actionButton.isEnabled = isEnabled
actionButton.alpha = isEnabled ? 1.0 : 0.5
}
private func showAlert(_ message: String, completion: (() -> Void)? = nil) {
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "确定", style: .default) { _ in
@@ -558,6 +660,37 @@ class EPLoginTypesViewController: UIViewController {
})
present(alert, animated: true)
}
/// Captcha WebView
/// - Parameter completion:
private func loadCaptchaWebView(completion: @escaping () -> Void) {
guard ClientConfig.share().shouldDisplayCaptcha else {
//
completion()
return
}
view.endEditing(true)
let webVC = XPWebViewController(roomUID: nil)
webVC.view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width * 0.8, height: UIScreen.main.bounds.width * 1.2)
webVC.view.backgroundColor = .clear
webVC.view.layer.cornerRadius = 12
webVC.view.layer.masksToBounds = true
webVC.isLoginStatus = false
webVC.isPush = false
webVC.hideNavigationBar()
webVC.url = URLWithType(.captchaSwitch)
webVC.verifyCaptcha = { result in
if result {
TTPopup.dismiss()
completion()
}
}
TTPopup.popupView(webVC.view, style: .alert)
}
}
// MARK: - EPLoginInputViewDelegate

View File

@@ -33,18 +33,18 @@ import UIKit
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.setNavigationBarHidden(true, animated: false)
setupUI()
loadPolicyStatus()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// navigationController?.setNavigationBarHidden(false, animated: animated)
}
// MARK: - Setup

View File

@@ -18,3 +18,16 @@ func YMLocalizedString(_ key: String) -> String {
return Bundle.ymLocalizedString(forKey: key)
}
/// URLType
extension URLType {
static var captchaSwitch: URLType {
return URLType(rawValue: 113)! // kCaptchaSwitchPath
}
}
/// DES
func encryptDES(_ plainText: String) -> String {
// 使 ObjC
let key = "1ea53d260ecf11e7b56e00163e046a26"
return DESEncrypt.encryptUseDES(plainText, key: key) ?? plainText
}

View File

@@ -24,6 +24,13 @@ struct EPLoginConfig {
static let loginButtonSpacing: CGFloat = 24
///
static let loginButtonHorizontalPadding: CGFloat = 30
/// /
static let uniformHeight: CGFloat = 56
/// /
static let uniformHorizontalPadding: CGFloat = 29
/// /
static let uniformCornerRadius: CGFloat = 28
/// /
static let cornerRadius: CGFloat = 23
@@ -83,13 +90,15 @@ struct EPLoginConfig {
static let feedbackButtonCornerRadius: CGFloat = 10.5
///
static let inputHeight: CGFloat = 52
static let inputHeight: CGFloat = 56
///
static let inputCornerRadius: CGFloat = 26
static let inputCornerRadius: CGFloat = 28
///
static let inputHorizontalPadding: CGFloat = 24
/// icon
static let inputIconSize: CGFloat = 20
///
static let inputBorderWidth: CGFloat = 1
///
static let codeButtonWidth: CGFloat = 102
@@ -117,11 +126,15 @@ struct EPLoginConfig {
static let iconDisabled = UIColor.gray
///
static let inputBackground = UIColor(red: 0xF3/255.0, green: 0xF5/255.0, blue: 0xFA/255.0, alpha: 1.0)
static let inputBackground = UIColor.white.withAlphaComponent(0.1)
static let inputText = UIColor(red: 0x1F/255.0, green: 0x1B/255.0, blue: 0x4F/255.0, alpha: 1.0)
static let inputBorder = UIColor.lightGray.withAlphaComponent(0.3)
static let inputBorder = UIColor.white
static let inputBorderFocused = UIColor.systemPurple
/// Login/Confirm
static let gradientStart = UIColor(red: 0xF8/255.0, green: 0x54/255.0, blue: 0xFC/255.0, alpha: 1.0) // #F854FC
static let gradientEnd = UIColor(red: 0x50/255.0, green: 0x0F/255.0, blue: 0xFF/255.0, alpha: 1.0) // #500FFF
///
static let codeButtonBackground = UIColor(red: 0x91/255.0, green: 0x68/255.0, blue: 0xFA/255.0, alpha: 1.0)
@@ -203,11 +216,11 @@ struct EPLoginConfig {
/// Client Secret
static let clientSecret = "uyzjdhds"
/// Client ID
static let clientId = "1"
static let clientId = "erban-client"
/// Grant Type
static let grantType = "sms_code"
static let grantType = "password"
///
static let version = "1.0.31"
static let version = "1"
///
static let codeTypeLogin = 1
@@ -253,6 +266,10 @@ struct EPLoginConfig {
/// -
static let iconNumber = "number"
///
static let iconPasswordSee = "icon_password_see"
static let iconPasswordUnsee = "icon_password_unsee"
/// -
static let iconBack = "chevron.left"
/// -

View File

@@ -83,13 +83,16 @@ import Foundation
completion: @escaping () -> Void,
failure: @escaping (Int, String) -> Void) {
// 🔐 DES
let encryptedEmail = encryptDES(email)
Api.emailGetCode({ (data, code, msg) in
if code == 200 {
completion()
} else {
failure(Int(code), msg ?? "发送邮箱验证码失败")
}
}, emailAddress: email, type: NSNumber(value: type))
}, emailAddress: encryptedEmail, type: NSNumber(value: type))
}
///
@@ -105,10 +108,16 @@ import Foundation
completion: @escaping () -> Void,
failure: @escaping (Int, String) -> Void) {
// Api+Login
// Api+Login.h
print("[EPLoginService] sendPhoneCode - 需要确认实际的 API 接口")
failure(-1, "手机验证码接口待确认")
// 🔐 DES
let encryptedPhone = encryptDES(phone)
Api.phoneSmsCode({ (data, code, msg) in
if code == 200 {
completion()
} else {
failure(Int(code), msg ?? "发送手机验证码失败")
}
}, mobile: encryptedPhone, type: String(type), phoneAreaCode: areaCode)
}
// MARK: - Login Methods
@@ -124,6 +133,10 @@ import Foundation
completion: @escaping (AccountModel) -> Void,
failure: @escaping (Int, String) -> Void) {
// 🔐 DES ID
let encryptedId = encryptDES(id)
let encryptedPassword = encryptDES(password)
Api.login(password: { [weak self] (data, code, msg) in
self?.parseAndSaveAccount(
data: data,
@@ -133,8 +146,8 @@ import Foundation
failure(errorCode, msg ?? "登录失败")
})
},
phone: id,
password: password,
phone: encryptedId,
password: encryptedPassword,
client_secret: clientSecret,
version: version,
client_id: clientId,
@@ -152,6 +165,9 @@ import Foundation
completion: @escaping (AccountModel) -> Void,
failure: @escaping (Int, String) -> Void) {
// 🔐 DES
let encryptedEmail = encryptDES(email)
Api.login(code: { [weak self] (data, code, msg) in
self?.parseAndSaveAccount(
data: data,
@@ -161,7 +177,7 @@ import Foundation
failure(errorCode, msg ?? "登录失败")
})
},
email: email,
email: encryptedEmail,
code: code,
client_secret: clientSecret,
version: version,
@@ -182,6 +198,9 @@ import Foundation
completion: @escaping (AccountModel) -> Void,
failure: @escaping (Int, String) -> Void) {
// 🔐 DES
let encryptedPhone = encryptDES(phone)
Api.login(code: { [weak self] (data, code, msg) in
self?.parseAndSaveAccount(
data: data,
@@ -191,7 +210,7 @@ import Foundation
failure(errorCode, msg ?? "登录失败")
})
},
phone: phone,
phone: encryptedPhone,
code: code,
client_secret: clientSecret,
version: version,
@@ -215,13 +234,17 @@ import Foundation
completion: @escaping () -> Void,
failure: @escaping (Int, String) -> Void) {
// 🔐 DES
let encryptedEmail = encryptDES(email)
let encryptedPassword = encryptDES(newPassword)
Api.resetPassword(email: { (data, code, msg) in
if code == 200 {
completion()
} else {
failure(Int(code), msg ?? "重置密码失败")
}
}, email: email, newPwd: newPassword, code: code)
}, email: encryptedEmail, newPwd: encryptedPassword, code: code)
}
///
@@ -239,13 +262,17 @@ import Foundation
completion: @escaping () -> Void,
failure: @escaping (Int, String) -> Void) {
// 🔐 DES
let encryptedPhone = encryptDES(phone)
let encryptedPassword = encryptDES(newPassword)
Api.resetPassword(phone: { (data, code, msg) in
if code == 200 {
completion()
} else {
failure(Int(code), msg ?? "重置密码失败")
}
}, phone: phone, newPwd: newPassword, smsCode: code, phoneAreaCode: areaCode)
}, phone: encryptedPhone, newPwd: encryptedPassword, smsCode: code, phoneAreaCode: areaCode)
}
// MARK: - Phone Quick Login ()

View File

@@ -16,6 +16,7 @@ struct EPLoginInputConfig {
var isSecure: Bool = false
var icon: String?
var placeholder: String
var keyboardType: UIKeyboardType = .default
}
///
@@ -31,6 +32,9 @@ class EPLoginInputView: UIView {
weak var delegate: EPLoginInputViewDelegate?
///
var onTextChanged: ((String) -> Void)?
private let stackView = UIStackView()
//
@@ -82,6 +86,8 @@ class EPLoginInputView: UIView {
private func setupUI() {
backgroundColor = EPLoginConfig.Colors.inputBackground
layer.cornerRadius = EPLoginConfig.Layout.inputCornerRadius
layer.borderWidth = EPLoginConfig.Layout.inputBorderWidth
layer.borderColor = EPLoginConfig.Colors.inputBorder.cgColor
// Main StackView
stackView.axis = .horizontal
@@ -161,9 +167,10 @@ class EPLoginInputView: UIView {
}
// TextField
inputTextField.textColor = EPLoginConfig.Colors.inputText
inputTextField.textColor = EPLoginConfig.Colors.textLight
inputTextField.font = .systemFont(ofSize: 14)
inputTextField.tintColor = EPLoginConfig.Colors.primary
inputTextField.tintColor = EPLoginConfig.Colors.textLight
inputTextField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
stackView.addArrangedSubview(inputTextField)
inputTextField.snp.makeConstraints { make in
@@ -171,15 +178,18 @@ class EPLoginInputView: UIView {
}
}
@objc private func textFieldDidChange() {
onTextChanged?(inputTextField.text ?? "")
}
private func setupEyeButton() {
eyeButton.setImage(UIImage(systemName: "eye.slash"), for: .normal)
eyeButton.setImage(UIImage(systemName: "eye"), for: .selected)
eyeButton.tintColor = EPLoginConfig.Colors.icon
eyeButton.setImage(kImage(EPLoginConfig.Images.iconPasswordUnsee), for: .normal)
eyeButton.setImage(kImage(EPLoginConfig.Images.iconPasswordSee), for: .selected)
eyeButton.addTarget(self, action: #selector(handleEyeTap), for: .touchUpInside)
stackView.addArrangedSubview(eyeButton)
eyeButton.snp.makeConstraints { make in
make.width.equalTo(30)
make.size.equalTo(24)
}
}
@@ -209,16 +219,17 @@ class EPLoginInputView: UIView {
//
areaStackView.isHidden = !config.showAreaCode
// Icon
if let iconName = config.icon {
iconImageView.image = UIImage(systemName: iconName)
iconImageView.isHidden = false
} else {
iconImageView.isHidden = true
}
// Icon - 使
iconImageView.isHidden = true
// Placeholder
inputTextField.placeholder = config.placeholder
// Placeholder60%
inputTextField.attributedPlaceholder = NSAttributedString(
string: config.placeholder,
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white.withAlphaComponent(0.6)]
)
//
inputTextField.keyboardType = config.keyboardType
//
inputTextField.isSecureTextEntry = config.isSecure

View File

@@ -28,8 +28,8 @@
/// @param phone
/// @param password
+ (void)loginWithPassword:(HttpRequestHelperCompletion)completion phone:(NSString *)phone password:(NSString *)password client_secret:(NSString *)client_secret version:(NSString *)version client_id:(NSString *)client_id grant_type:(NSString *)grant_type {
NSString * fang = [NSString stringFromBase64String:@"b2F1dGgvdG9rZW4="];///oauth/token
[self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,phone,password,client_secret,version, client_id, grant_type, nil];
[self makeRequest:@"oauth/token" method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__,phone,password,client_secret,version, client_id, grant_type, nil];
}
///

View File

@@ -43,6 +43,7 @@
// MARK: - Utilities
#import "UIImage+Utils.h"
#import "NSString+Utils.h"
#import "UIView+GradientLayer.h"
#import <MJExtension/MJExtension.h>
// MARK: - Login - Navigation & Web
@@ -51,6 +52,9 @@
// MARK: - Login - Utilities
#import "YUMIMacroUitls.h" // YMLocalizedString
#import "YUMIHtmlUrl.h" // URLWithType
#import "YUMIConstant.h" // KeyWithType, KeyType_PasswordEncode
#import "DESEncrypt.h" // DES加密工具
// MARK: - Login - Models (Phase 2 使用,先添加)
#import "AccountInfoStorage.h"
@@ -60,6 +64,10 @@
#import "Api+Login.h"
#import "Api+Main.h"
// MARK: - Login - Captcha & Config
#import "ClientConfig.h"
#import "TTPopup.h"
// 注意:
// 1. EPMomentViewController 和 EPMineViewController 直接继承 UIViewController
// 2. 不继承 BaseViewController避免 ClientConfig → PIBaseModel 依赖链)