diff --git a/yinmeng-ios.xcodeproj/project.pbxproj b/yinmeng-ios.xcodeproj/project.pbxproj index 00c6ef6..4c1f017 100644 --- a/yinmeng-ios.xcodeproj/project.pbxproj +++ b/yinmeng-ios.xcodeproj/project.pbxproj @@ -42,6 +42,8 @@ E8D15AB32B8B000400369467 /* PlanetStarVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15AB22B8B000400369467 /* PlanetStarVC.swift */; }; E8D15AB62B8B002700369467 /* ChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15AB52B8B002700369467 /* ChatVC.swift */; }; E8D15AB82B8B003C00369467 /* UserInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15AB72B8B003C00369467 /* UserInfoVC.swift */; }; + E8D15ABC2B8B87BA00369467 /* UserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15ABB2B8B87BA00369467 /* UserViewModel.swift */; }; + E8D15ABF2B8B885700369467 /* UserObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D15ABE2B8B885700369467 /* UserObject.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -87,6 +89,8 @@ E8D15AB22B8B000400369467 /* PlanetStarVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlanetStarVC.swift; sourceTree = ""; }; E8D15AB52B8B002700369467 /* ChatVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatVC.swift; sourceTree = ""; }; E8D15AB72B8B003C00369467 /* UserInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoVC.swift; sourceTree = ""; }; + E8D15ABB2B8B87BA00369467 /* UserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserViewModel.swift; sourceTree = ""; }; + E8D15ABE2B8B885700369467 /* UserObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserObject.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -332,11 +336,21 @@ E8D15AB92B8B004000369467 /* User */ = { isa = PBXGroup; children = ( + E8D15ABA2B8B87A900369467 /* VM */, E8D15AB72B8B003C00369467 /* UserInfoVC.swift */, ); path = User; sourceTree = ""; }; + E8D15ABA2B8B87A900369467 /* VM */ = { + isa = PBXGroup; + children = ( + E8D15ABB2B8B87BA00369467 /* UserViewModel.swift */, + E8D15ABE2B8B885700369467 /* UserObject.swift */, + ); + path = VM; + sourceTree = ""; + }; E8EE60802B8858A500D02F6E /* Security */ = { isa = PBXGroup; children = ( @@ -488,8 +502,10 @@ E86A43C62B862CC70084C04D /* UIImage+.swift in Sources */, E86A43D32B8773C90084C04D /* APPUtils.swift in Sources */, E86A43CB2B874C6F0084C04D /* AuthPrivacyView.swift in Sources */, + E8D15ABF2B8B885700369467 /* UserObject.swift in Sources */, E86A43BF2B8620C40084C04D /* Utils.swift in Sources */, E86A43BA2B85F1360084C04D /* AuthLoginVC.swift in Sources */, + E8D15ABC2B8B87BA00369467 /* UserViewModel.swift in Sources */, E81A7BAF2B885B20009E736E /* MAIDESEncryptTool.m in Sources */, E8D15AA82B89B74700369467 /* YMRequestX.swift in Sources */, E8D15AB02B8AFFCE00369467 /* HomeVoiceVC.swift in Sources */, diff --git a/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/UserInterfaceState.xcuserstate b/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/UserInterfaceState.xcuserstate index 72338a8..27502f0 100644 Binary files a/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/UserInterfaceState.xcuserstate and b/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 8499e8c..bf541d3 100644 --- a/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/yinmeng-ios.xcworkspace/xcuserdata/fengshuo.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -36,21 +36,5 @@ landmarkType = "7"> - - - - diff --git a/yinmeng-ios/AppDelegate.swift b/yinmeng-ios/AppDelegate.swift index c4694b0..d7b1cb2 100644 --- a/yinmeng-ios/AppDelegate.swift +++ b/yinmeng-ios/AppDelegate.swift @@ -23,22 +23,23 @@ var window: UIWindow? } private func loginStateListener() { + AuthViewModel.authVM.appClientConfig() + ///检车是否已经登录 + AuthViewModel.authVM.checkUserIsLogin() AuthViewModel.authVM.loginSuccess.subscribe(onNext: { result in print("是否登录成功\(result)") if result == true { ///如果登录成功显示tabbar - self.window = UIWindow.init(frame: UIScreen.main.bounds) - self.window?.backgroundColor = UIColor.white self.window?.rootViewController = BaseTabBarViewController() + if let uid = LoginTokenConfig.config.getAccountInfo()?.uid { + UserViewModel.userVM.getUserInfo(uid: uid) + } } else { ///去登录 - self.window = UIWindow.init(frame: UIScreen.main.bounds) - self.window?.backgroundColor = UIColor.white self.window?.rootViewController = BaseNavigationViewController(rootViewController:AuthLoginVC()) } }).disposed(by: rx.disposeBag) - ///检车是否已经登录 - AuthViewModel.authVM.checkUserIsLogin() + } diff --git a/yinmeng-ios/Modules/Auth/VC/AuthForgetVC.swift b/yinmeng-ios/Modules/Auth/VC/AuthForgetVC.swift index d7423cb..52320da 100644 --- a/yinmeng-ios/Modules/Auth/VC/AuthForgetVC.swift +++ b/yinmeng-ios/Modules/Auth/VC/AuthForgetVC.swift @@ -8,9 +8,28 @@ import UIKit class AuthForgetVC: BaseViewController, HiddenNavigationBarProtocol { + var countdownSeconds = 60 + var timer: Timer? + var viewModel:AuthViewModel = AuthViewModel() + var phone:String = "" + var code:String = "" + var password:String = "" override func viewDidLoad() { super.viewDidLoad() loadSubViews() + viewModel.resetPwd.subscribe(onNext: { success in + if success { + HUDTool.show(with: "重置密码成功") + self.navigationController?.popViewController(animated: true) + } + }).disposed(by: rx.disposeBag) + + viewModel.data.subscribe(onNext: { [weak self] success in + if success { + HUDTool.show(with: "验证码已发送\n+86\(self?.phone ?? "")") + self?.startCountdown() + } + }).disposed(by: rx.disposeBag) } private func loadSubViews() { @@ -170,6 +189,7 @@ class AuthForgetVC: BaseViewController, HiddenNavigationBarProtocol { let view = UITextField() view.textColor = .firstText view.font = UIFont.systemFont(ofSize: 16) + view.isSecureTextEntry = true view.leftViewMode = .always let leftView = UIView() leftView.frame = CGRect(x: 0, y: 0, width: 20, height: 52) @@ -200,22 +220,88 @@ class AuthForgetVC: BaseViewController, HiddenNavigationBarProtocol { } @objc func phoneTextFiledDidChange(_ textField: UITextField) { - + if let text = textField.text { + if text.count > 11 { + textField.text = text.substring(start: 0, 11) + } + } + phone = textField.text ?? "" } @objc func pwdTextFiledDidChange(_ textField: UITextField) { - + if let text = textField.text { + if text.count > 16 { + textField.text = text.substring(start: 0, 16) + } + } + password = textField.text ?? "" } @objc func codeTextFiledDidChange(_ textField: UITextField) { - + if let text = textField.text { + if text.count > 5 { + textField.text = text.substring(start: 0, 5) + } + } + code = textField.text ?? "" } @objc func getCodeBtnAction() { - + if phone.count > 0 { + viewModel.getSmsCode(phone: phone, type: 3) + } else { + HUDTool.show(with: "请输入正确的手机号码") + } } @objc func confirmBtnAction() { - + if phone.count > 0 { + if code.count > 0 { + if password.count > 0 { + viewModel.resetPassword(phone: phone, newPwd: password, smsCode: code) + } else { + HUDTool.show(with: "请设置密码") + } + } else { + HUDTool.show(with: "请输入验证码") + } + } else { + HUDTool.show(with: "请输入正确的手机号") + } } } + +extension AuthForgetVC { + + func startCountdown() { + if timer != nil { + timer?.invalidate() + timer = nil + } + countdownSeconds = 60 + timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true) + timer!.fire() + } + + @objc func updateCountdown() { + countdownSeconds -= 1 + + if countdownSeconds <= 0 { + getCodeBtn.setTitle("获取验证码", for: .normal) + getCodeBtn.isEnabled = true + stopCountdown() + return + } + getCodeBtn.isHidden = false + let seconds = countdownSeconds % 60 + getCodeBtn.setTitle("\(seconds)s后重试", for: .disabled) + getCodeBtn.isEnabled = false + } + + func stopCountdown() { + timer?.invalidate() + timer = nil + } +} + + diff --git a/yinmeng-ios/Modules/Auth/VC/AuthLoginVC.swift b/yinmeng-ios/Modules/Auth/VC/AuthLoginVC.swift index 99dc88b..1f649b4 100644 --- a/yinmeng-ios/Modules/Auth/VC/AuthLoginVC.swift +++ b/yinmeng-ios/Modules/Auth/VC/AuthLoginVC.swift @@ -12,9 +12,11 @@ import NSObject_Rx class AuthLoginVC: BaseViewController, HiddenNavigationBarProtocol { var countdownSeconds = 60 var timer: Timer? - var viewModel:AuthViewModel = AuthViewModel() + var viewModel:AuthViewModel = AuthViewModel.authVM var phone:String = "" var code:String = "" + var id:String = "" + var password:String = "" override func viewDidLoad() { super.viewDidLoad() @@ -279,6 +281,7 @@ class AuthLoginVC: BaseViewController, HiddenNavigationBarProtocol { let button = UIButton(type: .custom) button.setTitle("获取验证码", for: .normal) button.setTitleColor(ThemeColor(hexStr: "#9552FF"), for: .normal) + button.setTitleColor(ThemeColor(hexStr: "#878B9C"), for: .disabled) button.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .regular) button.addTarget(self, action: #selector(getCodeBtnAction), for: .touchUpInside) return button @@ -326,8 +329,8 @@ class AuthLoginVC: BaseViewController, HiddenNavigationBarProtocol { view.font = UIFont.systemFont(ofSize: 16) let attribute = NSMutableAttributedString(string: "请输入密码", attributes: [NSAttributedString.Key.font:UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.placeholderText]) view.attributedPlaceholder = attribute - view.keyboardType = .numberPad view.tintColor = ThemeColor(hexStr: "#282828") + view.isSecureTextEntry = true view.addTarget(self, action: #selector(pwdTextFiledDidChange), for: .editingChanged) return view }() @@ -396,14 +399,30 @@ extension AuthLoginVC { @objc func confirmBtnAction() { if self.phoneLoginBtn.isSelected == true { - viewModel.authPhoneCode(phone: phone, code: code) + if phone.count > 0 { + if code.count > 0 { + viewModel.authPhoneCode(phone: phone, code: code) + } else { + HUDTool.show(with: "请输入验证码") + } + } else { + HUDTool.show(with: "请输入正确的手机号") + } } else { - //TODO: id登录 + if id.count > 0 { + if password.count > 0 { + viewModel.authIDPassword(account: id, password: password) + } else { + HUDTool.show(with: "请输入密码") + } + } else { + HUDTool.show(with: "请输入账号") + } } } @objc func forgetBtnAction() { - self.navigationController?.pushViewController(AuthFillDataVC(), animated: true) + self.navigationController?.pushViewController(AuthForgetVC(), animated: true) } @objc func phoneTextFiledDidChange(_ textField: UITextField) { @@ -425,11 +444,21 @@ extension AuthLoginVC { } @objc func idTextFiledDidChange(_ textField: UITextField) { - + if let text = textField.text { + if text.count > 11 { + textField.text = text.substring(start: 0, 11) + } + } + id = textField.text ?? "" } @objc func pwdTextFiledDidChange(_ textField: UITextField) { - + if let text = textField.text { + if text.count > 16 { + textField.text = text.substring(start: 0, 16) + } + } + password = textField.text ?? "" } } @@ -450,14 +479,14 @@ extension AuthLoginVC { countdownSeconds -= 1 if countdownSeconds <= 0 { - getCodeBtn.setTitle("重新获取验证码", for: .normal) + getCodeBtn.setTitle("获取验证码", for: .normal) getCodeBtn.isEnabled = true stopCountdown() return } getCodeBtn.isHidden = false let seconds = countdownSeconds % 60 - getCodeBtn.setTitle("重新获取验证码(\(seconds)s)", for: .disabled) + getCodeBtn.setTitle("\(seconds)s", for: .disabled) getCodeBtn.isEnabled = false } diff --git a/yinmeng-ios/Modules/Auth/VM/AuthViewModel.swift b/yinmeng-ios/Modules/Auth/VM/AuthViewModel.swift index a132277..6d6cf8f 100644 --- a/yinmeng-ios/Modules/Auth/VM/AuthViewModel.swift +++ b/yinmeng-ios/Modules/Auth/VM/AuthViewModel.swift @@ -11,8 +11,18 @@ class AuthViewModel: NSObject { static let authVM = AuthViewModel.init() let data = PublishSubject() let token = PublishSubject() - let loginSuccess = PublishSubject() + let loginSuccess = BehaviorSubject(value: false) + let resetPwd = PublishSubject() + func appClientConfig() { + RequestGet(path: "client/init", parma: [:]) { data in + + } fail: { code, message in + + } + } + + ///获取验证码 func getSmsCode(phone:String, type:Int) { if let phoneDes = phone.encrypt() { let params:[String: Any] = ["mobile":phoneDes, "type":type] @@ -24,6 +34,7 @@ class AuthViewModel: NSObject { } } + ///账号密码登录 func authPhoneCode(phone:String, code:String) { if let phoneDes = phone.encrypt() { let params = ["phone":phoneDes, "code":code, "client_secret":"uyzjdhds", "version":"1", "client_id":"erban-client", "grant_type":"password"] @@ -45,6 +56,28 @@ class AuthViewModel: NSObject { } } + ///ID登录 + func authIDPassword(account:String, password: String) { + if let phoneDes = account.encrypt(), let pwdDes = password.encrypt() { + let params = ["phone":phoneDes, "password":pwdDes, "client_secret":"uyzjdhds", "version":"1", "client_id":"erban-client", "grant_type":"password"] + RequestPost(path: "oauth/token", parma: params) { data in + if let account = Deserialized.toModel(with: data) { + LoginTokenConfig.config.saveTokenToLocaltion(token: account) + self.token.onNext(account) + self.token.onCompleted() + ///进行token的置换 + if let accessToken = account.access_token { + self.tokenTransformTicket(accesToken: accessToken) + } + } + } fail: { code, data in + self.token.onNext(nil) + self.token.onCompleted() + } + + } + } + ///通过token获取ticket func tokenTransformTicket(accesToken:String) { let params = ["access_token": accesToken, "issue_type": "multi"] @@ -53,11 +86,26 @@ class AuthViewModel: NSObject { if let dic = data as? [String: Any], let tickets = dic["tickets"] as? [[String: Any]], let ticket1 = tickets[safe: 0], let ticket = ticket1["ticket"] as? String{ LoginTokenConfig.config.saveTicketToLoaction(ticket: ticket) self.loginSuccess.onNext(true) + self.loginSuccess.onCompleted() } else { self.loginSuccess.onNext(false) + self.loginSuccess.onCompleted() } } fail: { code, message in self.loginSuccess.onNext(false) + self.loginSuccess.onCompleted() + } + } + + ///充值密码 + func resetPassword(phone:String, newPwd:String, smsCode:String) { + if let phoneDes = phone.encrypt(), let pwdDes = newPwd.encrypt() { + let params = ["phone":phoneDes, "newPwd":pwdDes, "smsCode": smsCode] + RequestPost(path: "acc/pwd/reset", parma: params) { data in + self.resetPwd.onNext(true) + } fail: { code, message in + self.resetPwd.onNext(false) + } } } diff --git a/yinmeng-ios/Modules/User/VM/UserObject.swift b/yinmeng-ios/Modules/User/VM/UserObject.swift new file mode 100644 index 0000000..09f6be0 --- /dev/null +++ b/yinmeng-ios/Modules/User/VM/UserObject.swift @@ -0,0 +1,21 @@ +// +// UserObject.swift +// yinmeng-ios +// +// Created by MaiMang on 2024/2/25. +// + +import Foundation + +struct UserObject: HandyJSON { + var uid:Int? = 0 + var erbanNo:Int? = 0 + var avatar:String? = "" + var nick:String? = "" + var gender:GenderEnum? = .male +} + +enum GenderEnum:Int,HandyJSONEnum { + case male = 1 + case female = 2 +} diff --git a/yinmeng-ios/Modules/User/VM/UserViewModel.swift b/yinmeng-ios/Modules/User/VM/UserViewModel.swift new file mode 100644 index 0000000..0f9eef4 --- /dev/null +++ b/yinmeng-ios/Modules/User/VM/UserViewModel.swift @@ -0,0 +1,23 @@ +// +// UserViewModel.swift +// yinmeng-ios +// +// Created by MaiMang on 2024/2/25. +// + +import Foundation + +class UserViewModel: NSObject { + static let userVM = UserViewModel.init() + + func getUserInfo(uid:Int) { + let params = ["uid":uid] + RequestGet(path: "user/get", parma: params) { data in + if let info = Deserialized.toModel(with: data) { + print("用户信息是") + } + } fail: { code, message in + + } + } +}