Commit 63e4bec0 ilCode

Moya业务接口完善

1 个父辈 8613f641
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
5E47C97D2C202ED3002EA39E /* AsEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E47C97C2C202ED3002EA39E /* AsEmptyView.swift */; }; 5E47C97D2C202ED3002EA39E /* AsEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E47C97C2C202ED3002EA39E /* AsEmptyView.swift */; };
5E65F88B2C2275DB0082D374 /* RefreshFooterAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E65F88A2C2275DB0082D374 /* RefreshFooterAnimator.swift */; }; 5E65F88B2C2275DB0082D374 /* RefreshFooterAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E65F88A2C2275DB0082D374 /* RefreshFooterAnimator.swift */; };
5E65F88F2C2279160082D374 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5E65F88D2C2279160082D374 /* Localizable.strings */; }; 5E65F88F2C2279160082D374 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5E65F88D2C2279160082D374 /* Localizable.strings */; };
5E65F8932C22B7FB0082D374 /* UserModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E65F8922C22B7FB0082D374 /* UserModel.swift */; };
5E65F8952C22C5310082D374 /* UserManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E65F8942C22C5310082D374 /* UserManager.swift */; };
5E65F8972C22CAF40082D374 /* UserDefaultTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E65F8962C22CAF40082D374 /* UserDefaultTools.swift */; };
5E66B2D72C1BE2ED00590452 /* UIImage+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E66B2D62C1BE2ED00590452 /* UIImage+Ext.swift */; }; 5E66B2D72C1BE2ED00590452 /* UIImage+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E66B2D62C1BE2ED00590452 /* UIImage+Ext.swift */; };
5E66B2D92C1C295100590452 /* UIButton+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E66B2D82C1C295100590452 /* UIButton+Ext.swift */; }; 5E66B2D92C1C295100590452 /* UIButton+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E66B2D82C1C295100590452 /* UIButton+Ext.swift */; };
5E6CF00A2C12FAD600BF3CF5 /* TargetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6CF0092C12FAD600BF3CF5 /* TargetController.swift */; }; 5E6CF00A2C12FAD600BF3CF5 /* TargetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E6CF0092C12FAD600BF3CF5 /* TargetController.swift */; };
...@@ -92,6 +95,9 @@ ...@@ -92,6 +95,9 @@
5E65F88E2C2279160082D374 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; 5E65F88E2C2279160082D374 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
5E65F8902C227A1C0082D374 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = "<group>"; }; 5E65F8902C227A1C0082D374 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = "<group>"; };
5E65F8912C227A1C0082D374 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; }; 5E65F8912C227A1C0082D374 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
5E65F8922C22B7FB0082D374 /* UserModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserModel.swift; sourceTree = "<group>"; };
5E65F8942C22C5310082D374 /* UserManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserManager.swift; sourceTree = "<group>"; };
5E65F8962C22CAF40082D374 /* UserDefaultTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultTools.swift; sourceTree = "<group>"; };
5E66B2D62C1BE2ED00590452 /* UIImage+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Ext.swift"; sourceTree = "<group>"; }; 5E66B2D62C1BE2ED00590452 /* UIImage+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Ext.swift"; sourceTree = "<group>"; };
5E66B2D82C1C295100590452 /* UIButton+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Ext.swift"; sourceTree = "<group>"; }; 5E66B2D82C1C295100590452 /* UIButton+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Ext.swift"; sourceTree = "<group>"; };
5E6CF0092C12FAD600BF3CF5 /* TargetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetController.swift; sourceTree = "<group>"; }; 5E6CF0092C12FAD600BF3CF5 /* TargetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetController.swift; sourceTree = "<group>"; };
...@@ -189,6 +195,8 @@ ...@@ -189,6 +195,8 @@
5E93B48D2C1A98BE00CD6536 /* RegisterController.swift */, 5E93B48D2C1A98BE00CD6536 /* RegisterController.swift */,
5E93B48F2C1A9BDC00CD6536 /* LoginTools.swift */, 5E93B48F2C1A9BDC00CD6536 /* LoginTools.swift */,
5E9165D72C1D3F45004A3C5E /* UserProvider.swift */, 5E9165D72C1D3F45004A3C5E /* UserProvider.swift */,
5E65F8922C22B7FB0082D374 /* UserModel.swift */,
5E65F8942C22C5310082D374 /* UserManager.swift */,
); );
path = User; path = User;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -351,6 +359,7 @@ ...@@ -351,6 +359,7 @@
5EC03E4D2C1155720068A5CB /* CacheTools.swift */, 5EC03E4D2C1155720068A5CB /* CacheTools.swift */,
5EC03E4F2C118A420068A5CB /* AppInfo.swift */, 5EC03E4F2C118A420068A5CB /* AppInfo.swift */,
5E1E66AF2C194337009339F0 /* LayoutTools.swift */, 5E1E66AF2C194337009339F0 /* LayoutTools.swift */,
5E65F8962C22CAF40082D374 /* UserDefaultTools.swift */,
); );
path = Utils; path = Utils;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -543,7 +552,9 @@ ...@@ -543,7 +552,9 @@
5E9A1A2C2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift in Sources */, 5E9A1A2C2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift in Sources */,
5E9A1A3E2C0F043100321AC5 /* RootController.swift in Sources */, 5E9A1A3E2C0F043100321AC5 /* RootController.swift in Sources */,
5E9A1A332C0EF51600321AC5 /* UINavigationItem+GKExtension.swift in Sources */, 5E9A1A332C0EF51600321AC5 /* UINavigationItem+GKExtension.swift in Sources */,
5E65F8952C22C5310082D374 /* UserManager.swift in Sources */,
5E9A1A4A2C0F13BF00321AC5 /* UIColor+Ext.swift in Sources */, 5E9A1A4A2C0F13BF00321AC5 /* UIColor+Ext.swift in Sources */,
5E65F8932C22B7FB0082D374 /* UserModel.swift in Sources */,
5E9A1A362C0EF51600321AC5 /* UIViewController+GKGesture.swift in Sources */, 5E9A1A362C0EF51600321AC5 /* UIViewController+GKGesture.swift in Sources */,
5E6CF00A2C12FAD600BF3CF5 /* TargetController.swift in Sources */, 5E6CF00A2C12FAD600BF3CF5 /* TargetController.swift in Sources */,
5E9A1A4C2C0F144200321AC5 /* ColorTools.swift in Sources */, 5E9A1A4C2C0F144200321AC5 /* ColorTools.swift in Sources */,
...@@ -583,6 +594,7 @@ ...@@ -583,6 +594,7 @@
5E9A1A2E2C0EF51600321AC5 /* GKPushAnimatedTransition.swift in Sources */, 5E9A1A2E2C0EF51600321AC5 /* GKPushAnimatedTransition.swift in Sources */,
5E66B2D72C1BE2ED00590452 /* UIImage+Ext.swift in Sources */, 5E66B2D72C1BE2ED00590452 /* UIImage+Ext.swift in Sources */,
5E9A1A302C0EF51600321AC5 /* UIImage+GKExtension.swift in Sources */, 5E9A1A302C0EF51600321AC5 /* UIImage+GKExtension.swift in Sources */,
5E65F8972C22CAF40082D374 /* UserDefaultTools.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
......
...@@ -9,6 +9,7 @@ import UIKit ...@@ -9,6 +9,7 @@ import UIKit
import AuthenticationServices import AuthenticationServices
class LoginController: BaseController { class LoginController: BaseController {
private var isCodeLogin = true
private var countdownTimer: Timer? private var countdownTimer: Timer?
private var remainingSeconds = 60 private var remainingSeconds = 60
...@@ -320,9 +321,9 @@ class LoginController: BaseController { ...@@ -320,9 +321,9 @@ class LoginController: BaseController {
} }
@objc private func loginMethodChanged(_ sender: UIButton) { @objc private func loginMethodChanged(_ sender: UIButton) {
let isVerificationCodeLogin = sender == verificationCodeButton isCodeLogin = sender == verificationCodeButton
if isVerificationCodeLogin { if isCodeLogin {
verificationCodeButton.isSelected = true verificationCodeButton.isSelected = true
verificationCodeButton.titleLabel?.font = kBoldFontSize(17) verificationCodeButton.titleLabel?.font = kBoldFontSize(17)
passwordLoginButton.titleLabel?.font = kBoldFontSize(16) passwordLoginButton.titleLabel?.font = kBoldFontSize(16)
...@@ -334,17 +335,17 @@ class LoginController: BaseController { ...@@ -334,17 +335,17 @@ class LoginController: BaseController {
passwordLoginButton.isSelected = !verificationCodeButton.isSelected passwordLoginButton.isSelected = !verificationCodeButton.isSelected
// 切换输入框 // 切换输入框
self.phoneNumberField.isHidden = !isVerificationCodeLogin self.phoneNumberField.isHidden = !isCodeLogin
self.verificationCodeField.isHidden = !isVerificationCodeLogin self.verificationCodeField.isHidden = !isCodeLogin
self.getCodeButton.isHidden = !isVerificationCodeLogin self.getCodeButton.isHidden = !isCodeLogin
self.usernameField.isHidden = isVerificationCodeLogin self.usernameField.isHidden = isCodeLogin
self.passwordField.isHidden = isVerificationCodeLogin self.passwordField.isHidden = isCodeLogin
// 切换指示条位置 // 切换指示条位置
UIView.animate(withDuration: 0.3) { UIView.animate(withDuration: 0.3) {
self.indicatorView.snp.remakeConstraints { make in self.indicatorView.snp.remakeConstraints { make in
if isVerificationCodeLogin { if self.isCodeLogin {
make.top.equalTo(self.verificationCodeButton.snp.bottom).offset(-5) make.top.equalTo(self.verificationCodeButton.snp.bottom).offset(-5)
make.size.equalTo(CGSize(width: 60, height: 3)) make.size.equalTo(CGSize(width: 60, height: 3))
make.centerX.equalTo(self.verificationCodeButton) make.centerX.equalTo(self.verificationCodeButton)
...@@ -406,9 +407,55 @@ class LoginController: BaseController { ...@@ -406,9 +407,55 @@ class LoginController: BaseController {
navigationController?.pushViewController(PrivacyController(), animated: true) navigationController?.pushViewController(PrivacyController(), animated: true)
} }
@objc private func loginTapped() { @objc private func loginTapped(_ sender: UIButton) {
dealReadPrivacy() if !agreementCheckBox.isSelected {
agreementCheckBox.shakeAnimation()
return
}
if isCodeLogin {
guard let phoneNumber = phoneNumberField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !phoneNumber.isEmpty else {
view.makeToast("请输入手机号", position: .center)
return
}
guard let veriCode = verificationCodeField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !veriCode.isEmpty else {
view.makeToast("请输入验证码", position: .center)
return
}
view.makeToastActivity(.center)
UserProvider<LoginOrRegisterTarget>.mobileCodeLoginRequest(mobile: phoneNumber, code: veriCode) { logicResult in
self.view.hideToastActivity()
if case .failure(let failure) = logicResult {
self.view.makeToast(failure.localizedDescription, position: .center)
return
}
self.view.makeToast("登录成功", position: .center)
self.dismiss(animated: true)
}
} else {
guard let userName = usernameField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !userName.isEmpty else {
view.makeToast("请输入用户名或手机号", position: .center)
return
}
guard let pwd = passwordField.text?.trimmingCharacters(in: .whitespacesAndNewlines), !pwd.isEmpty else {
view.makeToast("请输入密码", position: .center)
return
}
view.makeToastActivity(.center)
UserProvider<LoginOrRegisterTarget>.pwdLoginRequest(name: userName, pwd: pwd) { logicResult in
self.view.hideToastActivity()
if case .failure(let failure) = logicResult {
self.view.makeToast(failure.localizedDescription, position: .center)
return
}
self.view.makeToast("登录成功", position: .center)
self.dismiss(animated: true)
}
}
} }
@objc private func registerTapped() { @objc private func registerTapped() {
......
...@@ -31,8 +31,10 @@ class ProfileController: BaseController { ...@@ -31,8 +31,10 @@ class ProfileController: BaseController {
extension ProfileController: ProfileViewDelegate { extension ProfileController: ProfileViewDelegate {
func tapHeader() { func tapHeader() {
// navigationController?.pushViewController(UpdateProfileController(), animated: true) if UserManager.shared.isLogged {
navigationController?.pushViewController(UpdateProfileController(), animated: true)
return
}
LoginTools.toLogin(target: self) LoginTools.toLogin(target: self)
} }
...@@ -50,6 +52,15 @@ extension ProfileController: ProfileViewDelegate { ...@@ -50,6 +52,15 @@ extension ProfileController: ProfileViewDelegate {
} }
func tapLogout() { func tapLogout() {
view.makeToastActivity(.center)
UserProvider<LoginOrRegisterTarget>.logoutRequest { logicResult in
self.view.hideToastActivity()
if case .failure(let failure) = logicResult {
self.view.makeToast(failure.localizedDescription, position: .center)
return
}
self.view.makeToast("退出登录成功", position: .center)
}
} }
} }
...@@ -29,7 +29,6 @@ class ProfileView: UIView { ...@@ -29,7 +29,6 @@ class ProfileView: UIView {
let lab = UILabel() let lab = UILabel()
lab.font = kFontSize(18) lab.font = kFontSize(18)
lab.textColor = kWhite lab.textColor = kWhite
lab.text = "chengx"
return lab return lab
}() }()
...@@ -98,6 +97,13 @@ class ProfileView: UIView { ...@@ -98,6 +97,13 @@ class ProfileView: UIView {
super.init(frame: frame) super.init(frame: frame)
setupView() setupView()
UserManager.shared.userModel
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] userModel in
self?.updateView(userModel: userModel)
})
.disposed(by: disposeBag)
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
...@@ -152,6 +158,27 @@ extension ProfileView { ...@@ -152,6 +158,27 @@ extension ProfileView {
make.bottom.equalTo(userIV).offset(-15) make.bottom.equalTo(userIV).offset(-15)
} }
} }
private func updateView(userModel: UserModel?) {
if let model = userModel {
if let mobile = model.usrName, mobile.count == 11 {
let start = mobile.startIndex
let midStart = mobile.index(start, offsetBy: 3)
let midEnd = mobile.index(start, offsetBy: 7)
let maskedMobile = mobile.replacingCharacters(in: midStart..<midEnd, with: "****")
nameLab.text = maskedMobile
} else {
nameLab.text = model.usrName ?? ""
}
userIV.kf.setImage(with: URL(string: UserModel.portraitUrl(code: model.faceImageCode)), placeholder: R.image.default_user())
logoutBtn.isHidden = false
return
}
nameLab.text = "登录/注册"
userIV.image = R.image.default_user()
logoutBtn.isHidden = true
}
} }
extension ProfileView: UITableViewDataSource, UITableViewDelegate { extension ProfileView: UITableViewDataSource, UITableViewDelegate {
......
...@@ -192,6 +192,22 @@ extension RegisterController { ...@@ -192,6 +192,22 @@ extension RegisterController {
view.makeToast("请输入手机号", position: .center) view.makeToast("请输入手机号", position: .center)
return return
} }
view.makeToastActivity(.center)
UserProvider<LoginOrRegisterTarget>.mobileCodeRequest(mobile: phoneNumber) { logicResult in
self.view.hideToastActivity()
if case .failure(let err) = logicResult {
self.view.makeToast(err.localizedDescription, position: .center)
return
}
self.dealCountDown()
}
}
@objc private func dealCountDown() {
getCodeButton.isEnabled = false getCodeButton.isEnabled = false
remainingSeconds = 60 remainingSeconds = 60
...@@ -241,12 +257,22 @@ extension RegisterController { ...@@ -241,12 +257,22 @@ extension RegisterController {
view.makeToast("请输入确认密码", position: .center) view.makeToast("请输入确认密码", position: .center)
return return
} }
if password != confirmPwd {
view.makeToast("2次输入的密码不一致", position: .center)
return
}
view.makeToastActivity(.center) view.makeToastActivity(.center)
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { UserProvider<LoginOrRegisterTarget>.mobileRegisterRequest(mobile: phoneNumber, code: veriCode, pass: password) { logicResult in
self.view.hideToastActivity() self.view.hideToastActivity()
// self.dismiss(animated: true)
if case .failure(let failure) = logicResult {
self.view.makeToast(failure.localizedDescription, position: .center)
return
}
self.view.makeToast("注册成功") self.view.makeToast("注册成功")
self.dismiss(animated: true)
} }
} }
......
//
// UserManager.swift
// AoleiSports
//
// Created by ilCode on 2024/6/19.
//
import Foundation
class UserManager {
static let shared = UserManager()
var isLogged: Bool {
return userModel.value != nil
}
private(set) var userModel = BehaviorRelay<UserModel?>(value: nil)
private init() {
loadUserData()
}
func saveUserData(userModel: UserModel?) {
guard let tmpUserModel = userModel else {
return
}
// 更新 BehaviorRelay
self.userModel.accept(tmpUserModel)
// 保存到 UserDefaults
let userModelJSON = tmpUserModel.toJSON()
if let userData = try? JSONSerialization.data(withJSONObject: userModelJSON) {
Defaults[\.userModelKey] = userData
}
}
func clearUserData() {
self.userModel.accept(nil)
Defaults[\.userModelKey] = nil
}
private func loadUserData() {
if let userData = Defaults[\.userModelKey],
let userModelJSON = try? JSONSerialization.jsonObject(with: userData) as? [String: Any],
let userModel = UserModel(JSON: userModelJSON) {
self.userModel.accept(userModel)
}
}
}
//
// UserModel.swift
// AoleiSports
//
// Created by ilCode on 2024/6/19.
//
import Foundation
struct UserModel: Mappable {
var appToken: String?
var usrName: String?
var mobile: String?
var faceImageCode: String?
init?(map: Map) {
}
mutating func mapping(map: Map) {
appToken <- map["AppToken"]
usrName <- map["Name"]
mobile <- map["Mobile"]
faceImageCode <- map["FaceImageCode"]
}
static func portraitUrl(code: String?) -> String {
if let tmpCode = code, !tmpCode.isEmpty {
return APIs.API_USER + tmpCode + ".jpg"
}
return ""
}
}
...@@ -8,7 +8,16 @@ ...@@ -8,7 +8,16 @@
import UIKit import UIKit
enum LoginOrRegisterTarget: TargetType { enum LoginOrRegisterTarget: TargetType {
case mobileCode(mobile: String) // 手机验证码 // 手机验证码
case mobileCode(mobile: String)
// 手机注册
case mobileRegister(mobile: String, code: String, pass: String)
// 手机验证码登录
case mobileCodeLogin(mobile: String, code: String)
// 密码登录
case pwdLogin(name: String, pwd: String)
// 退出登录
case logout
var task: Moya.Task { var task: Moya.Task {
switch self { switch self {
...@@ -19,6 +28,38 @@ enum LoginOrRegisterTarget: TargetType { ...@@ -19,6 +28,38 @@ enum LoginOrRegisterTarget: TargetType {
} }
"""] """]
return .requestParameters(parameters: parameters, encoding: JSONEncoding.default) return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
case .mobileRegister(let mobile, let code, let pass):
let parameters = ["query": """
mutation{
\(APIs.kMobileRegister)(mobile:"\(mobile)",code:"\(code)",pass:"\(pass)",pass2:"\(pass)")
}
"""]
return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
case .mobileCodeLogin(let mobile, let code):
let parameters = ["query": """
mutation{
\(APIs.kSmsLogin)(mobile:"\(mobile)",code:"\(code)")
}
"""]
return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
case .pwdLogin(let name, let pwd):
let parameters = ["query": """
mutation {
\(APIs.kPwdLogin)(name: "\(name)", pass: "\(pwd)")
}
"""]
return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
case .logout:
let parameters = ["query": """
mutation {
\(APIs.kLogout)
}
"""]
return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
} }
} }
} }
...@@ -29,10 +70,91 @@ class UserProvider<Target: TargetType>: BaseMoyaProvider<Target> { ...@@ -29,10 +70,91 @@ class UserProvider<Target: TargetType>: BaseMoyaProvider<Target> {
let target: LoginOrRegisterTarget = .mobileCode(mobile: mobile) let target: LoginOrRegisterTarget = .mobileCode(mobile: mobile)
moyaPostWithSJ(api: APIs.kMobileCode, target: target) { midResult in moyaPostWithSJ(api: APIs.kMobileCode, target: target) { midResult in
DDLogInfo("midResult:\(midResult)") DDLogInfo("手机验证码请求接口数据:\(midResult)")
switch midResult {
case .success(_):
completion(.success(true))
case .failure(let err):
completion(.failure(err))
}
}
}
// 手机注册请求
static func mobileRegisterRequest(mobile: String, code: String, pass: String, completion: @escaping (Result<Bool, AsError>) -> Void) {
let target: LoginOrRegisterTarget = .mobileRegister(mobile: mobile, code: code, pass: pass)
moyaPost(api: APIs.kMobileRegister, target: target) { midResult in
DDLogInfo("手机注册请求接口数据:\(midResult)")
switch midResult {
case let .success(midSuccessResult):
let appToken = midSuccessResult["AppToken"] as? String
var resultDic = midSuccessResult["Result"] as? [String: Any] ?? [:]
resultDic["AppToken"] = appToken
let userModel = UserModel(JSON: resultDic)
UserManager.shared.saveUserData(userModel: userModel)
completion(.success(true))
case .failure(let err):
completion(.failure(err))
}
}
}
// 手机验证码登录请求
static func mobileCodeLoginRequest(mobile: String, code: String, completion: @escaping (Result<Bool, AsError>) -> Void) {
let target: LoginOrRegisterTarget = .mobileCodeLogin(mobile: mobile, code: code)
moyaPost(api: APIs.kSmsLogin, target: target) { midResult in
DDLogInfo("手机验证码登录请求接口数据:\(midResult)")
switch midResult {
case let .success(midSuccessResult):
let appToken = midSuccessResult["AppToken"] as? String
var resultDic = midSuccessResult["Result"] as? [String: Any] ?? [:]
resultDic["AppToken"] = appToken
let userModel = UserModel(JSON: resultDic)
UserManager.shared.saveUserData(userModel: userModel)
completion(.success(true))
case .failure(let err):
completion(.failure(err))
}
}
}
// 密码登录请求
static func pwdLoginRequest(name: String, pwd: String, completion: @escaping (Result<Bool, AsError>) -> Void) {
let target: LoginOrRegisterTarget = .pwdLogin(name: name, pwd: pwd)
moyaPost(api: APIs.kPwdLogin, target: target) { midResult in
DDLogInfo("密码登录请求接口数据:\(midResult)")
switch midResult {
case let .success(midSuccessResult):
let appToken = midSuccessResult["AppToken"] as? String
var resultDic = midSuccessResult["Result"] as? [String: Any] ?? [:]
resultDic["AppToken"] = appToken
let userModel = UserModel(JSON: resultDic)
UserManager.shared.saveUserData(userModel: userModel)
completion(.success(true))
case .failure(let err):
completion(.failure(err))
}
}
}
// 退出登录请求
static func logoutRequest(completion: @escaping (Result<Bool, AsError>) -> Void) {
moyaPost(api: APIs.kLogout, target: LoginOrRegisterTarget.logout) { midResult in
DDLogInfo("退出登录请求接口数据:\(midResult)")
switch midResult { switch midResult {
case .success(_): case .success(_):
UserManager.shared.clearUserData()
completion(.success(true)) completion(.success(true))
case .failure(let err): case .failure(let err):
completion(.failure(err)) completion(.failure(err))
......
...@@ -16,3 +16,5 @@ ...@@ -16,3 +16,5 @@
@_exported import RxGesture @_exported import RxGesture
@_exported import ObjectMapper @_exported import ObjectMapper
@_exported import ESPullToRefresh @_exported import ESPullToRefresh
@_exported import SwiftyUserDefaults
@_exported import Kingfisher
...@@ -36,7 +36,7 @@ enum AsError: Swift.Error { ...@@ -36,7 +36,7 @@ enum AsError: Swift.Error {
case .parseErr(let message): case .parseErr(let message):
return "parse err: \(message)" return "parse err: \(message)"
case .busErr(let message): case .busErr(let message):
return "busErr err: \(message)" return "busErr: \(message)"
} }
} }
} }
...@@ -145,7 +145,10 @@ class BaseMoyaProvider<Target: TargetType>: MoyaProvider<Target> { ...@@ -145,7 +145,10 @@ class BaseMoyaProvider<Target: TargetType>: MoyaProvider<Target> {
super.init(plugins: [self.basePlugin]) super.init(plugins: [self.basePlugin])
self.initLoading = initLoading self.initLoading = initLoading
} }
}
//MARK: - Moya Post [String: Any]
extension BaseMoyaProvider {
/// Moya Post /// Moya Post
/// - Parameters: /// - Parameters:
/// - api: Api /// - api: Api
...@@ -206,6 +209,66 @@ class BaseMoyaProvider<Target: TargetType>: MoyaProvider<Target> { ...@@ -206,6 +209,66 @@ class BaseMoyaProvider<Target: TargetType>: MoyaProvider<Target> {
/// - Parameters: /// - Parameters:
/// - api: Api /// - api: Api
/// - target: TargetType /// - target: TargetType
/// - completion: completion([String: Any])
static func moyaPost(api: String, target: TargetType, completion: @escaping (Result<[String: Any], AsError>) -> Void) {
let provider = BaseMoyaProvider<Target>()
provider.request(target as! Target) { result in
switch result {
case let .success(response):
do {
guard let json = try JSONSerialization.jsonObject(with: response.data, options: []) as? [String: Any] else {
DDLogError("JSON格式不正确")
completion(.failure(.formatErr("JSON格式不正确")))
break
}
// 解析errors
if let errors = json["errors"] as? [[String: Any]],
let rootErr = errors.first,
let message = rootErr["message"] as? String, !message.isEmpty {
DDLogError("rootErr: \(message)")
completion(.failure(AsError.argsErr(message)))
return
}
// 解析data
guard let data = json["data"] as? [String: Any] else {
DDLogError("data数据错误")
completion(.failure(AsError.resDataErr("data数据错误")))
return
}
// 解析api
guard let apiDic = data["\(api)"] as? [String: Any] else {
DDLogError("\(api)数据错误")
completion(.failure(AsError.resDataErr("\(api)数据错误")))
return
}
// 解析业务Error
if let error = apiDic["Error"] as? String, !error.isEmpty {
DDLogError("api bus err: \(error)")
completion(.failure(AsError.busErr(error)))
} else {
// DDLogInfo("成功:\(apiDic)")
completion(.success(apiDic))
}
} catch {
DDLogError("JSON解析失败:\(error.localizedDescription)")
completion(.failure(.parseErr(error.localizedDescription)))
}
case let .failure(error):
DDLogError("errCode: \(error.errorCode)")
// 应该根据errCode细分错误类型
// completion(.failure(AsError.netErr(error.localizedDescription)))
completion(.failure(AsError.netErr("网络连接失败,请重试")))
}
}
}
}
//MARK: - Moya Post SwiftJSON
extension BaseMoyaProvider {
/// Moya Post
/// - Parameters:
/// - api: Api
/// - target: TargetType
/// - completion: completion(SwiftJSON处理) /// - completion: completion(SwiftJSON处理)
static func moyaPostWithSJ(api: String, target: TargetType, completion: @escaping (Result<[String: JSON], AsError>) -> Void) { static func moyaPostWithSJ(api: String, target: TargetType, completion: @escaping (Result<[String: JSON], AsError>) -> Void) {
let provider = BaseMoyaProvider<Target>() let provider = BaseMoyaProvider<Target>()
......
...@@ -10,9 +10,19 @@ import Foundation ...@@ -10,9 +10,19 @@ import Foundation
struct APIs { struct APIs {
static let SERVER_URL = "https://m.ydn.com/" static let SERVER_URL = "https://m.ydn.com/"
static let API_BASE_URL = SERVER_URL + "graphql" static let API_BASE_URL = SERVER_URL + "graphql"
static let API_USER = "https://img2.ydniu.com/user/"
// 获取验证码 // 获取验证码
static let kMobileCode = "getMobileCode" static let kMobileCode = "getMobileCode"
// 手机注册
static let kMobileRegister = "mobileRegist"
// 手机验证码登录
static let kSmsLogin = "ydn_sms_login"
// 密码登录
static let kPwdLogin = "ydn_login"
// 退出登录
static let kLogout = "ydn_logout"
// 赛事情报列表 // 赛事情报列表
static let kLiveScore = "liveScore" static let kLiveScore = "liveScore"
} }
......
//
// UserDefaultTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/19.
//
import Foundation
extension DefaultsKeys {
var userModelKey: DefaultsKey<Data?> { .init("userModelKey") }
}
...@@ -16,6 +16,8 @@ target 'AoleiSports' do ...@@ -16,6 +16,8 @@ target 'AoleiSports' do
pod 'ObjectMapper', '~> 4.4.2' pod 'ObjectMapper', '~> 4.4.2'
pod 'RxGesture', '~> 4.0.4' pod 'RxGesture', '~> 4.0.4'
pod 'ESPullToRefresh', '~> 2.9.3' pod 'ESPullToRefresh', '~> 2.9.3'
pod 'SwiftyUserDefaults', '~> 5.3.0'
pod 'Kingfisher', '~> 7.12.0'
end end
......
...@@ -4,6 +4,7 @@ PODS: ...@@ -4,6 +4,7 @@ PODS:
- CocoaLumberjack/Swift (3.8.5): - CocoaLumberjack/Swift (3.8.5):
- CocoaLumberjack/Core - CocoaLumberjack/Core
- ESPullToRefresh (2.9.3) - ESPullToRefresh (2.9.3)
- Kingfisher (7.12.0)
- Moya/Core (15.0.0): - Moya/Core (15.0.0):
- Alamofire (~> 5.0) - Alamofire (~> 5.0)
- Moya/RxSwift (15.0.0): - Moya/RxSwift (15.0.0):
...@@ -25,12 +26,14 @@ PODS: ...@@ -25,12 +26,14 @@ PODS:
- RxSwift (6.7.1) - RxSwift (6.7.1)
- SnapKit (5.7.1) - SnapKit (5.7.1)
- SwiftyJSON (5.0.2) - SwiftyJSON (5.0.2)
- SwiftyUserDefaults (5.3.0)
- Toast-Swift (5.1.1) - Toast-Swift (5.1.1)
DEPENDENCIES: DEPENDENCIES:
- Alamofire (~> 5.9.1) - Alamofire (~> 5.9.1)
- CocoaLumberjack/Swift - CocoaLumberjack/Swift
- ESPullToRefresh (~> 2.9.3) - ESPullToRefresh (~> 2.9.3)
- Kingfisher (~> 7.12.0)
- Moya/RxSwift (~> 15.0) - Moya/RxSwift (~> 15.0)
- NVActivityIndicatorView (~> 5.2.0) - NVActivityIndicatorView (~> 5.2.0)
- ObjectMapper (~> 4.4.2) - ObjectMapper (~> 4.4.2)
...@@ -40,6 +43,7 @@ DEPENDENCIES: ...@@ -40,6 +43,7 @@ DEPENDENCIES:
- RxSwift (~> 6.7.1) - RxSwift (~> 6.7.1)
- SnapKit (~> 5.7.1) - SnapKit (~> 5.7.1)
- SwiftyJSON (~> 5.0.2) - SwiftyJSON (~> 5.0.2)
- SwiftyUserDefaults (~> 5.3.0)
- Toast-Swift (~> 5.1.1) - Toast-Swift (~> 5.1.1)
SPEC REPOS: SPEC REPOS:
...@@ -47,6 +51,7 @@ SPEC REPOS: ...@@ -47,6 +51,7 @@ SPEC REPOS:
- Alamofire - Alamofire
- CocoaLumberjack - CocoaLumberjack
- ESPullToRefresh - ESPullToRefresh
- Kingfisher
- Moya - Moya
- NVActivityIndicatorView - NVActivityIndicatorView
- ObjectMapper - ObjectMapper
...@@ -57,12 +62,14 @@ SPEC REPOS: ...@@ -57,12 +62,14 @@ SPEC REPOS:
- RxSwift - RxSwift
- SnapKit - SnapKit
- SwiftyJSON - SwiftyJSON
- SwiftyUserDefaults
- Toast-Swift - Toast-Swift
SPEC CHECKSUMS: SPEC CHECKSUMS:
Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0 CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0
ESPullToRefresh: 0d68daa602b343c81753a1b95e09fd0bfcddfd40 ESPullToRefresh: 0d68daa602b343c81753a1b95e09fd0bfcddfd40
Kingfisher: 53a10ea35051a436b5fb626ca2dd8f3144d755e9
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
NVActivityIndicatorView: fe52a6a68664c2df8991d7d9e3d86d8d19453c53 NVActivityIndicatorView: fe52a6a68664c2df8991d7d9e3d86d8d19453c53
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677 ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
...@@ -73,8 +80,9 @@ SPEC CHECKSUMS: ...@@ -73,8 +80,9 @@ SPEC CHECKSUMS:
RxSwift: b9a93a26031785159e11abd40d1a55bcb8057e52 RxSwift: b9a93a26031785159e11abd40d1a55bcb8057e52
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
SwiftyJSON: f5b1bf1cd8dd53cd25887ac0eabcfd92301c6a5a SwiftyJSON: f5b1bf1cd8dd53cd25887ac0eabcfd92301c6a5a
SwiftyUserDefaults: 63f80248cf5bfb3458825d9a78f2eb7e1293a040
Toast-Swift: 7a03a532afe3a560d4044bc7c237e2864d295173 Toast-Swift: 7a03a532afe3a560d4044bc7c237e2864d295173
PODFILE CHECKSUM: aaab2dc38f3bdf57b45edf6252d34b03cda60517 PODFILE CHECKSUM: e0240e4c63b8761b0e735050fb2e59981354c37b
COCOAPODS: 1.15.2 COCOAPODS: 1.15.2
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!