PODS:
- - Alamofire (5.10.2)
+ - CryptoSwift (1.8.4)
+ - DeviceKit (5.4.0)
- DGActivityIndicatorView (2.1.1)
- FDFullscreenPopGesture (1.1)
- FSPagerView (0.8.3)
- 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)
- 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):
- YYText (1.0.7)
DEPENDENCIES:
+ - CryptoSwift
+ - DeviceKit (~> 5.4.0)
- DGActivityIndicatorView
- FDFullscreenPopGesture
- FSPagerView
- JXSegmentedView
- Kingfisher (~> 6.0)
- MJRefresh
- - Moya
- netfox
- RealmSwift
- SnapKit
- SocketRocket
- SVProgressHUD
- SwiftDate
+ - SwiftHTTP
- swiftScan
- TabPageViewController
- TZImagePickerController
SPEC REPOS:
https://gitee.com/mirrors/CocoaPods-Specs.git:
- - Alamofire
+ - CryptoSwift
+ - DeviceKit
- DGActivityIndicatorView
- FDFullscreenPopGesture
- FSPagerView
- JXSegmentedView
- Kingfisher
- MJRefresh
- - Moya
- netfox
- Realm
- RealmSwift
- SocketRocket
- SVProgressHUD
- SwiftDate
+ - SwiftHTTP
- swiftScan
- TabPageViewController
- TZImagePickerController
- YYText
SPEC CHECKSUMS:
- Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
+ CryptoSwift: e64e11850ede528a02a0f3e768cec8e9d92ecb90
+ DeviceKit: bd34bb1766d926c3cc5a5f6e3e9a6dd10148b805
DGActivityIndicatorView: ff2c76073d79692f724863c8dd38685866a03cb6
FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
FSPagerView: 670405b2f18e2a87fa37f20b00de783e562c25a8
JXSegmentedView: cd73555ce2134d1656db2cb383ba9c2f36fb5078
Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74
MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
- Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
netfox: 9d5cc727fe7576c4c7688a2504618a156b7d44b7
Realm: 853e5089d6042dff807bda000277eadfe2da93d2
RealmSwift: f33c19577cefcbf681345d721fcbc7b42be4c949
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
// 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<CommomApi>()
- func request<T: HandyJSON>(_ 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<CommomApi>()
+//
+// func request<T: HandyJSON>(_ 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********************")
+// }
+// }
+// }
+//
+//}
--- /dev/null
+//
+// 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<T: HandyJSON>(_ 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<T: HandyJSON>(_ 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) }
+}
public var code = -1
public var msg = "请求失败"
-
+ public var success = false
- public var isSuccess: Bool { return code == 20000}
+ public var isSuccess: Bool { return success}
}
<string>bluetooth-central</string>
<string>audio</string>
</array>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
</dict>
</plist>
--- /dev/null
+//
+// 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..<length {
+ let randomValue = Int.random(in: 0...letters.count - 1)
+ randomString.append(letters[letters.index(letters.startIndex, offsetBy: randomValue)])
+ }
+ return randomString
+ }
+}
/// e.g. 2020-01-01
static let short: Format = .init("yyyy-MM-dd")
+
/// e.g. 2020年01月01日
static let short1: Format = .init("yyy年MM月dd日")
static let full1: Format = .init("yyyy年MM月dd日 HH:mm:ss.SSS")
static let full2: Format = .init("yyyy-MM-ddTHH:mm")
static let full3: Format = .init("yyyy-MM-dd HH:mm")
+ static let full4: Format = .init("yyyyMMdd00000000")
}
/// 格式化成本地时间
//// Created by apple on 2020/11/14.
////
//
-//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()
-// }
-//
-//
-// deinit {
-// webView.removeObserver(self, forKeyPath: "canGoBack")
-// webView.removeObserver(self, forKeyPath: "estimatedProgress")
-// webView.removeObserver(self, forKeyPath: "title")
-// }
-// override func viewDidLoad() {
-// super.viewDidLoad()
-// setupLayout()
-// setupStyle()
-// }
-//
-// 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: - ********* 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)
+ }
+}
+
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)
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()
+// }
}
}
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{
// return !BleManager.shared.isConnetd
}
}
+
+
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)
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.
App.shared.window = window
window?.rootViewController = BaseTC()
-// window?.rootViewController = UINavigationController(rootViewController: ChatVC())
+ window?.rootViewController = UINavigationController(rootViewController: LoginVC())
AppLaunch.start()
}
--- /dev/null
+//
+// 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)
+ }
+}
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)
//
import UIKit
+import DeviceKit
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() {
}
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(){
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)
//
-// 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()
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
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()
}
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)
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{
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()
}
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)
+ }
}
}
--- /dev/null
+//
+// 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)
+ }
+ }
+}
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
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
v.text = " 和 "
}
useValue.do { (v) in
- v.textColor = .hexString("#121212")
+ v.textColor = .hexString("#0092E1")
v.font = .regular(12)
v.textAlignment = .left
v.text = "《用户协议》"
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{
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()
+ }
+ }
}
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)
make.top.bottom.equalToSuperview()
}
}
+
+ var showLeftView:Bool = false{
+ didSet{
+ if showLeftView {
+ textField.leftViewMode = .always
+ textField.text = ""
+ }
+ else{
+ textField.leftViewMode = .never
+ textField.text = ""
+ }
+ }
+ }
}
+
--- /dev/null
+//
+// 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())
+ }
+}
--- /dev/null
+//
+// 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{
+
+ }
+ }
+ }
+}
--- /dev/null
+//
+// 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
+ }
+}
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)
}
//
-
-
-
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()
+ }
+ }
}
}
}
@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)
+ }
+ }
}
}
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
+ }
+}
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){
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"
}
pod 'JXSegmentedView'
pod 'JXPagingView/Paging'
## pod 'Alamofire'
- pod 'Moya'#网络
+# pod 'Moya'#网络
+ pod 'SwiftHTTP'
pod 'swiftScan'#二维码
pod 'TZImagePickerController'#图片选择
pod 'netfox'#调试
pod 'SocketRocket'#socket,AI用到
pod 'DGActivityIndicatorView'#扫描雷达
+ pod 'DeviceKit', '~> 5.4.0'
+ pod 'CryptoSwift'
# pod 'MultiSlider'
# pod 'DSWaveformImage'