From 586eb879891e852e50302206470149766c35ee08 Mon Sep 17 00:00:00 2001 From: 杨锴 <841720330@qq.com> Date: 星期四, 05 九月 2024 15:07:57 +0800 Subject: [PATCH] fix API Login --- XQMuse/Assets.xcassets/Icons/icon_fail.imageset/Contents.json | 22 ++ XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift | 31 ++ XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@3x.png | 0 XQMuse/Root/Login/VC/LoginTreatyVC.swift | 27 ++ XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@2x.png | 0 XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@3x.png | 0 XQMuse.xcodeproj/project.pbxproj | 20 ++ XQMuse/Root/Network/Models.swift | 39 +++ XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift | 34 ++ XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@3x.png | 0 XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/Contents.json | 22 ++ XQMuse/Root/Login/VC/RegisterVC.swift | 41 +++- XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@2x.png | 0 XQMuse/Root/Login/VC/ForgotPasswordVC.swift | 3 XQMuse/Root/Login/VC/ForgotPasswordChangeVC.xib | 6 XQMuse/Root/Network/NetworkRequest.swift | 45 ++-- XQMuse/Root/Other/WebVC.swift | 29 ++ XQMuse/SceneDelegate.swift | 18 - XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@2x.png | 0 XQMuse/Assets.xcassets/Icons/icon_code.imageset/Contents.json | 22 ++ XQMuse/Root/Login/LoginVC.swift | 54 ++++- XQMuse/Root/Network/ViewModels/UserViewModel.swift | 42 ++++ XQMuse/Root/Login/LoginVC.xib | 6 XQMuse/Root/Login/VC/RegisterVC.xib | 4 XQMuse/Root/Login/View/Popup_1_View.swift | 6 XQMuse/Config/Types.swift | 39 +++ XQMuse/Root/Network/Services.swift | 75 ++++++ 27 files changed, 497 insertions(+), 88 deletions(-) diff --git a/XQMuse.xcodeproj/project.pbxproj b/XQMuse.xcodeproj/project.pbxproj index 3bc79c6..a7ea68d 100644 --- a/XQMuse.xcodeproj/project.pbxproj +++ b/XQMuse.xcodeproj/project.pbxproj @@ -85,6 +85,9 @@ 134A453A2C6E167D00538D78 /* CourseOfficalCommendTopCCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 134A45382C6E167D00538D78 /* CourseOfficalCommendTopCCell.xib */; }; 134CC7E02C73283700EAEFB7 /* PavilionSearchVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 134CC7DF2C73283700EAEFB7 /* PavilionSearchVC.xib */; }; 134CC7E12C73283700EAEFB7 /* PavilionSearchVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134CC7DE2C73283700EAEFB7 /* PavilionSearchVC.swift */; }; + 135B1D202C8863D10089A9BE /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135B1D1F2C8863D10089A9BE /* Types.swift */; }; + 135B1D222C8868170089A9BE /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135B1D212C8868170089A9BE /* Models.swift */; }; + 135B1D252C8947630089A9BE /* UserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135B1D242C8947630089A9BE /* UserViewModel.swift */; }; 135C2A502C7EC48D00CC2A67 /* apngb-animated_sun.png in Resources */ = {isa = PBXBuildFile; fileRef = 135C2A4F2C7EC48D00CC2A67 /* apngb-animated_sun.png */; }; 135C2A652C7F033300CC2A67 /* CLAnimationTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135C2A512C7F033300CC2A67 /* CLAnimationTransitioning.swift */; }; 135C2A662C7F033300CC2A67 /* CLFullScreenController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135C2A522C7F033300CC2A67 /* CLFullScreenController.swift */; }; @@ -334,6 +337,9 @@ 134A45382C6E167D00538D78 /* CourseOfficalCommendTopCCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CourseOfficalCommendTopCCell.xib; sourceTree = "<group>"; }; 134CC7DE2C73283700EAEFB7 /* PavilionSearchVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PavilionSearchVC.swift; sourceTree = "<group>"; }; 134CC7DF2C73283700EAEFB7 /* PavilionSearchVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PavilionSearchVC.xib; sourceTree = "<group>"; }; + 135B1D1F2C8863D10089A9BE /* Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; }; + 135B1D212C8868170089A9BE /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Models.swift; sourceTree = "<group>"; }; + 135B1D242C8947630089A9BE /* UserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserViewModel.swift; sourceTree = "<group>"; }; 135C2A4F2C7EC48D00CC2A67 /* apngb-animated_sun.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "apngb-animated_sun.png"; sourceTree = "<group>"; }; 135C2A512C7F033300CC2A67 /* CLAnimationTransitioning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLAnimationTransitioning.swift; sourceTree = "<group>"; }; 135C2A522C7F033300CC2A67 /* CLFullScreenController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLFullScreenController.swift; sourceTree = "<group>"; }; @@ -641,6 +647,14 @@ path = VC; sourceTree = "<group>"; }; + 135B1D232C8947570089A9BE /* ViewModels */ = { + isa = PBXGroup; + children = ( + 135B1D242C8947630089A9BE /* UserViewModel.swift */, + ); + path = ViewModels; + sourceTree = "<group>"; + }; 135C2A552C7F033300CC2A67 /* CLFullScreenController */ = { isa = PBXGroup; children = ( @@ -790,8 +804,10 @@ 1385DFFF2C6C4F1200AADB1F /* Network */ = { isa = PBXGroup; children = ( + 135B1D232C8947570089A9BE /* ViewModels */, 1385DFFB2C6C4F1200AADB1F /* NetworkRequest.swift */, 1385DFFD2C6C4F1200AADB1F /* Services.swift */, + 135B1D212C8868170089A9BE /* Models.swift */, ); path = Network; sourceTree = "<group>"; @@ -871,6 +887,7 @@ 13985DB42C69B7DF0046B6DC /* Def.swift */, 13985DB72C69B80D0046B6DC /* Themes.swift */, 13897D882C7DB9D7006209E0 /* EqualCellSpaceFlowLayout.swift */, + 135B1D1F2C8863D10089A9BE /* Types.swift */, ); path = Config; sourceTree = "<group>"; @@ -1333,6 +1350,8 @@ 13FB6D872C6EF9DE00A0685D /* CourseDetialVC.swift in Sources */, 135C2A652C7F033300CC2A67 /* CLAnimationTransitioning.swift in Sources */, 132DB8FE2C74826D00EF33A7 /* SettingVC.swift in Sources */, + 135B1D222C8868170089A9BE /* Models.swift in Sources */, + 135B1D202C8863D10089A9BE /* Types.swift in Sources */, 135C2A662C7F033300CC2A67 /* CLFullScreenController.swift in Sources */, 138F0C352C7597CA0072A16C /* HelpCenterVC.swift in Sources */, 13D256B42C6C68E7006FC2D7 /* ShareView.swift in Sources */, @@ -1453,6 +1472,7 @@ 135C2A752C7F033300CC2A67 /* CLPlayerView.swift in Sources */, 1300BD3C2C6DFB1C000BCA5E /* VIPCenterVC.swift in Sources */, 134803D62C76E3E000F4FDDA /* WatchHistoryVC.swift in Sources */, + 135B1D252C8947630089A9BE /* UserViewModel.swift in Sources */, 1377B4162C6DCC4300CF7CA5 /* Home_Style_4_Inner_1_CCell.swift in Sources */, 135C2A6D2C7F033300CC2A67 /* CLRotateAnimationView.swift in Sources */, 13E160212C6CB8930027F781 /* CommentListVC.swift in Sources */, diff --git a/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/Contents.json b/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/Contents.json new file mode 100644 index 0000000..65bdc39 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "btn_eye_close@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "btn_eye_close@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@2x.png b/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@2x.png new file mode 100644 index 0000000..6036b3d --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@2x.png Binary files differ diff --git a/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@3x.png b/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@3x.png new file mode 100644 index 0000000..7c825d8 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/btn_eye_close.imageset/btn_eye_close@3x.png Binary files differ diff --git a/XQMuse/Assets.xcassets/Icons/icon_code.imageset/Contents.json b/XQMuse/Assets.xcassets/Icons/icon_code.imageset/Contents.json new file mode 100644 index 0000000..3f3a6e2 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/icon_code.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_code@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_code@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@2x.png b/XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@2x.png new file mode 100644 index 0000000..d2679d1 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@2x.png Binary files differ diff --git a/XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@3x.png b/XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@3x.png new file mode 100644 index 0000000..b337aa1 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/icon_code.imageset/icon_code@3x.png Binary files differ diff --git a/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/Contents.json b/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/Contents.json new file mode 100644 index 0000000..6569847 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_fail@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_fail@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@2x.png b/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@2x.png new file mode 100644 index 0000000..2cd6f15 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@2x.png Binary files differ diff --git a/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@3x.png b/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@3x.png new file mode 100644 index 0000000..15ee252 --- /dev/null +++ b/XQMuse/Assets.xcassets/Icons/icon_fail.imageset/icon_fail@3x.png Binary files differ diff --git a/XQMuse/Config/Types.swift b/XQMuse/Config/Types.swift new file mode 100644 index 0000000..8a58405 --- /dev/null +++ b/XQMuse/Config/Types.swift @@ -0,0 +1,39 @@ +// +// Types.swift +// XQMuse +// +// Created by 无故事王国 on 2024/9/4. +// + +import Foundation +import HandyJSON + +enum LoginType{ + case pwd,code +} + +enum AgreementType:Int,HandyJSONEnum{ + case none = 0 + ///用户协议 + case user = 1 + ///隐私协议 + case privacy = 2 + /// 关于我们 + case aboutUs = 3 + /// 新手指南 + case guide = 4 + /// 课程/冥想 + case course = 5 +} + + +enum SendCodeType:Int,HandyJSONEnum{ + //注册 + case register = 1 + ///验证码登录 + case codeLogin = 2 + ///找回密码 + case forgetPwd = 3 + ///第三方登录后验证手机 + case threePlantform = 4 +} diff --git a/XQMuse/Root/Login/LoginVC.swift b/XQMuse/Root/Login/LoginVC.swift index a51511b..c98775f 100644 --- a/XQMuse/Root/Login/LoginVC.swift +++ b/XQMuse/Root/Login/LoginVC.swift @@ -12,10 +12,6 @@ class LoginViewModel{ - enum LoginType{ - case pwd,code - } - var loginType = BehaviorRelay<LoginType>(value:.pwd) var loginPhone = BehaviorRelay<String>(value:"") var loginContent = BehaviorRelay<String>(value:"") @@ -57,6 +53,7 @@ @IBOutlet weak var btn_register: UIButton! @IBOutlet weak var btn_login: UIButton! @IBOutlet weak var btn_sendCode: UIButton! + @IBOutlet weak var btn_isRead: UIButton! private var viewModel = LoginViewModel() @@ -113,6 +110,7 @@ } override func setUI() { + btn_eye.isSelected = true view.addSubview(unlineImageView) unlineImageView.snp.makeConstraints { make in make.top.equalTo(self.btn_loginByPwd.snp.bottom).offset(6) @@ -129,40 +127,74 @@ @IBAction func loginTypeAction(_ sender: UIButton) { sender.tag == 10 ? viewModel.loginType.accept(.pwd):viewModel.loginType.accept(.code) + + switch viewModel.loginType.value{ + case .code: + tf_content.isSecureTextEntry = false + case .pwd: + tf_content.isSecureTextEntry = btn_eye.isSelected + } } @IBAction func eyeAction(_ sender: UIButton) { sender.isSelected = !sender.isSelected + tf_content.isSecureTextEntry = sender.isSelected } + + @IBAction func isReadAction(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + } + @IBAction func sendCodeAction(_ sender: UIButton) { guard !viewModel.loginPhone.value.isEmpty else {alert(msg: "请输入手机号");return} guard viewModel.loginPhone.value.jq_isPhone else {alert(msg: "请输入正确手机号");return} - sender.jq_openCountDown(60, defultTitle: "发送验证码") { - sender.titleLabel?.font = UIFont.systemFont(ofSize: 12) - sender.setTitleColor(.black.withAlphaComponent(0.3), for: .normal) - } completeClouse: { - sender.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium) - sender.setTitleColor(UIColor(hexStr: "#96AD81"), for: .normal) - } + Services.sendCode(type: .codeLogin).subscribe(onNext: {data in + if let _ = data.data{ + sender.jq_openCountDown(60, defultTitle: "发送验证码") { + sender.titleLabel?.font = UIFont.systemFont(ofSize: 12) + sender.setTitleColor(.black.withAlphaComponent(0.3), for: .normal) + } completeClouse: { + sender.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium) + sender.setTitleColor(UIColor(hexStr: "#96AD81"), for: .normal) + } + } + }).disposed(by: disposeBag) } @IBAction func loginAction(_ sender: UIButton) { guard viewModel.checkSafe() else {return} + guard btn_isRead.isSelected else { + alertError(msg: "请阅读并同意《用户注册协议》和《用户隐私协议》");return + } + Services.loginBy(phone: viewModel.loginPhone.value, content: viewModel.loginContent.value, type: viewModel.loginType.value).subscribe(onNext: { data in + if let model = data.data{ + UserViewModel.saveUserInfo(model) + sceneDelegate?.loginSuccess() + } + }).disposed(by: disposeBag) } @IBAction func userRegisterTreatyAction(_ sender: UIButton) { let vc = LoginTreatyVC() + vc.topIndex = 0 + vc.clickHandle {[unowned self] state in + self.btn_isRead.isSelected = state + } vc.modalPresentationStyle = .custom present(vc, animated: true) } @IBAction func userPrivateTreatyAction(_ sender: UIButton) { let vc = LoginTreatyVC() + vc.topIndex = 1 + vc.clickHandle {[unowned self] state in + self.btn_isRead.isSelected = state + } vc.modalPresentationStyle = .custom present(vc, animated: true) } diff --git a/XQMuse/Root/Login/LoginVC.xib b/XQMuse/Root/Login/LoginVC.xib index 3e57974..15a5f29 100644 --- a/XQMuse/Root/Login/LoginVC.xib +++ b/XQMuse/Root/Login/LoginVC.xib @@ -11,6 +11,7 @@ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="LoginVC" customModule="XQMuse" customModuleProvider="target"> <connections> <outlet property="btn_eye" destination="3sh-AF-8OT" id="XFA-5f-8tu"/> + <outlet property="btn_isRead" destination="6Xe-Xr-eHg" id="2cB-qi-GNv"/> <outlet property="btn_login" destination="eKb-oX-1Uq" id="dDh-bd-0Xq"/> <outlet property="btn_loginByCode" destination="Afa-A3-2l1" id="E63-hJ-wVB"/> <outlet property="btn_loginByPwd" destination="Ec8-sg-6R6" id="Y2P-aU-5lk"/> @@ -104,6 +105,7 @@ </constraints> <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <state key="normal" title="Button" image="btn_eye_open"/> + <state key="selected" image="btn_eye_close"/> <connections> <action selector="eyeAction:" destination="-1" eventType="touchUpInside" id="dWR-mX-Km9"/> </connections> @@ -198,6 +200,9 @@ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <state key="normal" title="Button" image="btn_choose"/> <state key="selected" image="btn_choose_s"/> + <connections> + <action selector="isReadAction:" destination="-1" eventType="touchUpInside" id="mKS-up-7fH"/> + </connections> </button> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="我已阅读并同意" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="esZ-HR-QwQ"> <rect key="frame" x="57" y="240" width="86" height="14.333333333333343"/> @@ -290,6 +295,7 @@ <resources> <image name="btn_choose" width="28" height="28"/> <image name="btn_choose_s" width="28" height="28"/> + <image name="btn_eye_close" width="21" height="8"/> <image name="btn_eye_open" width="20" height="20"/> <image name="btn_loginApple" width="44" height="44"/> <image name="btn_wechat" width="44" height="44"/> diff --git a/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift b/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift index f426728..1d88e8d 100644 --- a/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift +++ b/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.swift @@ -13,14 +13,29 @@ @IBOutlet weak var tf_input: QMUITextField! @IBOutlet weak var btn_complete: UIButton! + @IBOutlet weak var btn_eye: UIButton! private let shadowView = UIView() + var secretCode:String = "" + var phone:String = "" + + init(phone:String,secretCode:String) { + super.init(nibName: nil, bundle: nil) + self.phone = phone + self.secretCode = secretCode + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override func viewDidLoad() { super.viewDidLoad() title = "找回密码" } override func setUI() { + btn_eye.isSelected = true view.addSubview(shadowView) shadowView.backgroundColor = .white shadowView.snp.makeConstraints { make in @@ -38,14 +53,23 @@ shadowView.jq_gradientColor(colorArr: [UIColor(hexStr: "#F5F5F5").withAlphaComponent(0.15).cgColor,UIColor.white.cgColor], cornerRadius: 0, startPoint: CGPoint(x: 0, y: 0), endPoint: CGPoint(x: 0, y: 1), bounds: CGRect(x: 0, y: 0, width: JQ_ScreenW, height: 30),locations: [0.1,0.9]) } - + @IBAction func eyeAction(_ sender: UIButton) { + btn_eye.isSelected = !btn_eye.isSelected + tf_input.isSecureTextEntry = btn_eye.isSelected + } + @IBAction func completeAction(_ sender: UIButton) { + view.endEditing(true) guard !tf_input.text!.isEmpty else {alertError(msg: "请输入密码");return} guard tf_input.text!.count >= 8 else {alertError(msg: "密码至少8个字符,不能全是字母或数字");return} guard tf_input.text!.jq_isComplexPassword else {alertError(msg: "密码至少8个字符,不能全是字母或数字");return} - view.endEditing(true) - Popup_1_View.show(state: .success, title: "修改成功", subtitle: "您的密码已修改成功,快去登录账户吧") { - self.navigationController?.popToRootViewController(animated: true) - } + + Services.updatePwd(cellPhone: phone, password: tf_input.text!, secretCode: secretCode).subscribe(onNext: {data in + if let model = data.data{ + Popup_1_View.show(state: .success, title: "修改成功", subtitle: "您的密码已修改成功,快去登录账户吧") { + self.navigationController?.popToRootViewController(animated: true) + } + } + }).disposed(by: disposeBag) } } diff --git a/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.xib b/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.xib index 11cd4e8..67d2a0d 100644 --- a/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.xib +++ b/XQMuse/Root/Login/VC/ForgotPasswordChangeVC.xib @@ -12,6 +12,7 @@ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ForgotPasswordChangeVC" customModule="XQMuse" customModuleProvider="target"> <connections> <outlet property="btn_complete" destination="d75-LE-ADF" id="rmq-Hs-zrm"/> + <outlet property="btn_eye" destination="Yms-9v-sdO" id="OUp-yM-n4g"/> <outlet property="tf_input" destination="LM8-B2-jWF" id="sqd-EQ-r6O"/> <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/> </connections> @@ -55,6 +56,10 @@ <rect key="frame" x="342" y="193.66666666666666" width="20" height="22"/> <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <state key="normal" image="btn_eye_open"/> + <state key="selected" image="btn_eye_close"/> + <connections> + <action selector="eyeAction:" destination="-1" eventType="touchUpInside" id="i8H-qL-5Sc"/> + </connections> </button> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="至少8个字符,不能全是字母或数字" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XwG-d3-D1z"> <rect key="frame" x="31" y="249.66666666666663" width="227" height="17"/> @@ -107,6 +112,7 @@ </view> </objects> <resources> + <image name="btn_eye_close" width="21" height="8"/> <image name="btn_eye_open" width="20" height="20"/> <systemColor name="systemBackgroundColor"> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> diff --git a/XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift b/XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift index 70f83d7..1b6cc8a 100644 --- a/XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift +++ b/XQMuse/Root/Login/VC/ForgotPasswordInputCodeVC.swift @@ -43,7 +43,7 @@ super.viewDidAppear(animated) c1.becomeFirstResponder() c1.jq_borderWidth = 1 - starTimer() + sendCode() } override func viewDidLoad() { @@ -92,6 +92,13 @@ } } + + private func sendCode(){ + Services.sendCode(type: .forgetPwd).subscribe(onNext: { _ in + self.starTimer() + }).disposed(by: disposeBag) + } + private func starTimer(){ times = 60 btn_retry.isEnabled = false @@ -115,19 +122,29 @@ } @IBAction func checkingAction(_ sender: UIButton) { + view.endEditing(true) if inputCode.count != 6{ alertError(msg: "请输入验证码");return } - view.endEditing(true) - Popup_1_View.show(state: .success, title: "验证成功", subtitle:"手机号验证成功") { - let vc = ForgotPasswordChangeVC() - self.push(vc: vc) - } + + Services.forgotPwdVerifyCode(cellPhone: phone, captcha: inputCode).subscribe(onNext: {data in + if data.data?.successFlag ?? false{ + Popup_1_View.show(state: .success, title: "验证成功", subtitle:"手机号验证成功") { + let vc = ForgotPasswordChangeVC(phone:self.phone,secretCode: data.data?.secret ?? "") + self.push(vc: vc) + } + }else{ + Popup_1_View.show(state: .fail, title: "验证失败", subtitle:"手机号验证失败") { + + } + } + }).disposed(by: disposeBag) + } @IBAction func tryAgainAction(_ sender: UIButton) { view.endEditing(true) - starTimer() + sendCode() } diff --git a/XQMuse/Root/Login/VC/ForgotPasswordVC.swift b/XQMuse/Root/Login/VC/ForgotPasswordVC.swift index 1fc040a..d50e0ca 100644 --- a/XQMuse/Root/Login/VC/ForgotPasswordVC.swift +++ b/XQMuse/Root/Login/VC/ForgotPasswordVC.swift @@ -36,6 +36,7 @@ } @IBAction func checkingAction(_ sender: UIButton) { + view.endEditing(true) if tf_phone.text!.isEmpty{ alertError(msg: "请输入手机号");return } @@ -43,10 +44,8 @@ if !tf_phone.text!.jq_isPhone{ alertError(msg: "请输入正确手机号");return } - view.endEditing(true) let vc = ForgotPasswordInputCodeVC(phone: tf_phone.text!) push(vc: vc) - } diff --git a/XQMuse/Root/Login/VC/LoginTreatyVC.swift b/XQMuse/Root/Login/VC/LoginTreatyVC.swift index b2b409a..7cd76bd 100644 --- a/XQMuse/Root/Login/VC/LoginTreatyVC.swift +++ b/XQMuse/Root/Login/VC/LoginTreatyVC.swift @@ -12,7 +12,8 @@ class LoginTreatyVC: BaseVC { @IBOutlet weak var view_menu: UIView! @IBOutlet weak var view_content: UIView! - + var topIndex = 0 + private(set) var pageMenu:SPPageMenu = { let pageMenu = SPPageMenu(frame: .zero, trackerStyle: .line) // 追踪线 @@ -50,6 +51,8 @@ pageVC.scrollview.bounces = false return pageVC }() + private var clouse:((Bool)->Void)! + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) UIView.animate(withDuration: 0.5) { @@ -65,10 +68,16 @@ override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.black.withAlphaComponent(0) + + DispatchQueue.main.asyncAfter(delay: 0.1) { + self.pageMenu.selectedItemIndex = self.topIndex + self.pageViewController.scroll(toPage: self.topIndex, animation: true) + } } override func setUI() { view_menu.addSubview(pageMenu) + pageMenu.delegate = self pageMenu.snp.makeConstraints { make in make.edges.equalToSuperview() } @@ -82,12 +91,18 @@ } } + func clickHandle(_ clouse:@escaping (Bool)->Void){ + self.clouse = clouse + } + @IBAction func rejectAction(_ sender: UIButton) { dismiss(animated: true) + clouse(false) } @IBAction func completeAction(_ sender: UIButton) { dismiss(animated: true) + clouse(true) } } @@ -109,6 +124,14 @@ } func pageViewController(_ pageViewConteoller: FFPageViewController, controllerForPage page: Int) -> UIViewController { - return WebVC(url: "https://www.baidu.com") + + var agreementType:AgreementType = .none + if page == 0{ + agreementType = .user + }else{ + agreementType = .privacy + } + + return WebVC(type: agreementType) } } diff --git a/XQMuse/Root/Login/VC/RegisterVC.swift b/XQMuse/Root/Login/VC/RegisterVC.swift index 04e73e2..006e180 100644 --- a/XQMuse/Root/Login/VC/RegisterVC.swift +++ b/XQMuse/Root/Login/VC/RegisterVC.swift @@ -56,7 +56,8 @@ @IBOutlet weak var tf_pwd: QMUITextField! @IBOutlet weak var tf_pwdAgain: QMUITextField! @IBOutlet weak var btn_register: UIButton! - + @IBOutlet weak var btn_isRead: UIButton! + private var viewModel = RegisterViewModel() let shadowView = UIView() @@ -88,31 +89,49 @@ guard !viewModel.phone.value.isEmpty else {alertError(msg: "请输入手机号");return} guard viewModel.phone.value.jq_isPhone else {alertError(msg: "请输入正确手机号");return} - sender.jq_openCountDown(60, defultTitle: "发送验证码") { - sender.titleLabel?.font = UIFont.systemFont(ofSize: 12) - sender.setTitleColor(.black.withAlphaComponent(0.3), for: .normal) - } completeClouse: { - sender.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium) - sender.setTitleColor(UIColor(hexStr: "#96AD81"), for: .normal) - } + Services.sendCode(type: .register).subscribe(onNext: {data in + if let _ = data.data{ + sender.jq_openCountDown(60, defultTitle: "发送验证码") { + sender.titleLabel?.font = UIFont.systemFont(ofSize: 12) + sender.setTitleColor(.black.withAlphaComponent(0.3), for: .normal) + } completeClouse: { + sender.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium) + sender.setTitleColor(UIColor(hexStr: "#96AD81"), for: .normal) + } + } + }).disposed(by: disposeBag) } @IBAction func registerAction(_ sender: UIButton) { - guard viewModel.checkSafe() else {return} view.endEditing(true) + guard viewModel.checkSafe() else {return} + guard btn_isRead.isSelected else { + alertError(msg: "请阅读并同意《用户注册协议》和《用户隐私协议》");return + } + Services.register(cellPhone: viewModel.phone.value, captcha: viewModel.code.value, password: viewModel.pwd.value).subscribe(onNext: {data in + if let model = data.data{ + UserViewModel.saveUserInfo(model) + sceneDelegate?.loginSuccess() + } + }).disposed(by: disposeBag) } + @IBAction func isReadAction(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + } + + @IBAction func userResigerAgreementAction(_ sender: Any) { - let vc = WebVC() + let vc = WebVC(type: .user) vc.title = "用户注册协议" push(vc: vc) } @IBAction func userPrivateAgreementAction(_ sender: Any) { - let vc = WebVC() + let vc = WebVC(type: .privacy) vc.title = "用户隐私协议" push(vc: vc) } diff --git a/XQMuse/Root/Login/VC/RegisterVC.xib b/XQMuse/Root/Login/VC/RegisterVC.xib index 519a994..c7e0704 100644 --- a/XQMuse/Root/Login/VC/RegisterVC.xib +++ b/XQMuse/Root/Login/VC/RegisterVC.xib @@ -11,6 +11,7 @@ <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RegisterVC" customModule="XQMuse" customModuleProvider="target"> <connections> + <outlet property="btn_isRead" destination="iO1-Hp-lde" id="ixe-V6-sXe"/> <outlet property="btn_register" destination="PqN-MA-u63" id="odf-D6-k92"/> <outlet property="tf_code" destination="vho-4t-8f7" id="iq1-yh-uY9"/> <outlet property="tf_phone" destination="e5F-tB-S0k" id="nJI-hk-jml"/> @@ -208,6 +209,9 @@ <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/> <state key="normal" title="Button" image="btn_choose"/> <state key="selected" image="btn_choose_s"/> + <connections> + <action selector="isReadAction:" destination="-1" eventType="touchUpInside" id="KBs-ma-2YF"/> + </connections> </button> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="我已阅读并同意" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ioV-dr-25D"> <rect key="frame" x="57" y="436" width="86" height="14.333333333333314"/> diff --git a/XQMuse/Root/Login/View/Popup_1_View.swift b/XQMuse/Root/Login/View/Popup_1_View.swift index 901dd1e..8021868 100644 --- a/XQMuse/Root/Login/View/Popup_1_View.swift +++ b/XQMuse/Root/Login/View/Popup_1_View.swift @@ -32,6 +32,12 @@ static func show(state:Popup_1_State,title:String,subtitle:String, complete:@escaping()->Void){ let popupView = Popup_1_View.jq_loadNibView() + switch state { + case .fail: + popupView.img_state.image = UIImage(named: "icon_fail") + case .success: + popupView.img_state.image = UIImage(named: "icon_success") + } popupView.label_title.text = title popupView.label_subTitle.text = subtitle popupView.completeClouse = complete diff --git a/XQMuse/Root/Network/Models.swift b/XQMuse/Root/Network/Models.swift new file mode 100644 index 0000000..6990177 --- /dev/null +++ b/XQMuse/Root/Network/Models.swift @@ -0,0 +1,39 @@ +// +// Model.swift +// XQMuse +// +// Created by 无故事王国 on 2024/9/4. +// + +import HandyJSON +import UserDefaultsStore + +struct LoginUserInfoModel:HandyJSON,Identifiable,Codable{ + + static let idKey = \LoginUserInfoModel.userid + + var accessToken: String = "" + var appUserId: Int = 0 + var bindStatus: Int = 0 + var cellPhone: String = "" + var expireIn: Int = 0 + var expireTime: Int = 0 + var ipaddr: String = "" + var loginTime: Int = 0 + var token: String = "" + var userid: Int = 0 + var username: String = "" +} + + +struct HtmlModel:HandyJSON{ + var content: String = "" + var contentType:AgreementType = .none + var id: Int = 0 +} + + +struct VerifiyForgotPwdModel:HandyJSON{ + var secret:String = "" + var successFlag:Bool = false +} diff --git a/XQMuse/Root/Network/NetworkRequest.swift b/XQMuse/Root/Network/NetworkRequest.swift index 859e619..cd3464f 100644 --- a/XQMuse/Root/Network/NetworkRequest.swift +++ b/XQMuse/Root/Network/NetworkRequest.swift @@ -33,12 +33,6 @@ struct SimpleModel: HandyJSON { } -struct HtmlModel: HandyJSON { - var content = "" - var content1 = "" - var id = 0 - var type = 0 -} extension String: HandyJSON{ @@ -136,25 +130,26 @@ /// 参数加密 @discardableResult func done() -> Parameters { - var paramsArray: [String] = [] - // 排序 - let sortedArray: [String] = Array(params.keys).sorted() - - //防止自签名而错误 - if !sortedArray.contains("sign"){ - for item in sortedArray{ - // 拼接字符串 - if params.has(key: item){ - paramsArray.append("\(item)=\(params[item]!)") - } - } - let content = paramsArray.joined(separator: "&") -// params += ["sign": "\(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))"] - -#if DEBUG -// LogInfo("签名:\(content) ----- \(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))") -#endif - } +// var paramsArray: [String] = [] +// // 排序 +// let sortedArray: [String] = Array(params.keys).sorted() +// +// //防止自签名而错误 +// if !sortedArray.contains("sign"){ +// for item in sortedArray{ +// // 拼接字符串 +// if params.has(key: item){ +// paramsArray.append("\(item)=\(params[item]!)") +// } +// } +// let content = paramsArray.joined(separator: "&") +// +//// params += ["sign": "\(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))"] +// +//#if DEBUG +//// LogInfo("签名:\(content) ----- \(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))") +//#endif +// } return self.params } diff --git a/XQMuse/Root/Network/Services.swift b/XQMuse/Root/Network/Services.swift index e8a1270..22ac7f5 100644 --- a/XQMuse/Root/Network/Services.swift +++ b/XQMuse/Root/Network/Services.swift @@ -12,7 +12,7 @@ import JQTools #if DEBUG -let All_Url = "http://" +let All_Url = "https://console-mock.apipost.cn/mock/edb6887b-40b2-4245-aab0-50d773033f15" #else let All_Url = "http://" //正式地址 #endif @@ -21,14 +21,71 @@ } +// MARK: -- 登录 extension Services{ -// class func updateInfo(birthday:String?,gender:Int?,name:String?)->Observable<BaseResponse<SimpleModel>>{ -// let params = ParamsAppender.build(url: All_Url) -// .interface(url: "/account/api/appUser/updateInfo") -// .append(key: "birthday", value: birthday) -// .append(key: "gender", value: gender) -// .append(key: "name", value: name) -// return NetworkRequest.request(params: params, method: .post, progress: false) -// } + /// 密码登录 + class func loginBy(phone:String,content:String,type:LoginType)->Observable<BaseResponse<LoginUserInfoModel>>{ + let params = ParamsAppender.build(url: All_Url) + + switch type { + case .pwd: + params.interface(url: "/auth/app/login") + .append(key: "cellPhone", value: phone) + .append(key: "password", value: content.jq_md5String().uppercased()) + case .code: + params.interface(url: "/auth/app/captchaLogin") + .append(key: "cellPhone", value: phone) + .append(key: "captcha",value:content) + } + return NetworkRequest.request(params: params, method: .post, progress: true) + } + + /// 发送验证码 + class func sendCode(type:SendCodeType)->Observable<BaseResponse<SimpleModel>>{ + let params = ParamsAppender.build(url: All_Url) + params.interface(url: "/auth/app/sendCaptchaCode") + .append(key: "type", value: type.rawValue) + return NetworkRequest.request(params: params, method: .get, progress: true) + } + + /// 注册 + class func register(cellPhone:String,captcha:String,inviteUserId:String? = nil,password:String)->Observable<BaseResponse<LoginUserInfoModel>>{ + let params = ParamsAppender.build(url: All_Url) + params.interface(url: "/auth/app/register") + .append(key: "cellPhone", value: cellPhone) + .append(key: "captcha", value: captcha) + .append(key: "inviteUserId", value: inviteUserId) + .append(key: "password", value: password.jq_md5String().uppercased()) + return NetworkRequest.request(params: params, method: .post, progress: true) + } + + /// 找回密码验证手机号 + class func forgotPwdVerifyCode(cellPhone:String,captcha:String)->Observable<BaseResponse<VerifiyForgotPwdModel>>{ + let params = ParamsAppender.build(url: All_Url) + params.interface(url: "/auth/app/verifyPhone") + .append(key: "cellPhone", value: cellPhone) + .append(key: "captcha", value: captcha) + return NetworkRequest.request(params: params, method: .post, progress: true) + } + + class func updatePwd(cellPhone:String,password:String,secretCode:String)->Observable<BaseResponse<SimpleModel>>{ + let params = ParamsAppender.build(url: All_Url) + params.interface(url: "/auth/app/changePassword") + .append(key: "cellPhone", value: cellPhone) + .append(key: "password", value: password.jq_md5String().uppercased()) + .append(key: "secret", value: secretCode) + return NetworkRequest.request(params: params, method: .post, progress: true) + } +} + +extension Services{ + /// 获取协议 + class func agreementBy(_ type:AgreementType)->Observable<BaseResponse<HtmlModel>>{ + let params = ParamsAppender.build(url: All_Url) + .interface(url: "/system/public/getContent") + .append(key: "key", value: type.rawValue) + return NetworkRequest.request(params: params, method: .get, progress: false) + } + } diff --git a/XQMuse/Root/Network/ViewModels/UserViewModel.swift b/XQMuse/Root/Network/ViewModels/UserViewModel.swift new file mode 100644 index 0000000..093001c --- /dev/null +++ b/XQMuse/Root/Network/ViewModels/UserViewModel.swift @@ -0,0 +1,42 @@ +// +// UserViewModel.swift +// XQMuse +// +// Created by 无故事王国 on 2024/9/5. +// + +import Foundation +import UserDefaultsStore + +class UserViewModel{ + private static let userInfo = UserDefaultsStore<LoginUserInfoModel>(uniqueIdentifier: "UserInfoModel")! + + static func getToken()->String?{ + return UserDefaults.standard.object(forKey: "_userToken") as? String + } + static func saveToken(_ token:String){ + UserDefaults.standard.set(token, forKey: "_userToken") + UserDefaults.standard.synchronize() + } + + static func clearToken(){ + UserDefaults.standard.set(nil, forKey: "_userToken") + UserDefaults.standard.synchronize() + } + + static func saveUserInfo(_ model:LoginUserInfoModel){ + do{ + try UserViewModel.userInfo.save(model) + }catch{ + + } + } + + static func getUserInfo()->LoginUserInfoModel?{ + return UserViewModel.userInfo.allObjects().first + } + + static func clearUserInfo(){ + UserViewModel.userInfo.deleteAll() + } +} diff --git a/XQMuse/Root/Other/WebVC.swift b/XQMuse/Root/Other/WebVC.swift index 16a69a8..f463d3d 100644 --- a/XQMuse/Root/Other/WebVC.swift +++ b/XQMuse/Root/Other/WebVC.swift @@ -7,12 +7,14 @@ import UIKit import WebKit +import JQTools class WebVC: BaseVC { private var webView:WKWebView? - private(set) var url = "" - private(set) var htmlText = "" + private var type:AgreementType? + private(set) var url:String? + private(set) var htmlText:String? private(set) var baseUrl:URL? private var progressView = UIProgressView() private let jsCode = """ @@ -27,6 +29,11 @@ public convenience init(url:String) { self.init() self.url = url + } + + public convenience init(type:AgreementType){ + self.init() + self.type = type } public convenience init(htmlText:String,baseURL:URL? = nil) { @@ -65,12 +72,22 @@ make.height.equalTo(2) } + if type != nil{ + Services.agreementBy(type!).subscribe(onNext: {data in + if let model = data.data{ + self.webView?.loadHTMLString(model.content.jq_wrapHtml(), baseURL: nil) + } + }).disposed(by: disposeBag) + } - if !url.isEmpty { - let urlRequest = URLRequest(url: URL(string: url)!) + if url != nil { + let urlRequest = URLRequest(url: URL(string: url!)!) webView?.load(urlRequest) - }else{ - webView?.loadHTMLString(htmlText, baseURL: baseUrl) + return + } + + if htmlText != nil{ + webView?.loadHTMLString(htmlText!, baseURL: baseUrl) } } diff --git a/XQMuse/SceneDelegate.swift b/XQMuse/SceneDelegate.swift index 16cc298..a73d4e8 100644 --- a/XQMuse/SceneDelegate.swift +++ b/XQMuse/SceneDelegate.swift @@ -7,29 +7,22 @@ import UIKit import SVProgressHUD +import JQTools class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } window = UIWindow(windowScene: windowScene) window?.frame = windowScene.coordinateSpace.bounds - // if UserViewModel.getToken() != nil{ - // app.registerAndLoginSuccess() - // }else{ - // let loginNav = LoginNav(rootViewController: LoginVC()) - // window?.rootViewController = loginNav - // window?.makeKeyAndVisible() - // } - let tabbar = BaseTabBarVC() window?.rootViewController = tabbar window?.makeKeyAndVisible() tabbar.selectedIndex = 0 + SVProgressHUD.setContainerView(window) SVProgressHUD.setDefaultStyle(.dark) @@ -43,7 +36,12 @@ } func needLogin(){ - + let loginNav = LoginNav(rootViewController: LoginVC()) + loginNav.modalPresentationStyle = .fullScreen + JQ_currentViewController().present(loginNav, animated: true) + } + func loginSuccess(){ + } func sceneDidDisconnect(_ scene: UIScene) { -- Gitblit v1.7.1