From: liangzhenying <867174124@qq.com> Date: Mon, 29 Sep 2025 07:18:22 +0000 (+0800) Subject: 登录注册接口调试 X-Git-Tag: 1.0.2~94 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=f22649a1ee68caa9bf8b9676a01066a4f6a8062c;p=mirrors%2FShenYin.git 登录注册接口调试 --- diff --git a/ShenYin/Podfile.lock b/ShenYin/Podfile.lock index 7cb6391..f64e2ec 100644 --- a/ShenYin/Podfile.lock +++ b/ShenYin/Podfile.lock @@ -1,5 +1,6 @@ PODS: - - Alamofire (5.10.2) + - CryptoSwift (1.8.4) + - DeviceKit (5.4.0) - DGActivityIndicatorView (2.1.1) - FDFullscreenPopGesture (1.1) - FSPagerView (0.8.3) @@ -48,10 +49,6 @@ PODS: - JXSegmentedView (1.4.1) - Kingfisher (6.3.1) - MJRefresh (3.7.9) - - Moya (15.0.0): - - Moya/Core (= 15.0.0) - - Moya/Core (15.0.0): - - Alamofire (~> 5.0) - netfox (1.21.0) - Realm (20.0.3): - Realm/Headers (= 20.0.3) @@ -64,6 +61,7 @@ PODS: - SVProgressHUD/Core (= 2.3.1) - SVProgressHUD/Core (2.3.1) - SwiftDate (7.0.0) + - SwiftHTTP (3.0.1) - swiftScan (1.2.1) - TabPageViewController (0.2.8) - TZImagePickerController (3.8.9): @@ -75,6 +73,8 @@ PODS: - YYText (1.0.7) DEPENDENCIES: + - CryptoSwift + - DeviceKit (~> 5.4.0) - DGActivityIndicatorView - FDFullscreenPopGesture - FSPagerView @@ -84,13 +84,13 @@ DEPENDENCIES: - JXSegmentedView - Kingfisher (~> 6.0) - MJRefresh - - Moya - netfox - RealmSwift - SnapKit - SocketRocket - SVProgressHUD - SwiftDate + - SwiftHTTP - swiftScan - TabPageViewController - TZImagePickerController @@ -99,7 +99,8 @@ DEPENDENCIES: SPEC REPOS: https://gitee.com/mirrors/CocoaPods-Specs.git: - - Alamofire + - CryptoSwift + - DeviceKit - DGActivityIndicatorView - FDFullscreenPopGesture - FSPagerView @@ -116,7 +117,6 @@ SPEC REPOS: - JXSegmentedView - Kingfisher - MJRefresh - - Moya - netfox - Realm - RealmSwift @@ -124,6 +124,7 @@ SPEC REPOS: - SocketRocket - SVProgressHUD - SwiftDate + - SwiftHTTP - swiftScan - TabPageViewController - TZImagePickerController @@ -131,7 +132,8 @@ SPEC REPOS: - YYText SPEC CHECKSUMS: - Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496 + CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90 + DeviceKit: bd34bb1766d926c3cc5a5f6e3e9a6dd10148b805 DGActivityIndicatorView: ff2c76073d79692f724863c8dd38685866a03cb6 FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0 FSPagerView: 670405b2f18e2a87fa37f20b00de783e562c25a8 @@ -148,7 +150,6 @@ SPEC CHECKSUMS: JXSegmentedView: cd73555ce2134d1656db2cb383ba9c2f36fb5078 Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74 MJRefresh: ff9e531227924c84ce459338414550a05d2aea78 - Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee netfox: 9d5cc727fe7576c4c7688a2504618a156b7d44b7 Realm: 853e5089d6042dff807bda000277eadfe2da93d2 RealmSwift: f33c19577cefcbf681345d721fcbc7b42be4c949 @@ -156,12 +157,13 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22 SwiftDate: bbc26e26fc8c0c33fbee8c140c5e8a68293a148a + SwiftHTTP: e94f1aa8cde58637dcc0100f6349de31a3337fde swiftScan: 0849e7d7c1c641384767a573ee8cb90b88d1ddd9 TabPageViewController: 8bd4104909754416b35a98f3b72a5b674ab20dd5 TZImagePickerController: 456f470b5dea97b37226ec7a694994a8663340b2 YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 -PODFILE CHECKSUM: 57796390fdd051e53f61c569309d2caa20f804e9 +PODFILE CHECKSUM: 1495066f701d18df80b99c90e3a4f415fed5c214 COCOAPODS: 1.16.2 diff --git a/ShenYin/ShenYin/Api/HttpClient.swift b/ShenYin/ShenYin/Api/HttpClient.swift index 3d88d08..1e4ecc1 100644 --- a/ShenYin/ShenYin/Api/HttpClient.swift +++ b/ShenYin/ShenYin/Api/HttpClient.swift @@ -5,123 +5,136 @@ // Created by incar on 2024/1/9. // -import Foundation -import Moya -import HandyJSON - -// 相关api -enum CommomApi -{ - case sms(phone:String,type:SmsType) - case countryList - case list(pageNO: Int = 1, pageSize: Int = 10) - case login(phone:String,code:String) -} - -// 实现TargetType协议 -extension CommomApi: TargetType -{ - // url - var baseURL: URL - { -// return URL(string: "https://app-api.raisound.com")! - return URL(string: "https://app-api.deepchords.com")! - } - - /// 请求路径 - var path: String { - switch self { - case .sms(let phone,let type): - return "/uc/sms" - case .countryList: - return "/uc/country/list" - case .list: - return "list" - case .login(_,_): - return "/uc/phone/reg-login" - } - } - - /// 请求方式 - var method: Moya.Method { - switch self { - case .sms(_,_): - return .get - case .login(_,_): - return .post - default: - return .get - } - } - - /// 解析格式 - var sampleData: Data { - return "{}".data(using: String.Encoding.utf8)! - } -//https://sz.58.com/esf-ajax/activity/ashen_switch/?city_id=4 - - var task: Task { - // 公共参数 - var params: [String: Any] = ["token": "Gz1qYLXeBW8MZuUfDlr9wsAYuVS1cZFMJY9BbaF842L2gRps747o4w=="] - - // 收集参数 - switch self { - case let .sms(phone, type): - params["phone"] = phone - params["type"] = type - case let .list(pageNO, pageSize): - params["pageNO"] = pageNO - params["pageSize"] = pageSize - case let .login(phone,code): - params["phone"] = phone - params["smsCode"] = code - break - default: break - } - // 发起请求 - return .requestParameters(parameters: params, encoding: URLEncoding.default) - } - - /// 公共请求头 - var headers: [String : String]? { - return ["devtype": "iOS", "devid": UIDevice().identifierForVendor?.uuidString ?? "unknow"] - } - - -//https://gz.fang.anjuke.com/xinfang/harmony/adviser/adviser/getMainAdviserBlock?client_source=3&limit=100&target_id=523085&target_type=1&adviser_id=&adviser_type=1&loupan_id=523085&layout_id=&page_source=2 -} - -class HttpClient{ - static let instance = HttpClient() - let provider = MoyaProvider() - func request(_ target: CommomApi,completionHandler:@escaping ((T, String) -> Void)){ - - - provider.request(target){ (response) in - Logger.debug("url = \(target.baseURL.absoluteString + target.path)") - Logger.debug("param = \(response)") - - - switch response { - case .success(let value): - let data = value.data -// print("reponse data=>",data.hexEncodedString()) - var responseStr = "response转字符串失败" - if let str = String(data: data, encoding: .utf8) { - responseStr = str - } - Logger.debug("reponse text=>",responseStr) - if let res = T.deserialize(from: responseStr){ - completionHandler(res,responseStr) - return - } - completionHandler(ResponseBaseModel() as! T,"解析请求失败") - break - case .failure(let error): - completionHandler(ResponseBaseModel() as! T,"请求失败") - Logger.debug("***************\n网络连接失败!\n\(error)\n********************") - } - } - } - -} +//import Foundation +//import Moya +//import HandyJSON +//import DeviceKit +//// 相关api +//enum CommomApi +//{ +// case sms(phone:String,type:SmsType) +// case countryList +// case list(pageNO: Int = 1, pageSize: Int = 10) +// case register(param:[String:Any]) +// case login(phone:String,code:String) +//} +// +//// 实现TargetType协议 +//extension CommomApi: TargetType +//{ +// // url +// var baseURL: URL +// { +//// return URL(string: "https://app-api.raisound.com")! +//// http://118.145.178.188:32000/uc/country/list +//// return URL(string: "https://app-api.deepchords.com")! +// return URL(string: "http://118.145.178.188:32000")! +// } +// +// /// 请求路径 +// var path: String { +// switch self { +// case .sms(_,_): +// return "/uc/sms" +// case .countryList: +// return "/uc/country/list" +// case .list: +// return "list" +// case .register( let param): +// return "/uc/sign-up?smsCode=\(param["smsCode"]!)" +// case .login(_,_): +// return "/uc/phone/reg-login" +// } +// } +// +// /// 请求方式 +// var method: Moya.Method { +// switch self { +// case .sms(_,_): +// return .get +// case .register(_): +// return .post +// case .login(_,_): +// return .post +// default: +// return .get +// } +// } +// +// /// 解析格式 +// var sampleData: Data { +// return "{}".data(using: String.Encoding.utf8)! +// } +////https://sz.58.com/esf-ajax/activity/ashen_switch/?city_id=4 +//// let idfv = UIDevice.current.identifierForVendor?.uuidString +// var task: Task { +// // 公共参数 +//// var params: [String: Any] = ["token": "Gz1qYLXeBW8MZuUfDlr9wsAYuVS1cZFMJY9BbaF842L2gRps747o4w=="] +// var params: [String: Any] = [:] +// +// // 收集参数 +// switch self { +// case let .sms(phone, type): +// params["phone"] = phone +// params["type"] = type +// case let .list(pageNO, pageSize): +// params["pageNO"] = pageNO +// params["pageSize"] = pageSize +// case let .register(para): +// params += para +// case let .login(phone,code): +// params["phone"] = phone +// params["smsCode"] = code +// break +// default: +// break +// } +// return .requestParameters(parameters: params, encoding: URLEncoding.default) +// } +// +// /// 公共请求头 +// var headers: [String : String]? { +// return [ +// "devtype": "iOS", +// "devid": UIDevice().identifierForVendor?.uuidString ?? "unknow", +//// "Content - Type": "application/json" +// ] +// } +// +// +////https://gz.fang.anjuke.com/xinfang/harmony/adviser/adviser/getMainAdviserBlock?client_source=3&limit=100&target_id=523085&target_type=1&adviser_id=&adviser_type=1&loupan_id=523085&layout_id=&page_source=2 +//} +// +//class HttpClient{ +// static let instance = HttpClient() +// let provider = MoyaProvider() +// +// func request(_ target: CommomApi,completionHandler:@escaping ((T, String) -> Void)){ +// provider.request(target){ (response) in +// Logger.debug("url = \(target.baseURL.absoluteString + target.path)") +// Logger.debug("param = \(target.task)") +// +// +// switch response { +// case .success(let value): +// let data = value.data +//// print("reponse data=>",data.hexEncodedString()) +// var responseStr = "response转字符串失败" +// if let str = String(data: data, encoding: .utf8) { +// responseStr = str +// } +// Logger.debug("reponse text=>",responseStr) +// if let res = T.deserialize(from: responseStr){ +// completionHandler(res,responseStr) +// return +// } +// completionHandler(T(),"解析请求失败") +// break +// case .failure(let error): +// completionHandler(T(),"请求失败") +// Logger.debug("***************\n网络连接失败!\n\(error)\n********************") +// } +// } +// } +// +//} diff --git a/ShenYin/ShenYin/Api/HttpClient2.swift b/ShenYin/ShenYin/Api/HttpClient2.swift new file mode 100644 index 0000000..02d1827 --- /dev/null +++ b/ShenYin/ShenYin/Api/HttpClient2.swift @@ -0,0 +1,213 @@ +// +// HttpClient2.swift +// ShenYin +// +// Created by liangshi on 2025/9/28. +// + +import Foundation +import SwiftHTTP +import HandyJSON +import DeviceKit + + +enum RequestMethod{ + case get + case post + case put +} + +// 相关api +enum CommomApi +{ + case sms(phone:String,type:SmsType) + case countryList + case list(pageNO: Int = 1, pageSize: Int = 10) + case register(param:[String:Any]) + case smsLogin(param:[String:Any]) + case login(param:[String:Any]) + case deactivate + case updatePwd(param:[String:Any]) + case token +} + +// 实现TargetType协议 +extension CommomApi{ + // url + var baseURL: String + { + // return URL(string: "https://app-api.raisound.com")! + // http://118.145.178.188:32000/uc/country/list + // return URL(string: "https://app-api.deepchords.com")! + return "http://118.145.178.188:32000" + } + + var url:String{ + return baseURL + path + } + + /// 请求路径 + var path: String { + switch self { + case .sms(_,_): + return "/uc/sms" + case .countryList: + return "/uc/country/list" + case .list: + return "list" + case .register( let param): + return "/uc/sign-up?smsCode=\(param["smsCode"]!)" + case .smsLogin(_): + return "/uc/phone/sms-login" + case .login(_): + return "/uc/sign-in" + case .deactivate: + return "/uc/sign-away" + case .updatePwd(_): + return "/uc/reset" + case .token: + return "/uc/token" + } + } + + var method:RequestMethod{ + switch self { + case .register(_),.smsLogin(_),.login(_): + return .post + case .updatePwd(_): + return .put + default: + return .get + } + } + + + /// 解析格式 + var sampleData: Data { + return "{}".data(using: String.Encoding.utf8)! + } + //https://sz.58.com/esf-ajax/activity/ashen_switch/?city_id=4 + // let idfv = UIDevice.current.identifierForVendor?.uuidString + var param: [String:Any] { + // 公共参数 + // var params: [String: Any] = ["token": "Gz1qYLXeBW8MZuUfDlr9wsAYuVS1cZFMJY9BbaF842L2gRps747o4w=="] + var params: [String: Any] = [:] + + // 收集参数 + switch self { + case let .sms(phone, type): + params["phone"] = phone + params["type"] = type.value + case let .list(pageNO, pageSize): + params["pageNO"] = pageNO + params["pageSize"] = pageSize + case let .register(para): + params += para + case let .smsLogin(para): + params += para + break + case let .login(para): + params += para + break + case let .updatePwd(para): + params += para + break + default: + break + } + return params + } + + /// 公共请求头 + var headers: [String : String]? { + return [ + "devtype": "iOS", + "devid": UIDevice().identifierForVendor?.uuidString ?? "unknow", + // "Content - Type": "application/json" + ] + } +} + +class HttpClient{ + + static func request(_ target: CommomApi,completionHandler:@escaping ((T, String) -> Void)){ + let url = target.url + let params = target.param + Logger.debug("request => ",url) + Logger.debug(params) + + if target.method == .get { + HTTP.GET(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in + handleResponse(response, completionHandler: completionHandler) + } + } + else if target.method == .post{ + HTTP.POST(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in + handleResponse(response, completionHandler: completionHandler) + } + } + else if target.method == .put{ + HTTP.PUT(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in + handleResponse(response, completionHandler: completionHandler) + } + } + } + +} + +extension HttpClient{ + private static func handleResponse(_ response: Response, completionHandler: @escaping ((T, String) -> Void)) { + DispatchQueue.main.sync { + guard let dict = receiveData(response) else{ + completionHandler(T(),"请求失败") + return + } + let responseStr = response.data.string ?? "" + if let res = T.deserialize(from: dict){ + completionHandler(res,responseStr) + return + } + completionHandler(T(),"请求失败") + } + } + + static func receiveData(_ response:Response) ->(NSDictionary?){ + if let _ = response.error { + Logger.debug(response.description) + return (nil) + } + Logger.debug(response.data.string ?? "") + guard let dict = response.data.jsonObject() as? NSDictionary else{ + return (nil) + } + return (dict) + } + + static func receiveData(_ data:Data?, _ response:URLResponse?,_ error:Error?) ->(NSDictionary?){ + if let _ = error { + Logger.debug(response?.description ?? "") + return (nil) + } + + guard let data = data,let dict = data.jsonObject() as? NSDictionary else{ + Logger.debug(response?.description ?? "") + return (nil) + } + Logger.debug(data.string ?? "") + return (dict) + } + +} + +extension Data { + var string: String? { String(data: self, encoding: .utf8) } + func jsonObject(options: JSONSerialization.ReadingOptions = [.mutableContainers]) -> Any? { + do { return try JSONSerialization.jsonObject(with: self, options: options) } + catch { Logger.debug(error) } + return nil + } +} + +extension String { + var data: Data? { self.data(using: .utf8) } +} diff --git a/ShenYin/ShenYin/Api/ResponseBaseModel.swift b/ShenYin/ShenYin/Api/ResponseBaseModel.swift index e887c13..8f98274 100644 --- a/ShenYin/ShenYin/Api/ResponseBaseModel.swift +++ b/ShenYin/ShenYin/Api/ResponseBaseModel.swift @@ -12,7 +12,7 @@ public class ResponseBaseModel: HandyJSON { public var code = -1 public var msg = "请求失败" - + public var success = false - public var isSuccess: Bool { return code == 20000} + public var isSuccess: Bool { return success} } diff --git a/ShenYin/ShenYin/Info.plist b/ShenYin/ShenYin/Info.plist index e31de9e..8d34e7e 100644 --- a/ShenYin/ShenYin/Info.plist +++ b/ShenYin/ShenYin/Info.plist @@ -27,5 +27,10 @@ bluetooth-central audio + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + diff --git a/ShenYin/ShenYin/Tools/AESEncryption.swift b/ShenYin/ShenYin/Tools/AESEncryption.swift new file mode 100644 index 0000000..df13e2a --- /dev/null +++ b/ShenYin/ShenYin/Tools/AESEncryption.swift @@ -0,0 +1,55 @@ +// +// Untitled.swift +// ShenYin +// +// Created by liangshi on 2025/9/28. +// +import CryptoSwift + +class AESEncryption { + static func encrypt(_ plainText: String, key: String, iv: String) -> String? { + guard let plainData = plainText.data(using:.utf8), + let keyData = key.data(using:.utf8), + let ivData = iv.data(using:.utf8) else { + return nil + } + let plainBytes = Array(plainData.withUnsafeBytes { Array($0) }) + let keyBytes = Array(keyData.withUnsafeBytes { Array($0) }) + let ivBytes = Array(ivData.withUnsafeBytes { Array($0) }) + do { + let encrypted = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding:.pkcs5).encrypt(plainBytes) + return Data(encrypted).base64EncodedString() + } catch { + print("Encryption error: \(error)") + return nil + } + } + + static func decrypt(_ encryptedText: String, key: String, iv: String) -> String? { + guard let encryptedData = Data(base64Encoded: encryptedText), + let keyData = key.data(using:.utf8), + let ivData = iv.data(using:.utf8) else { + return nil + } + let encryptedBytes = Array(encryptedData.withUnsafeBytes { Array($0) }) + let keyBytes = Array(keyData.withUnsafeBytes { Array($0) }) + let ivBytes = Array(ivData.withUnsafeBytes { Array($0) }) + do { + let decrypted = try AES(key: keyBytes, blockMode: CBC(iv: ivBytes), padding:.pkcs5).decrypt(encryptedBytes) + return String(data: Data(decrypted), encoding:.utf8) + } catch { + print("Decryption error: \(error)") + return nil + } + } + + static func generateRandomString(length: Int = 16) -> String { + let letters = "abcdef0123456789" + var randomString: String = "" + for _ in 0..= 1.0 { -// kDelay(0.3) { -// self.progressView.alpha = 0.0 -// self.progressView.setProgress(0.0, animated: false) -// } -// } -// }else if keyPath == "title" { -// if initData.title.isEmpty { -// navBar.title = webView.title ?? " " -// } -// -// } else { -// super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) -// } -// } -//} -// -//// MARK: - ********* webview delegate -//extension BaseWebViewController: WKNavigationDelegate { -// -// func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { -// webView.evaluateJavaScript( -// "document.getElementsByTagName('body')[0].style.background='#FAFAFA'", -// completionHandler: nil) -// } -// func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { -// k_log("==== error: \(error)") -// } -// func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { -// k_log("==== error: \(error)") -// } -// func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { -// if (navigationAction.targetFrame == nil) { -// webView.load(navigationAction.request) -// } -// guard let policy = WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2) -// else { decisionHandler(.allow); return } -// decisionHandler(policy) -// } -//} -// -//// MARK: - ********* UIResponse Funcs -//extension BaseWebViewController { -// override func navleftViewTapped() { -// if webView.canGoBack { -// webView.goBack() -// } -// else{ -// if let _ = self.presentingViewController { -// self.dismiss(animated: true, completion: nil) -// } else if let nav = self.navigationController { -// nav.popViewController(animated: true) -// } -// } -// -// } -// override func navRightViewTapped() { -// if let _ = self.presentingViewController { -// self.dismiss(animated: true, completion: nil) -// } else if let nav = self.navigationController { -// nav.popViewController(animated: true) -// } -// } -//} -// -//// MARK: - UI Setup -//private extension BaseWebViewController { -// -// func setupLayout() { -// view.addSubview(webView) -// webView.addSubview(progressView) -// -// webView.snp.makeConstraints { (m) in -// m.top.equalToSuperview().inset(kNavBtm) -// m.bottom.equalToSuperview() -// m.leading.trailing.equalToSuperview() -// } -// progressView.snp.makeConstraints { (m) in -// m.top.leading.trailing.equalToSuperview() -// m.height.equalTo(2) -// } -// } -// -// func setupStyle() { -// -// navBar.title = initData.title -// setNavRight(title: "关闭",norColor: .color(.secondary)) -// -// view.backgroundColor = .color(.viewBg) -// -// webView.navigationDelegate = self -// webView.uiDelegate = self -// webView.backgroundColor = .color(.viewBg) -// -// webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil) -// webView.addObserver(self, forKeyPath: "canGoBack", options: .new, context: nil) -// webView.addObserver(self, forKeyPath: "title", options: .new, context: nil) -// webView.evaluateJavaScript("document.getElementsByTagName('body')[0].style.background='#FAFAFA'", completionHandler: nil) -// -// /// 加载URL -// if let requestUrl = initData.urlStr.yc.asUrl { -// let request = URLRequest(url: requestUrl) -// webView.load(request) -// } -// else if let request = initData.request { -// webView.load(request) -// } -// else { return } -// -// /// 进度条 -// progressView.trackTintColor = .clear -// progressView.progressTintColor = .color(.theme) -// progressView.isHidden = false -// progressView.setProgress(0.05, animated: true) -// -// } -//} -// -//// MARK: - WKUIDelegate 不实现该代理方法 网页内调用弹窗时会抛出异常,导致程序崩溃 -//extension BaseWebViewController: WKUIDelegate { -// // 获取js 里面的提示 -// func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { -// if self.navigationController?.visibleViewController != self { -// completionHandler() -// return -// } -// let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert) -// alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in -// completionHandler() -// })) -// alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in -// completionHandler() -// })) -// self.present(alert, animated: true, completion: nil) -// } -// -// // js 信息的交流 -// func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { -// let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert) -// alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in -// completionHandler(true) -// })) -// alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in -// completionHandler(false) -// })) -// self.present(alert, animated: true, completion: nil) -// } -// -// // 交互。可输入的文本。 -// func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { -// let alert = UIAlertController(title: prompt, message: defaultText, preferredStyle: .alert) -// alert.addTextField { (textField: UITextField) -> Void in -// textField.textColor = UIColor.red -// } -// alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in -// completionHandler(alert.textFields![0].text!) -// })) -// self.present(alert, animated: true, completion: nil) -// } -//} -// +import UIKit +import WebKit + +struct BaseWebViewParams { + var urlStr: String + var request: URLRequest? + var title: String + init(urlStr: String, title: String = "") { + self.urlStr = urlStr + self.title = title + self.request = nil + } + init(request: URLRequest, title: String = "") { + self.request = request + self.urlStr = "" + self.title = title + } +} + +final class BaseWebViewController: BaseVC { + let webView = BaseWebView() + private let progressView = UIProgressView(progressViewStyle: .default) + private var initData: BaseWebViewParams + init(initData: BaseWebViewParams) { + + self.initData = initData + super.init() + } + + override func setupViews() { + view.addSubview(webView) + webView.addSubview(progressView) + + navBar.title = initData.title + navBar.rightView.setTitle("关闭", for: .normal) + + view.backgroundColor = .color(.bgColor) + + webView.navigationDelegate = self + webView.uiDelegate = self + webView.backgroundColor = .color(.bgColor) + + webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil) + webView.addObserver(self, forKeyPath: "canGoBack", options: .new, context: nil) + webView.addObserver(self, forKeyPath: "title", options: .new, context: nil) + webView.evaluateJavaScript("document.getElementsByTagName('body')[0].style.background='#FAFAFA'", completionHandler: nil) + + /// 加载URL + if let requestUrl = initData.urlStr.yc.asUrl { + let request = URLRequest(url: requestUrl) + webView.load(request) + } + else if let request = initData.request { + webView.load(request) + } + else { return } + + /// 进度条 + progressView.trackTintColor = .clear + progressView.progressTintColor = .color(.theme) + progressView.isHidden = false + progressView.setProgress(0.05, animated: true) + } + override func setupLayout() { + webView.snp.makeConstraints { (m) in + m.top.equalToSuperview().inset(kNavBtm) + m.bottom.equalToSuperview() + m.leading.trailing.equalToSuperview() + } + progressView.snp.makeConstraints { (m) in + m.top.leading.trailing.equalToSuperview() + m.height.equalTo(2) + } + } + + override func navleftViewTapped() { + if webView.canGoBack { + webView.goBack() + } + else{ + if let _ = self.presentingViewController { + self.dismiss(animated: true, completion: nil) + } else if let nav = self.navigationController { + nav.popViewController(animated: true) + } + } + + } + override func navRightViewTapped() { + if let _ = self.presentingViewController { + self.dismiss(animated: true, completion: nil) + } else if let nav = self.navigationController { + nav.popViewController(animated: true) + } + } + + deinit { + webView.removeObserver(self, forKeyPath: "canGoBack") + webView.removeObserver(self, forKeyPath: "estimatedProgress") + webView.removeObserver(self, forKeyPath: "title") + } + + override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + if keyPath == "canGoBack" { + if webView.canGoBack { + self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true + } else { + self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false + } + } else if keyPath == "estimatedProgress" { + progressView.alpha = CGFloat(1.0 - webView.estimatedProgress) + 0.2 + let progerss = max(Float(webView.estimatedProgress), 0.1) + progressView.setProgress(progerss, animated: true) + if webView.estimatedProgress >= 1.0 { + kDelay(0.3) { + self.progressView.alpha = 0.0 + self.progressView.setProgress(0.0, animated: false) + } + } + }else if keyPath == "title" { + if initData.title.isEmpty { + navBar.title = webView.title ?? " " + } + + } else { + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + } + } +} + +// MARK: - ********* webview delegate +extension BaseWebViewController: WKNavigationDelegate { + + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + webView.evaluateJavaScript( + "document.getElementsByTagName('body')[0].style.background='#FAFAFA'", + completionHandler: nil) + } + func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { + k_log("==== error: \(error)") + } + func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { + k_log("==== error: \(error)") + } + func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + if (navigationAction.targetFrame == nil) { + webView.load(navigationAction.request) + } + guard let policy = WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2) + else { decisionHandler(.allow); return } + decisionHandler(policy) + } +} + +// MARK: - WKUIDelegate 不实现该代理方法 网页内调用弹窗时会抛出异常,导致程序崩溃 +extension BaseWebViewController: WKUIDelegate { + // 获取js 里面的提示 + func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { + if self.navigationController?.visibleViewController != self { + completionHandler() + return + } + let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in + completionHandler() + })) + alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in + completionHandler() + })) + self.present(alert, animated: true, completion: nil) + } + + // js 信息的交流 + func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { + let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in + completionHandler(true) + })) + alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in + completionHandler(false) + })) + self.present(alert, animated: true, completion: nil) + } + + // 交互。可输入的文本。 + func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { + let alert = UIAlertController(title: prompt, message: defaultText, preferredStyle: .alert) + alert.addTextField { (textField: UITextField) -> Void in + textField.textColor = UIColor.red + } + alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in + completionHandler(alert.textFields![0].text!) + })) + self.present(alert, animated: true, completion: nil) + } +} + diff --git a/ShenYin/ShenYin/UI/Home/HistoryRecord/SelecteCell.swift b/ShenYin/ShenYin/UI/Home/HistoryRecord/SelecteCell.swift index fa414f1..f849162 100644 --- a/ShenYin/ShenYin/UI/Home/HistoryRecord/SelecteCell.swift +++ b/ShenYin/ShenYin/UI/Home/HistoryRecord/SelecteCell.swift @@ -73,6 +73,11 @@ class SelectCell: BaseTableViewCell { titleLabel.text = genderType.title } } + var country:CountryModel = CountryModel(){ + didSet{ + titleLabel.text = country.name + } + } override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) diff --git a/ShenYin/ShenYin/UI/Launch/AppLaunch.swift b/ShenYin/ShenYin/UI/Launch/AppLaunch.swift index 50f4af0..635358a 100644 --- a/ShenYin/ShenYin/UI/Launch/AppLaunch.swift +++ b/ShenYin/ShenYin/UI/Launch/AppLaunch.swift @@ -24,12 +24,19 @@ class AppLaunch:NSObject{ IQKeyboardManager.shared.resignOnTouchOutside = true } static func loadCache(){ + if CacheManager.shared.user.isLogin { + App.shared.didLogin() + } + else{ + App.shared.goToLogin() + } + let list = DeviceCache.shared.getDeviceList() Logger.debug("缓存设备",list) - if list.count > 0 { - CacheManager.shared.currentDevice = list.first - BleManager.shared.startScanDevice() - App.shared.enter() - } +// if list.count > 0 { +// CacheManager.shared.currentDevice = list.first +// BleManager.shared.startScanDevice() +// App.shared.enter() +// } } } diff --git a/ShenYin/ShenYin/UI/Launch/AppManager.swift b/ShenYin/ShenYin/UI/Launch/AppManager.swift index 183d48a..500ac80 100644 --- a/ShenYin/ShenYin/UI/Launch/AppManager.swift +++ b/ShenYin/ShenYin/UI/Launch/AppManager.swift @@ -17,15 +17,20 @@ class App{ return getTopViewController(from: vc) } - func enter(){ + func didLogin(){ window?.rootViewController = BaseTC() } + func goToLogin(){ + window?.rootViewController = BaseNC(rootViewController: LoginVC()) + } func goToPage(_ viewController: UIViewController,animated:Bool = true){ viewController.hidesBottomBarWhenPushed = true topVC().navigationController?.pushViewController(viewController, animated: animated) } - + func popPage(){ + topVC().navigationController?.popViewController(animated: true) + } } extension App{ @@ -48,3 +53,5 @@ extension App{ // return !BleManager.shared.isConnetd } } + + diff --git a/ShenYin/ShenYin/UI/Launch/BleManager.swift b/ShenYin/ShenYin/UI/Launch/BleManager.swift index 6f3c078..2e6ef0e 100644 --- a/ShenYin/ShenYin/UI/Launch/BleManager.swift +++ b/ShenYin/ShenYin/UI/Launch/BleManager.swift @@ -199,7 +199,7 @@ extension BleManager : JoyGemAIManagerDelegate { self.isConnetd = true NotificationManager.post(type: .deviceValidChange, objtect: nil) ConnectPopView().showAutoHide { - App.shared.enter() +// App.shared.enter() } CacheManager.shared.saveDevice(DeviceModel(name: connectPeripheral?.name ?? "", uuid: connectPeripheral?.identifier.uuidString ?? "")) PcmSound.sharedInstance().setup(16000, withchannels: 1) diff --git a/ShenYin/ShenYin/UI/Launch/SceneDelegate.swift b/ShenYin/ShenYin/UI/Launch/SceneDelegate.swift index 531b766..fa3008b 100644 --- a/ShenYin/ShenYin/UI/Launch/SceneDelegate.swift +++ b/ShenYin/ShenYin/UI/Launch/SceneDelegate.swift @@ -8,10 +8,8 @@ import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { - var window: UIWindow? - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. @@ -20,7 +18,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { App.shared.window = window window?.rootViewController = BaseTC() -// window?.rootViewController = UINavigationController(rootViewController: ChatVC()) + window?.rootViewController = UINavigationController(rootViewController: LoginVC()) AppLaunch.start() } diff --git a/ShenYin/ShenYin/UI/Mine/Login/Controller/ContryListVC.swift b/ShenYin/ShenYin/UI/Mine/Login/Controller/ContryListVC.swift new file mode 100644 index 0000000..e3cfc89 --- /dev/null +++ b/ShenYin/ShenYin/UI/Mine/Login/Controller/ContryListVC.swift @@ -0,0 +1,73 @@ +// +// ContryListVC.swift +// ShenYin +// +// Created by liangshi on 2025/9/27. +// + +import UIKit +class ContryListVC: BaseVC{ + let tableView = UITableView(frame: .zero, style: .plain) + var currentType = CountryModel() + var didSelected:((_ model:CountryModel)->Void)? + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + override func setupViews() { + self.navBar.title = "国家/地区" + tableView.do { v in + v.backgroundColor = .rgb(0xF7F7F7) + v.delegate = self + v.dataSource = self + v.rowHeight = 52 + v.separatorStyle = .none + v.register(SelectCell.self, forCellReuseIdentifier: SelectCell.reuseID) + } + view.addSubviews([tableView]) + + } + override func setupLayout() { + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalTo(kNavBtm) + } + } + override func setupData() { + LoginVM.fetchCountryList {[weak self] result in + guard let self = self else{return} + self.tableView.reloadData() + } + } +} + +extension ContryListVC:UITableViewDelegate,UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return LoginVM.shared.countryList.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = SelectCell.cell(withTableView: tableView, indexPath: indexPath) + cell.country = LoginVM.shared.countryList[indexPath.row] + let rect = CGRect(x: 0, y: 0, width: kScreenWid - 36, height: 52) + if indexPath.row == 0 { + cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 8, height: 8)) + } + else if indexPath.row == LoginVM.shared.countryList.count - 1{ + cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: 8, height: 8)) + } + else{ + cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.allCorners], cornerRadii: CGSize(width: 0, height: 0)) + } + cell.selectedIcon.isHidden = cell.country.name != currentType.name + return cell + } + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let data = LoginVM.shared.countryList[indexPath.row] + currentType = data + tableView.reloadData() + didSelected?(data) + navigationController?.popViewController(animated: true) + } +} diff --git a/ShenYin/ShenYin/UI/Mine/Login/Controller/ForgetVC.swift b/ShenYin/ShenYin/UI/Mine/Login/Controller/ForgetVC.swift index 8a5d553..275adcb 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/Controller/ForgetVC.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/Controller/ForgetVC.swift @@ -110,30 +110,46 @@ extension ForgetVC{ return } YLprogressHUD.showLoading() - LoginVM.sendCode(phone: text) { [weak self] (model) in + HttpClient.request(CommomApi.sms(phone: text,type: .forget)) {[weak self] (model:ResponseBaseModel, res) in if model.isSuccess{ self?.codeView.codeButton.start() } YLprogressHUD.showAutoHiden(model.msg) } } - @objc func registerAction(){ - App.shared.goToPage(RegisterVC()) - } @objc func loginAction(){ - guard let pohne = phoneView.textField.text else{ + guard let phone = phoneView.textField.value else{ YLprogressHUD.showAutoHiden("请输入正确的手机号码") return } - guard let code = codeView.textField.text else{ - YLprogressHUD.showAutoHiden("请输入正确的验证码") + guard let code = codeView.textField.value else{ + YLprogressHUD.showAutoHiden("请输入验证码") + return + } + guard let pwd = pwdView.textField.value else{ + YLprogressHUD.showAutoHiden("请输入密码") return } YLprogressHUD.showLoading() - LoginVM.login(phone: pohne, code: code) {[weak self] result in + + let plainText = pwd + let key = Date().format(.full4) + let iv = AESEncryption.generateRandomString() + guard let encryptedText = AESEncryption.encrypt(plainText, key: key, iv: iv) else { + return + } + + var params:[String:Any] = [:] + params["phone"] = phone + params["password"] = encryptedText + params["nonce"] = iv + params["smsCode"] = code + + let api = CommomApi.updatePwd(param: params) + HttpClient.request(api) { (result:ResponseBaseModel,res) in if result.isSuccess{ YLprogressHUD.showSuccess { - self?.view.window?.rootViewController = BaseTC() + App.shared.popPage() } } YLprogressHUD.showAutoHiden(result.msg) diff --git a/ShenYin/ShenYin/UI/Mine/Login/Controller/LoginVC.swift b/ShenYin/ShenYin/UI/Mine/Login/Controller/LoginVC.swift index 0b9c891..6748b47 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/Controller/LoginVC.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/Controller/LoginVC.swift @@ -6,6 +6,7 @@ // import UIKit +import DeviceKit class LoginVC:BaseVC{ @@ -15,8 +16,7 @@ class LoginVC:BaseVC{ let phoneView = CustomInputView() let pwdView = PasswordView() let loginBtn = CustomButton() - let registerBtn = CustomButton() - let forgetBtn = UIButton() + let othersView = OthersLoginView() let agreeView = AgreeView() override func viewDidLoad() { @@ -56,15 +56,8 @@ class LoginVC:BaseVC{ } loginBtn.set(title: "登录",style: .theme1, target: self, action: #selector(loginAction)) - registerBtn.set(title: "注册", style: .theme2,target: self, action: #selector(registerAction)) - forgetBtn.do { v in - v.setTitle("忘记密码", for: .normal) - v.titleLabel?.font = .regular(12) - v.setTitleColor(.hexString("#666666"), for: .normal) - v.addTarget(self, action: #selector(forgetAction), for: .touchUpInside) - } view.addSubviews([tipsLabel,bgView]) - bgView.addSubviews([titleLabel,phoneView,pwdView,loginBtn,registerBtn,agreeView,forgetBtn]) + bgView.addSubviews([titleLabel,phoneView,pwdView,loginBtn,agreeView,othersView]) } override func setupLayout(){ @@ -96,48 +89,63 @@ class LoginVC:BaseVC{ make.left.right.equalToSuperview().inset(51) make.height.equalTo(55) } - registerBtn.snp.makeConstraints { make in - make.top.equalTo(loginBtn.snp.bottom).offset(20) - make.left.right.equalToSuperview().inset(51) - make.height.equalTo(55) - } agreeView.snp.makeConstraints { make in - make.bottom.equalToSuperview().inset(62) + make.top.equalTo(pwdView.snp.bottom).offset(10) make.centerX.equalToSuperview() make.height.equalTo(30) } - forgetBtn.snp.makeConstraints { make in - make.right.equalTo(pwdView.snp.right) - make.width.equalTo(55) + othersView.snp.makeConstraints { make in + make.centerX.equalToSuperview() make.height.equalTo(50) - make.top.equalTo(pwdView.snp.bottom) + make.left.right.equalToSuperview() + make.top.equalTo(loginBtn.snp.bottom).offset(20) } } } extension LoginVC{ - @objc func forgetAction(){ - App.shared.goToPage(ForgetVC()) - } - @objc func registerAction(){ - App.shared.goToPage(RegisterVC()) - } @objc func loginAction(){ guard let phone = phoneView.textField.value else{ YLprogressHUD.showAutoHiden("请输入正确的手机号码") return } - guard let code = pwdView.textField.value else{ + guard let pwd = pwdView.textField.value else{ YLprogressHUD.showAutoHiden("请输入密码") return } YLprogressHUD.showLoading() - LoginVM.login(phone: phone, code: code) {[weak self] result in + + + let plainText = pwd + let key = Date().format(.full4) + let iv = AESEncryption.generateRandomString() + + Logger.debug("pwd: \(pwd)") + Logger.debug("iv: \(iv)") + Logger.debug("key: \(key)") + + guard let encryptedText = AESEncryption.encrypt(plainText, key: key, iv: iv) else { + return + } + Logger.debug("Encrypted: \(encryptedText)") + // if let decryptedText = AESEncryption.decrypt(encryptedText, key: key, iv: iv) { + // Logger.debug("Decrypted: \(decryptedText)") + // } + + var params:[String:Any] = [:] + params["account"] = phone + params["password"] = encryptedText + params["nonce"] = iv + + params["deviceName"] = Device.current.name + params["deviceCode"] = CacheManager.uuid() + + LoginVM.login(param: params) { result in if result.isSuccess{ YLprogressHUD.showSuccess { - self?.view.window?.rootViewController = BaseTC() + App.shared.didLogin() } } YLprogressHUD.showAutoHiden(result.msg) diff --git a/ShenYin/ShenYin/UI/Mine/Login/Controller/RegisterVC.swift b/ShenYin/ShenYin/UI/Mine/Login/Controller/RegisterVC.swift index 0bacf68..98eef3b 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/Controller/RegisterVC.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/Controller/RegisterVC.swift @@ -1,22 +1,22 @@ // -// LoginVC.swift +// RegisterVC.swift // ShenYin // // Created by liangshi on 2025/7/30. // import UIKit +import DeviceKit class RegisterVC:BaseVC{ - let scrollView = UIScrollView() + let tipsLabel = UILabel() let bgView = UIView() let titleLabel = UILabel() + let regionView = RegionView() let phoneView = CustomInputView() let codeView = CodeView() let pwdView = PasswordView() - let pwdView2 = PasswordView() - let loginBtn = CustomButton() let registerBtn = CustomButton() let agreeView = AgreeView() @@ -24,7 +24,8 @@ class RegisterVC:BaseVC{ super.viewDidLoad() } override func setupViews(){ - self.navBar.title = "" + // self.navBar.title = "" + // navBar.isHidden = true view.backgroundColor = .color(.bgColor) tipsLabel.do { v in v.numberOfLines = 0 @@ -48,45 +49,35 @@ class RegisterVC:BaseVC{ v.font = .medium(18) v.textColor = .hexString("#121212") } - phoneView.do { v in - v.textField.text = "13480939445" - } + codeView.do { v in v.codeButton.addTarget(self, action: #selector(codeButtonAction), for: .touchUpInside) } - pwdView.do { v in - v.textField.placeholder = "请输入密码" + regionView.do { v in + v.didSelected = {[weak self] model in + guard let self = self else {return} + updateLayout() + phoneView.showLeftView = model.isChinese + } + v.region = CountryModel.chinese() } - pwdView2.do { v in - v.textField.placeholder = "请确认密码" + phoneView.do { v in + v.textField.text = "19276672101" } registerBtn.set(title: "注册",style: .theme1, target: self, action: #selector(registerAction)) - loginBtn.set(title: "登录",style: .theme2, target: self, action: #selector(loginAction)) - agreeView.isHidden = true - - scrollView.backgroundColor = .clear - view.addSubview(scrollView) - scrollView.addSubviews([tipsLabel,bgView]) - bgView.addSubviews([titleLabel,phoneView,codeView,pwdView,pwdView2,loginBtn,registerBtn,agreeView]) + view.addSubviews([tipsLabel,bgView]) + bgView.addSubviews([titleLabel,regionView,phoneView,codeView,pwdView,registerBtn,agreeView]) } override func setupLayout(){ - scrollView.snp.makeConstraints { make in - make.top.equalToSuperview().inset(kNavBtm) - make.left.equalToSuperview() - make.height.equalTo(kScreenHei - kNavBtm) - make.width.equalTo(kScreenWid) - } tipsLabel.snp.makeConstraints { make in make.left.equalToSuperview().inset(28) - make.top.equalTo(20) + make.top.equalTo(kNavBtm + 20) make.centerX.equalToSuperview() } bgView.snp.makeConstraints { make in - make.left.equalToSuperview() - make.top.equalToSuperview().inset(160) - make.width.equalTo(kScreenWid) - make.height.equalTo(kScreenHei - 250) + make.left.right.equalToSuperview() + make.top.equalToSuperview().inset(244) make.bottom.equalToSuperview() } @@ -94,10 +85,14 @@ class RegisterVC:BaseVC{ make.top.equalToSuperview().offset(34) make.left.right.equalToSuperview().inset(36) } - phoneView.snp.makeConstraints { make in + regionView.snp.makeConstraints { make in make.top.equalToSuperview().offset(82) make.left.right.equalToSuperview().inset(36) } + phoneView.snp.makeConstraints { make in + make.top.equalTo(regionView.snp.bottom).offset(20) + make.left.right.equalToSuperview().inset(36) + } codeView.snp.makeConstraints { make in make.top.equalTo(phoneView.snp.bottom).offset(20) make.left.right.equalToSuperview().inset(36) @@ -106,27 +101,25 @@ class RegisterVC:BaseVC{ make.top.equalTo(codeView.snp.bottom).offset(20) make.left.right.equalToSuperview().inset(36) } - pwdView2.snp.makeConstraints { make in - make.top.equalTo(pwdView.snp.bottom).offset(20) - make.left.right.equalToSuperview().inset(36) - } registerBtn.snp.makeConstraints { make in - make.top.equalTo(pwdView2.snp.bottom).offset(54) - make.left.right.equalToSuperview().inset(51) - make.height.equalTo(55) - } - loginBtn.snp.makeConstraints { make in - make.top.equalTo(registerBtn.snp.bottom).offset(20) + make.top.equalTo(pwdView.snp.bottom).offset(54) make.left.right.equalToSuperview().inset(51) make.height.equalTo(55) } agreeView.snp.makeConstraints { make in - make.bottom.equalToSuperview().inset(62) + make.top.equalTo(pwdView.snp.bottom).offset(10) make.centerX.equalToSuperview() make.height.equalTo(30) } } - + func updateLayout(){ + if regionView.region.name == "中国"{ + phoneView.textField.placeholder = "请输入手机号码" + } + else{ + phoneView.textField.placeholder = "请输入邮箱" + } + } } extension RegisterVC{ @@ -136,7 +129,7 @@ extension RegisterVC{ return } YLprogressHUD.showLoading() - LoginVM.sendCode(phone: text) { [weak self] (model) in + HttpClient.request(CommomApi.sms(phone: text,type: .reg)) {[weak self] (model:ResponseBaseModel, res) in if model.isSuccess{ self?.codeView.codeButton.start() } @@ -156,29 +149,39 @@ extension RegisterVC{ YLprogressHUD.showAutoHiden("请输入密码") return } - guard let pwd2 = pwdView2.textField.value else{ - YLprogressHUD.showAutoHiden("请输入确认密码") + YLprogressHUD.showLoading() + + let plainText = pwd + let key = Date().format(.full4) + let iv = AESEncryption.generateRandomString() + + Logger.debug("pwd: \(pwd)") + Logger.debug("iv: \(iv)") + Logger.debug("key: \(key)") + + guard let encryptedText = AESEncryption.encrypt(plainText, key: key, iv: iv) else { return } - YLprogressHUD.showLoading() -// LoginVM.login(phone: pohne, code: code) {[weak self] result in -// if result.isSuccess{ -// YLprogressHUD.showSuccess { -// self?.view.window?.rootViewController = BaseTC() -// } -// } -// YLprogressHUD.showAutoHiden(result.msg) -// } - } - @objc func loginAction(){ - App.shared.goToPage(LoginVC()) -// guard let pohne = phoneView.textField.text else{ -// YLprogressHUD.showAutoHiden("请输入正确的手机号码") -// return -// } -// guard let code = codeView.textField.text else{ -// YLprogressHUD.showAutoHiden("请输入正确的验证码") -// return + Logger.debug("Encrypted: \(encryptedText)") +// if let decryptedText = AESEncryption.decrypt(encryptedText, key: key, iv: iv) { +// Logger.debug("Decrypted: \(decryptedText)") // } + var params:[String:Any] = [:] + params["phone"] = phone + params["userName"] = Device.current.name + params["password"] = encryptedText + params["nonce"] = iv + params["smsCode"] = code + params["countryId"] = regionView.region.id + + let api = CommomApi.register(param: params) + HttpClient.request(api) { (result:ResponseBaseModel,res) in + if result.isSuccess{ + YLprogressHUD.showSuccess { + App.shared.popPage() + } + } + YLprogressHUD.showAutoHiden(result.msg) + } } } diff --git a/ShenYin/ShenYin/UI/Mine/Login/Controller/SmsLoginVC.swift b/ShenYin/ShenYin/UI/Mine/Login/Controller/SmsLoginVC.swift new file mode 100644 index 0000000..940af6f --- /dev/null +++ b/ShenYin/ShenYin/UI/Mine/Login/Controller/SmsLoginVC.swift @@ -0,0 +1,168 @@ +// +// PwdLoginVC.swift +// ShenYin +// +// Created by liangshi on 2025/9/27. +// + +import UIKit +import DeviceKit + +class SmsLoginVC:BaseVC{ + + let tipsLabel = UILabel() + let bgView = UIView() + let titleLabel = UILabel() + let regionView = RegionView() + let phoneView = CustomInputView() + let codeView = CodeView() + let loginBtn = CustomButton() + let pwdBtn = CustomButton() + let agreeView = AgreeView() + + override func viewDidLoad() { + super.viewDidLoad() + } + override func setupViews(){ + view.backgroundColor = .color(.bgColor) + tipsLabel.do { v in + v.numberOfLines = 0 + v.font = .medium(22) + v.textColor = .rgb(0x121212) + let text = "您好, \n欢迎使用DeepChords" + let stype = NSMutableParagraphStyle() + stype.lineSpacing = 10 + let attrString = NSMutableAttributedString(string: text) + let attr: [NSAttributedString.Key : Any] = [.font: UIFont.medium(22),.paragraphStyle:stype] + attrString.addAttributes(attr, range: NSRange(location: 0, length: attrString.length)) + v.attributedText = attrString + } + + bgView.do { v in + v.backgroundColor = .white + v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: kScreenHei - 244), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 50, height: 50)) + } + titleLabel.do { v in + v.text = "验证码登录" + v.font = .medium(18) + v.textColor = .hexString("#121212") + } + + codeView.do { v in + v.codeButton.addTarget(self, action: #selector(codeButtonAction), for: .touchUpInside) + } + regionView.do { v in + v.didSelected = {[weak self] model in + guard let self = self else {return} + updateLayout() + phoneView.showLeftView = model.isChinese + } + v.region = CountryModel.chinese() + } + phoneView.do { v in + v.textField.text = "13480939445" + } + loginBtn.set(title: "登录",style: .theme1, target: self, action: #selector(loginAction)) + pwdBtn.set(title: "密码登录", style: .theme2,target: self, action: #selector(pwdAction)) + view.addSubviews([tipsLabel,bgView]) + bgView.addSubviews([titleLabel,regionView,phoneView,codeView,loginBtn,pwdBtn,agreeView]) + + } + override func setupLayout(){ + tipsLabel.snp.makeConstraints { make in + make.left.equalToSuperview().inset(28) + make.top.equalTo(kNavBtm + 20) + make.centerX.equalToSuperview() + } + bgView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview().inset(244) + make.bottom.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(34) + make.left.right.equalToSuperview().inset(36) + } + regionView.snp.makeConstraints { make in + make.top.equalToSuperview().offset(82) + make.left.right.equalToSuperview().inset(36) + } + phoneView.snp.makeConstraints { make in + make.top.equalTo(regionView.snp.bottom).offset(20) + make.left.right.equalToSuperview().inset(36) + } + codeView.snp.makeConstraints { make in + make.top.equalTo(phoneView.snp.bottom).offset(20) + make.left.right.equalToSuperview().inset(36) + } + loginBtn.snp.makeConstraints { make in + make.top.equalTo(codeView.snp.bottom).offset(54) + make.left.right.equalToSuperview().inset(51) + make.height.equalTo(55) + } + pwdBtn.snp.makeConstraints { make in + make.top.equalTo(loginBtn.snp.bottom).offset(20) + make.left.right.equalToSuperview().inset(51) + make.height.equalTo(55) + } + agreeView.snp.makeConstraints { make in + make.top.equalTo(codeView.snp.bottom).offset(10) + make.centerX.equalToSuperview() + make.height.equalTo(30) + } + } + func updateLayout(){ + if regionView.region.name == "中国"{ + phoneView.textField.placeholder = "请输入手机号码" + } + else{ + phoneView.textField.placeholder = "请输入邮箱" + } + } +} + +extension SmsLoginVC{ + @objc func pwdAction(){ + App.shared.popPage() + } + @objc func codeButtonAction(){ + guard let text = phoneView.textField.value else{ + YLprogressHUD.showAutoHiden("请输入正确的手机号码") + return + } + YLprogressHUD.showLoading() + HttpClient.request(CommomApi.sms(phone: text,type: .login)) {[weak self] (model:ResponseBaseModel, res) in + if model.isSuccess{ + self?.codeView.codeButton.start() + } + YLprogressHUD.showAutoHiden(model.msg) + } + } + @objc func loginAction(){ + guard let phone = phoneView.textField.value else{ + YLprogressHUD.showAutoHiden("请输入正确的手机号码") + return + } + guard let code = codeView.textField.value else{ + YLprogressHUD.showAutoHiden("请输入验证码") + return + } + YLprogressHUD.showLoading() + var params:[String:Any] = [:] + params["phone"] = phone + params["deviceName"] = Device.current.name + params["deviceCode"] = CacheManager.uuid() + params["smsCode"] = code + params["countryId"] = regionView.region.id + + LoginVM.smsLogin(param: params) { result in + if result.isSuccess{ + YLprogressHUD.showSuccess { + App.shared.didLogin() + } + } + YLprogressHUD.showAutoHiden(result.msg) + } + } +} diff --git a/ShenYin/ShenYin/UI/Mine/Login/View/AgreeView.swift b/ShenYin/ShenYin/UI/Mine/Login/View/AgreeView.swift index a7963b3..e3dab41 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/View/AgreeView.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/View/AgreeView.swift @@ -16,8 +16,8 @@ class AgreeView: BaseView { agreeBtn.do { (v) in v.isSelected = true v.contentMode = .center - v.setImage(UIImage(named: "select_normal"), for: .normal) - v.setImage(UIImage(named: "select_selected"), for: .selected) + v.setImage(UIImage(named: "tip_normal"), for: .normal) + v.setImage(UIImage(named: "tip_selected"), for: .selected) v.addTarget(self, action: #selector(agreeBtnAction), for: .touchUpInside) } agreeTitle.do { (v) in @@ -27,10 +27,10 @@ class AgreeView: BaseView { v.text = "登录并同意" } agreeValue.do { (v) in - v.textColor = .hexString("#121212") + v.textColor = .hexString("#0092E1") v.font = .regular(12) v.textAlignment = .left - v.text = "《隐私权政策》" + v.text = " 《隐私政策》" v.add(target: self, action: #selector(agreementAction)) } andlabel.do { (v) in @@ -40,7 +40,7 @@ class AgreeView: BaseView { v.text = " 和 " } useValue.do { (v) in - v.textColor = .hexString("#121212") + v.textColor = .hexString("#0092E1") v.font = .regular(12) v.textAlignment = .left v.text = "《用户协议》" @@ -77,12 +77,15 @@ class AgreeView: BaseView { agreeBtn.isSelected = !agreeBtn.isSelected } @objc func agreementAction(){ - + let param = BaseWebViewParams(urlStr: "https://www.baidu.com") + let vc = BaseWebViewController(initData: param) + App.shared.goToPage(vc) } @objc func useAction(){ - + let param = BaseWebViewParams(urlStr: "https://www.baidu.com") + let vc = BaseWebViewController(initData: param) + App.shared.goToPage(vc) } - } extension UILabel{ diff --git a/ShenYin/ShenYin/UI/Mine/Login/View/CodeView.swift b/ShenYin/ShenYin/UI/Mine/Login/View/CodeView.swift index 7e05c1b..85c6b63 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/View/CodeView.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/View/CodeView.swift @@ -68,4 +68,15 @@ extension UIView{ make.centerY.equalToSuperview() } } + func addRightLine(height:Float){ + let line = UIView() + line.backgroundColor = .hexString("#666666") + addSubview(line) + line.snp.makeConstraints { make in + make.height.equalTo(height) + make.width.equalTo(1) + make.right.equalToSuperview() + make.centerY.equalToSuperview() + } + } } diff --git a/ShenYin/ShenYin/UI/Mine/Login/View/CustomInputView.swift b/ShenYin/ShenYin/UI/Mine/Login/View/CustomInputView.swift index c639c9e..424a6b0 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/View/CustomInputView.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/View/CustomInputView.swift @@ -15,6 +15,25 @@ class CustomInputView: BaseView { v.textColor = .black v.keyboardType = .phonePad v.placeholder = "请输入手机号码" + + let label = UILabel() + label.textColor = .hexString("#666666") + label.font = .medium(16) + let imageAtt = NSTextAttachment() + imageAtt.image = UIImage(named: "arrow_next") + imageAtt.bounds = CGRect(x: 0, y: 0, width: 8, height: 12) + let text = "+86 " + let textString = NSAttributedString(string: text) + + let muAtt = NSMutableAttributedString() + muAtt.append(textString) + muAtt.append(NSAttributedString(attachment: imageAtt)) + muAtt.append(NSAttributedString(string: " ")) + label.attributedText = muAtt + +// label.backgroundColor = .red + v.leftView = label + v.leftViewMode = .never } inputBgView.backgroundColor = .rgb(0xF3F4F8) @@ -36,4 +55,18 @@ class CustomInputView: BaseView { make.top.bottom.equalToSuperview() } } + + var showLeftView:Bool = false{ + didSet{ + if showLeftView { + textField.leftViewMode = .always + textField.text = "" + } + else{ + textField.leftViewMode = .never + textField.text = "" + } + } + } } + diff --git a/ShenYin/ShenYin/UI/Mine/Login/View/OthersLoginView.swift b/ShenYin/ShenYin/UI/Mine/Login/View/OthersLoginView.swift new file mode 100644 index 0000000..3d8a59e --- /dev/null +++ b/ShenYin/ShenYin/UI/Mine/Login/View/OthersLoginView.swift @@ -0,0 +1,84 @@ +// +// OthersLoginView.swift +// ShenYin +// +// Created by liangshi on 2025/9/27. +// + +import UIKit +class OthersLoginView: BaseView { + let registerLabel = UILabel() + let pwdLabel = UILabel() + let smsLabel = UILabel() + let line1 = UIView() + let line2 = UIView() + + override func setupViews() { + addSubviews([registerLabel,pwdLabel,smsLabel,line1,line2]) + line1.backgroundColor = .hexString("#666666") + line2.backgroundColor = .hexString("#666666") + + registerLabel.do { v in + v.text = " 注册" + v.textColor = .hexString("#666666") + v.font = .regular(12) + v.textAlignment = .center + v.yc.addTap(target: self, action: #selector(registerAction)) + } + pwdLabel.do { v in + v.text = "忘记密码" + v.textColor = .hexString("#666666") + v.font = .regular(12) + v.textAlignment = .center + v.yc.addTap(target: self, action: #selector(forgetAction)) + } + smsLabel.do { v in + v.text = "验证码登录" + v.textColor = .hexString("#666666") + v.font = .regular(12) + v.textAlignment = .center + v.yc.addTap(target: self, action: #selector(smsAction)) + } + } + override func setupLayout() { + pwdLabel.snp.makeConstraints { make in +// make.width.equalTo(78) + make.height.equalToSuperview() + make.center.equalToSuperview() + } + registerLabel.snp.makeConstraints { make in +// make.width.equalTo(78) + make.height.equalToSuperview() + make.centerY.equalToSuperview() + make.right.equalTo(pwdLabel.snp.left).offset(-30) + } + smsLabel.snp.makeConstraints { make in +// make.width.equalTo(78) + make.height.equalToSuperview() + make.centerY.equalToSuperview() + make.left.equalTo(pwdLabel.snp.right).offset(30) + } + line1.snp.makeConstraints { make in + make.height.equalTo(12) + make.width.equalTo(1) + make.right.equalTo(pwdLabel.snp.left).offset(-15) + make.centerY.equalToSuperview() + } + line2.snp.makeConstraints { make in + make.height.equalTo(12) + make.width.equalTo(1) + make.left.equalTo(pwdLabel.snp.right).offset(15) + make.centerY.equalToSuperview() + } + } + @objc func forgetAction(){ + App.shared.goToPage(ForgetVC()) + } + + @objc func registerAction(){ + App.shared.goToPage(RegisterVC()) + } + @objc func smsAction(){ + App.shared.goToPage(SmsLoginVC()) + } +} diff --git a/ShenYin/ShenYin/UI/Mine/Login/View/RegionView.swift b/ShenYin/ShenYin/UI/Mine/Login/View/RegionView.swift new file mode 100644 index 0000000..603f629 --- /dev/null +++ b/ShenYin/ShenYin/UI/Mine/Login/View/RegionView.swift @@ -0,0 +1,90 @@ +// +// AreaView.swift +// ShenYin +// +// Created by liangshi on 2025/9/27. +// +import UIKit + + +class RegionView: BaseView { + let inputBgView = UIView() + let titleLabel = UILabel() + let valeLabel = UILabel() + let arrrowIcon = UIImageView() + + var didSelected:((_ model:CountryModel)->Void)? + var region = CountryModel(){ + didSet{ + valeLabel.text = region.name + didSelected?(region) + } + } + + override func setupViews() { + addSubviews([inputBgView]) + inputBgView.addSubviews([titleLabel,valeLabel,arrrowIcon]) + + inputBgView.backgroundColor = .rgb(0xF3F4F8) + inputBgView.layer.cornerRadius = 10 + inputBgView.layer.masksToBounds = true + inputBgView.yc.addTap(target: self, action: #selector(tapAction)) + titleLabel.do { v in + v.text = "国家/地区" + v.textColor = .hexString("#666666") + v.font = .medium(16) + v.textAlignment = .center + } + valeLabel.do { v in + v.textColor = .hexString("#121212") + v.font = .medium(16) + v.textAlignment = .center + } + arrrowIcon.do { v in + v.image = UIImage(named: "arrow_next") + } + + loadData() + } + override func setupLayout() { + inputBgView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview() + make.height.equalTo(50) + make.bottom.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().inset(20) + make.centerY.equalToSuperview() + } + arrrowIcon.snp.makeConstraints { make in + make.right.equalToSuperview().inset(20) + make.centerY.equalToSuperview() + make.width.equalTo(8) + make.height.equalTo(12) + } + valeLabel.snp.makeConstraints { make in + make.right.equalTo(arrrowIcon.snp.left).offset(-10) + make.centerY.equalToSuperview() + } + } + @objc func tapAction(){ + let vc = ContryListVC() + vc.didSelected = {[weak self] model in + guard let self = self else{return} + region = model + } + App.shared.goToPage(vc) + } + func loadData(){ + + + LoginVM.fetchCountryList {[weak self] result in + guard let self = self else{return} + if result.isSuccess{ + + } + } + } +} diff --git a/ShenYin/ShenYin/UI/Mine/Login/ViewModel/CountryModel.swift b/ShenYin/ShenYin/UI/Mine/Login/ViewModel/CountryModel.swift new file mode 100644 index 0000000..88fc5c4 --- /dev/null +++ b/ShenYin/ShenYin/UI/Mine/Login/ViewModel/CountryModel.swift @@ -0,0 +1,34 @@ +// +// CountryModel.swift +// ShenYin +// +// Created by liangshi on 2025/9/27. +// + +import Foundation +import HandyJSON +public class CountryModelRoot: ResponseBaseModel { + public var data = [CountryModel]() +} +public class CountryModel: HandyJSON { + public var id = "" + public var name = "" + public var language = "" + public var money = "" + public var phonePrefix = "" + + required public init() { } + + var isChinese:Bool{ + return name == "中国" + } + + static func chinese()->CountryModel{ + let model = CountryModel() + model.name = "中国" + model.phonePrefix = "86" + model.id = "1968848875208851458" + + return model + } +} diff --git a/ShenYin/ShenYin/UI/Mine/Login/ViewModel/LoginVM.swift b/ShenYin/ShenYin/UI/Mine/Login/ViewModel/LoginVM.swift index 551f367..81bbaf8 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/ViewModel/LoginVM.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/ViewModel/LoginVM.swift @@ -32,15 +32,32 @@ class LoginModel:ResponseBaseModel { class LoginVM:BaseVM{ - static public func sendCode(phone:String, completion:@escaping (_ result:ResponseBaseModel) ->Void) { - HttpClient.instance.request(CommomApi.sms(phone: phone,type: .login)) { (model:ResponseBaseModel, res) in + static let shared = LoginVM() + var countryList = [CountryModel]() + + static public func login(param:[String:Any], completion:@escaping (_ result:LoginModel) ->Void) { + let api = CommomApi.login(param: param) + HttpClient.request(api) { (model:LoginModel,res) in + if model.isSuccess{ + CacheManager.shared.login(token: model.data) + } completion(model) } } - static public func login(phone:String,code:String, completion:@escaping (_ result:LoginModel) ->Void) { - HttpClient.instance.request(CommomApi.login(phone: phone,code: code)) { (model:LoginModel, res) in + static public func smsLogin(param:[String:Any], completion:@escaping (_ result:LoginModel) ->Void) { + let api = CommomApi.smsLogin(param: param) + HttpClient.request(api) { (model:LoginModel,res) in + if model.isSuccess{ + CacheManager.shared.login(token: model.data) + } + completion(model) + } + } + + static public func fetchCountryList(completion:@escaping (_ result:CountryModelRoot) ->Void) { + HttpClient.request(CommomApi.countryList) { (model:CountryModelRoot, res) in if model.isSuccess{ - UserModel.shared.token = model.data + LoginVM.shared.countryList = model.data } completion(model) } diff --git a/ShenYin/ShenYin/UI/Mine/Login/ViewModel/UserModel.swift b/ShenYin/ShenYin/UI/Mine/Login/ViewModel/UserModel.swift index 73a0e75..c580355 100644 --- a/ShenYin/ShenYin/UI/Mine/Login/ViewModel/UserModel.swift +++ b/ShenYin/ShenYin/UI/Mine/Login/ViewModel/UserModel.swift @@ -6,13 +6,38 @@ // - - - class UserModel { - static let shared = UserModel() - var token:String? + static let cacheKey = "Login" + var token:String? { + didSet{ + saveToken(text: token) + } + } var isLogin:Bool{ return token != nil } + func loadCache(){ + self.token = getToken() + if self.token != nil { + } + } +} +extension UserModel{ + private func getToken()->String?{ + if let value = UserDefaults.standard.value(forKey: UserModel.cacheKey),let token = value as? String{ + return token + } + return nil + + } + private func saveToken(text:String?){ + if let text = text { + UserDefaults.standard.set(text, forKey: UserModel.cacheKey) + UserDefaults.standard.synchronize() + } + else{ + UserDefaults.standard.removeObject(forKey: UserModel.cacheKey) + UserDefaults.standard.synchronize() + } + } } diff --git a/ShenYin/ShenYin/UI/Mine/MoreSetVC.swift b/ShenYin/ShenYin/UI/Mine/MoreSetVC.swift index 3008cda..f456ff3 100644 --- a/ShenYin/ShenYin/UI/Mine/MoreSetVC.swift +++ b/ShenYin/ShenYin/UI/Mine/MoreSetVC.swift @@ -63,13 +63,26 @@ class MoreSetVC: BaseVC{ } } @objc func swictAction(){ - + CustomAlert.showWith(title: "提示", messgage: "确定要切换账号吗?", cancelCallback: nil) { + CacheManager.shared.logout() + } } @objc func logoutAction(){ - + CustomAlert.showWith(title: "提示", messgage: "确定要退出登录吗?", cancelCallback: nil) { + CacheManager.shared.logout() + } } @objc func deactivateAction(){ - + CustomAlert.showWith(title: "提示", messgage: "真的要注销账号吗?", cancelCallback: nil) { + HttpClient.request(.deactivate) { (result:ResponseBaseModel,res) in + if result.isSuccess{ + YLprogressHUD.showSuccess { + CacheManager.shared.logout() + } + } + YLprogressHUD.showAutoHiden(result.msg) + } + } } } diff --git a/ShenYin/ShenYin/UI/common/Cache/CacheManager.swift b/ShenYin/ShenYin/UI/common/Cache/CacheManager.swift index 49d9de8..788934d 100644 --- a/ShenYin/ShenYin/UI/common/Cache/CacheManager.swift +++ b/ShenYin/ShenYin/UI/common/Cache/CacheManager.swift @@ -14,5 +14,48 @@ class CacheManager{ self.currentDevice = device DeviceCache.shared.saveDevice(device) } + + var user = UserModel() + + init(){ + user.loadCache() + tokenIsValid() + } } +extension CacheManager{ + func login(token:String){ + user.token = token + NotificationManager.post(type: .login, objtect: nil) + + } + func logout(){ + user.token = nil + NotificationManager.post(type: .logout, objtect: nil) + App.shared.goToLogin() + } + func tokenIsValid(){ + HttpClient.request(CommomApi.token) { [weak self](model:ResponseBaseModel,res) in + guard let self = self else{return} + if model.isSuccess{ + + } + else{ + logout() + } + } + } +} + + +extension CacheManager{ + static func uuid()->String{ + if let value = UserDefaults.standard.value(forKey: "uuid"),let uuid = value as? String{ + return uuid + } + let uuid = UUID().uuidString + UserDefaults.standard.setValue(uuid, forKey: "uuid") + UserDefaults.standard.synchronize() + return uuid + } +} diff --git a/ShenYin/ShenYin/UI/common/Cache/TipsCache.swift b/ShenYin/ShenYin/UI/common/Cache/TipsCache.swift index dc5ce48..c8958a2 100644 --- a/ShenYin/ShenYin/UI/common/Cache/TipsCache.swift +++ b/ShenYin/ShenYin/UI/common/Cache/TipsCache.swift @@ -11,6 +11,7 @@ class TipsCache{ static func needShow(type:RecordTipsType,show:Bool){ UserDefaults.standard.set(show, forKey: type.title) + UserDefaults.standard.synchronize() } static func needShow(type:RecordTipsType)->Bool{ if let value = UserDefaults.standard.value(forKey: type.title){ diff --git a/ShenYin/ShenYin/UI/common/NotificationManager.swift b/ShenYin/ShenYin/UI/common/NotificationManager.swift index 50771da..21b1732 100644 --- a/ShenYin/ShenYin/UI/common/NotificationManager.swift +++ b/ShenYin/ShenYin/UI/common/NotificationManager.swift @@ -9,11 +9,17 @@ import Foundation enum NotificationType:String{ case deviceValidChange + case login + case logout var value:String{ switch self { case .deviceValidChange: return "deviceValidChange" + case .login: + return "login" + case .logout: + return "logout" default: return "unknown" } diff --git a/ShenYin/podfile b/ShenYin/podfile index 426028d..e7c4132 100644 --- a/ShenYin/podfile +++ b/ShenYin/podfile @@ -24,7 +24,8 @@ target 'ShenYin' do pod 'JXSegmentedView' pod 'JXPagingView/Paging' ## pod 'Alamofire' - pod 'Moya'#网络 +# pod 'Moya'#网络 + pod 'SwiftHTTP' pod 'swiftScan'#二维码 pod 'TZImagePickerController'#图片选择 pod 'netfox'#调试 @@ -32,6 +33,8 @@ target 'ShenYin' do pod 'SocketRocket'#socket,AI用到 pod 'DGActivityIndicatorView'#扫描雷达 + pod 'DeviceKit', '~> 5.4.0' + pod 'CryptoSwift' # pod 'MultiSlider' # pod 'DSWaveformImage'