2 İşlemeler 9c71d15b4e ... 307a312b50

Yazar SHA1 Mesaj Tarih
  zhujieshan 307a312b50 feat:接入中台埋点 3 ay önce
  zhujieshan d7c7b1faf8 feat:接入中台埋点 3 ay önce
34 değiştirilmiş dosya ile 648 ekleme ve 282 silme
  1. BIN
      .DS_Store
  2. 20 0
      QuickSearchLocation.xcodeproj/project.pbxproj
  3. 1 1
      QuickSearchLocation/Classes/Common/Tool/QSLGravityManager.swift
  4. 10 11
      QuickSearchLocation/Classes/Common/Tool/QSLJumpManager.swift
  5. 2 1
      QuickSearchLocation/Classes/Common/Tool/QSLStatisticsUserTimeManager.swift
  6. 2 2
      QuickSearchLocation/Classes/Common/View/QSLAlertView.swift
  7. 5 5
      QuickSearchLocation/Classes/Common/View/QSLPrivacyAlertView.swift
  8. 57 0
      QuickSearchLocation/Classes/EventHandle/QSEventHandle.swift
  9. 77 0
      QuickSearchLocation/Classes/EventHandle/QSLCentralEventManager.swift
  10. 101 0
      QuickSearchLocation/Classes/EventHandle/QSLCentralNetwork.swift
  11. 4 1
      QuickSearchLocation/Classes/Main/AppDelegate.swift
  12. 5 5
      QuickSearchLocation/Classes/Main/CustomTabBarController.swift
  13. 15 18
      QuickSearchLocation/Classes/Pages/QSLAdd/Controller/QSLAddController.swift
  14. 14 17
      QuickSearchLocation/Classes/Pages/QSLContact/Controller/QSLContactController.swift
  15. 2 4
      QuickSearchLocation/Classes/Pages/QSLContact/View/QSLContactAddAlertView.swift
  16. 2 2
      QuickSearchLocation/Classes/Pages/QSLFriend/Cell/QSLFriendTableViewCell.swift
  17. 11 17
      QuickSearchLocation/Classes/Pages/QSLFriend/Controller/QSLFriendController.swift
  18. 3 5
      QuickSearchLocation/Classes/Pages/QSLFriend/View/QSLFriendRemarkAlertView.swift
  19. 7 6
      QuickSearchLocation/Classes/Pages/QSLGuide/QSLGuideController.swift
  20. 2 2
      QuickSearchLocation/Classes/Pages/QSLHome/Cell/QSLHomeFriendTableViewCell.swift
  21. 7 6
      QuickSearchLocation/Classes/Pages/QSLHome/Controller/QSLHomeController.swift
  22. 2 1
      QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeFriendView.swift
  23. 17 20
      QuickSearchLocation/Classes/Pages/QSLLogin/Controller/QSLLoginViewController.swift
  24. 4 5
      QuickSearchLocation/Classes/Pages/QSLMessage/Controller/QSLMessageController.swift
  25. 2 2
      QuickSearchLocation/Classes/Pages/QSLMessage/QSLRequest/QSLRequestCell.swift
  26. 3 4
      QuickSearchLocation/Classes/Pages/QSLMessage/QSLRequest/QSLRequestController.swift
  27. 2 2
      QuickSearchLocation/Classes/Pages/QSLMessage/View/QSLMessageHeaderView.swift
  28. 8 17
      QuickSearchLocation/Classes/Pages/QSLMine/Controller/QSLMineController.swift
  29. 6 5
      QuickSearchLocation/Classes/Pages/QSLMine/QSQuickLogon/QSQuickLogonHandle.swift
  30. 8 22
      QuickSearchLocation/Classes/Pages/QSLRoad/Controller/QSLRoadController.swift
  31. 10 14
      QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLActivityVipVC.swift
  32. 54 56
      QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLVipController.swift
  33. 2 5
      QuickSearchLocation/Macro/QSLApi.swift
  34. 183 26
      QuickSearchLocation/Tools/QSLDeviceTool.swift

BIN
.DS_Store


+ 20 - 0
QuickSearchLocation.xcodeproj/project.pbxproj

@@ -120,8 +120,11 @@
 		FE8360BB2D03002D00978E03 /* QSLMapPointModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8360BA2D03002D00978E03 /* QSLMapPointModel.swift */; };
 		FE8360BD2D068DCB00978E03 /* QSLMemberModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8360BC2D068DCB00978E03 /* QSLMemberModel.swift */; };
 		FE8360C02D06D33500978E03 /* QSLAppInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8360BF2D06D33500978E03 /* QSLAppInfoController.swift */; };
+		FE86455D2E9A5E8E008A78D4 /* QSLCentralNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE86455C2E9A5E8E008A78D4 /* QSLCentralNetwork.swift */; };
+		FE86455F2E9CA866008A78D4 /* QSLCentralEventManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE86455E2E9CA866008A78D4 /* QSLCentralEventManager.swift */; };
 		FE9139C92DE6B018001A8E42 /* QSLVipMostGoodCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9139C82DE6B018001A8E42 /* QSLVipMostGoodCell.swift */; };
 		FE94B4F42D23F09100D2B001 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE94B4F32D23F09100D2B001 /* LoadingViewController.swift */; };
+		FEAF6BD22E9A0ED200920311 /* QSEventHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEAF6BD12E9A0ED200920311 /* QSEventHandle.swift */; };
 		FEC010E72D9E8B06008B8B0A /* QSLSubscriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC010E62D9E8AFE008B8B0A /* QSLSubscriptionModel.swift */; };
 		FEC3D9562E8276CB007164A9 /* QSLActivityVipVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC3D9552E8276CB007164A9 /* QSLActivityVipVC.swift */; };
 		FEC3D9582E82973C007164A9 /* QSLActivityVipCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC3D9572E82973C007164A9 /* QSLActivityVipCell.swift */; };
@@ -260,8 +263,11 @@
 		FE8360BA2D03002D00978E03 /* QSLMapPointModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLMapPointModel.swift; sourceTree = "<group>"; };
 		FE8360BC2D068DCB00978E03 /* QSLMemberModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLMemberModel.swift; sourceTree = "<group>"; };
 		FE8360BF2D06D33500978E03 /* QSLAppInfoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLAppInfoController.swift; sourceTree = "<group>"; };
+		FE86455C2E9A5E8E008A78D4 /* QSLCentralNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLCentralNetwork.swift; sourceTree = "<group>"; };
+		FE86455E2E9CA866008A78D4 /* QSLCentralEventManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLCentralEventManager.swift; sourceTree = "<group>"; };
 		FE9139C82DE6B018001A8E42 /* QSLVipMostGoodCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLVipMostGoodCell.swift; sourceTree = "<group>"; };
 		FE94B4F32D23F09100D2B001 /* LoadingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingViewController.swift; sourceTree = "<group>"; };
+		FEAF6BD12E9A0ED200920311 /* QSEventHandle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSEventHandle.swift; sourceTree = "<group>"; };
 		FEC010E62D9E8AFE008B8B0A /* QSLSubscriptionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLSubscriptionModel.swift; sourceTree = "<group>"; };
 		FEC3D9552E8276CB007164A9 /* QSLActivityVipVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLActivityVipVC.swift; sourceTree = "<group>"; };
 		FEC3D9572E82973C007164A9 /* QSLActivityVipCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLActivityVipCell.swift; sourceTree = "<group>"; };
@@ -487,6 +493,7 @@
 		04F33BBD2BC63B2F003E2111 /* Classes */ = {
 			isa = PBXGroup;
 			children = (
+				FE8645622E9CB427008A78D4 /* EventHandle */,
 				FEEB37CB2E28CCF900BFFD7D /* AppleAD */,
 				FE8360912D00308E00978E03 /* Network */,
 				FE5B423D2CF45926000AACCB /* Common */,
@@ -904,6 +911,16 @@
 			path = QSLAppInfo;
 			sourceTree = "<group>";
 		};
+		FE8645622E9CB427008A78D4 /* EventHandle */ = {
+			isa = PBXGroup;
+			children = (
+				FE86455C2E9A5E8E008A78D4 /* QSLCentralNetwork.swift */,
+				FEAF6BD12E9A0ED200920311 /* QSEventHandle.swift */,
+				FE86455E2E9CA866008A78D4 /* QSLCentralEventManager.swift */,
+			);
+			path = EventHandle;
+			sourceTree = "<group>";
+		};
 		FEEB37CB2E28CCF900BFFD7D /* AppleAD */ = {
 			isa = PBXGroup;
 			children = (
@@ -1047,6 +1064,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				FEAF6BD22E9A0ED200920311 /* QSEventHandle.swift in Sources */,
 				04F33BC92BC67100003E2111 /* QSLColor.swift in Sources */,
 				FE638A9E2D0709C900858121 /* QSLPrivacyAlertView.swift in Sources */,
 				FE8360902CFFFAD600978E03 /* QSLAlertView.swift in Sources */,
@@ -1077,6 +1095,7 @@
 				FE638AA42D0978B100858121 /* QSLVipManager.swift in Sources */,
 				04F33BE92BC69EA5003E2111 /* QSLConst.swift in Sources */,
 				FE8360B52D029BA800978E03 /* QSLMapMessageModel.swift in Sources */,
+				FE86455D2E9A5E8E008A78D4 /* QSLCentralNetwork.swift in Sources */,
 				FE8360952D003D8F00978E03 /* QSLApi.swift in Sources */,
 				04F33BEE2BC78B91003E2111 /* QSLUserModel.swift in Sources */,
 				FE8360862CF86E2900978E03 /* QSLVipCommentCellView.swift in Sources */,
@@ -1098,6 +1117,7 @@
 				FE8360A22D00814000978E03 /* QSLPopViewCell.swift in Sources */,
 				04B666BD2BC7D15A0020BFBD /* QSLHomeViewModel.swift in Sources */,
 				04F33BA62BC6367C003E2111 /* AppDelegate.swift in Sources */,
+				FE86455F2E9CA866008A78D4 /* QSLCentralEventManager.swift in Sources */,
 				FEC010E72D9E8B06008B8B0A /* QSLSubscriptionModel.swift in Sources */,
 				FE94B4F42D23F09100D2B001 /* LoadingViewController.swift in Sources */,
 				04F33BCF2BC675C5003E2111 /* UIApplication+Extension.swift in Sources */,

+ 1 - 1
QuickSearchLocation/Classes/Common/Tool/QSLGravityManager.swift

@@ -50,7 +50,7 @@ class QSLGravityManager {
             // 检查订单
             QSLBaseManager.shared.initPayCheck()
             
-            gravityInstance?.track(QSLGravityConst.launch_show)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.launch_show)
             
             if let clientId = gravityInstance?.getCurrentClientId() {
                 QSLBaseManager.shared.uploadClientId(clientId: clientId)

+ 10 - 11
QuickSearchLocation/Classes/Common/Tool/QSLJumpManager.swift

@@ -40,13 +40,13 @@ extension QSLJumpManager {
                 return
             }
             if let currentWindow = UIApplication.keyWindow {
-                gravityInstance?.track(QSLGravityConst.new_vip_retention_show, properties: ["trigger_type":"close_vip_center"])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_show, eventProps: ["trigger_type":"close_vip_center"])
                 QSLRetainPopUpAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure:  { [weak self] in
                     QSLCountdownManager.shared.selectGood = yearGood
                     self?.unlockBtnAction()
-                    gravityInstance?.track(QSLGravityConst.new_vip_retention_click, properties: ["button":"continue_payment"])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_click, eventProps: ["button":"continue_payment"])
                 },closeBtnClosure: {
-                    gravityInstance?.track(QSLGravityConst.new_vip_retention_click, properties: ["button":"close"])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_click, eventProps: ["button":"close"])
                 })
             }
         }
@@ -69,16 +69,16 @@ extension QSLJumpManager {
                 if status == .success {
                     QSLLoading.success(text: "支付成功")
                     
-                    gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(selectGood.amount)])
-                    //支付成功埋点
-                    gravityInstance?.track(QSLGravityConst.vip_submit_success, properties: ["id": 01001])
-                    
                     //弹出是否好评的弹窗
                     //QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(QSLGuideusersToCommentType.member)
                     
                     // 引力传递支付事件
                     gravityInstance?.trackPayEvent(withAmount: Int32(selectGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: selectGood.name, withPayMethod: "apple")
                     
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(selectGood.amount)])
+   
+                    QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_submit_success, eventProps: ["id": 01001])
+                    
                     DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                         NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
                         
@@ -87,13 +87,12 @@ extension QSLJumpManager {
                         }
                     }
                     
-                    
+                
                 } else if status == .cancel {
-                    gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
                     QSLLoading.error(text: "支付取消")
                 } else if status == .fail {
-                    gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
-                    gravityInstance?.track(QSLGravityConst.vip_fail)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
                     QSLLoading.error(text: "支付失败")
                 } 
             }

+ 2 - 1
QuickSearchLocation/Classes/Common/Tool/QSLStatisticsUserTimeManager.swift

@@ -86,7 +86,8 @@ class QSLStatisticsUserTimeManager {
         ]
         
         // 通过GravityEngine上报事件
-        gravityInstance?.track(QSLGravityConst.usage_collect_accumulatedTime, properties: properties)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.usage_collect_accumulatedTime, eventProps: properties)
+
         print("时长上报成功")
         self.totalUsageTime = 0  // 重置累计时长
         self.userDefaults.set(Date().timeIntervalSince1970, forKey: Keys.lastUploadTime)

+ 2 - 2
QuickSearchLocation/Classes/Common/View/QSLAlertView.swift

@@ -123,7 +123,7 @@ class QSLAlertView: UIView {
         }
         view.addSubview(window)
         
-        gravityInstance?.track(QSLGravityConst.friend_delete_show)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_delete_show)
         
         UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) {
             window.backgroundColor = .hexStringColor(hexString: "#000000", alpha: 0.7)
@@ -163,7 +163,7 @@ class QSLAlertView: UIView {
         }
         view.addSubview(window)
         
-        gravityInstance?.track(QSLGravityConst.friend_delete_show)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_delete_show)
         
         UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) {
             window.backgroundColor = .hexStringColor(hexString: "#000000", alpha: 0.7)

+ 5 - 5
QuickSearchLocation/Classes/Common/View/QSLPrivacyAlertView.swift

@@ -121,7 +121,7 @@ class QSLPrivacyAlertView: UIView {
         window.privacyBlock = privacyClosure
         view.addSubview(window)
         
-        gravityInstance?.track(QSLGravityConst.privacy_show)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.privacy_show)
         
         UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) {
             window.backgroundColor = .hexStringColor(hexString: "#000000", alpha: 0.7)
@@ -143,9 +143,9 @@ class QSLPrivacyAlertView: UIView {
         if isFirstClick {
             self.firstButton.title("不同意并退出")
             isFirstClick = false
-            gravityInstance?.track(QSLGravityConst.privacy_disagree)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.privacy_disagree)
         } else {
-            gravityInstance?.track(QSLGravityConst.privacy_second_disagree)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.privacy_second_disagree)
             exit(0)
         }
     }
@@ -153,9 +153,9 @@ class QSLPrivacyAlertView: UIView {
     // 确认按钮点击事件
     @objc func secondBtnAction() {
         if isFirstClick {
-            gravityInstance?.track(QSLGravityConst.privacy_agree)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.privacy_agree)
         } else {
-            gravityInstance?.track(QSLGravityConst.privacy_second_agree)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.privacy_second_agree)
         }
         if let secondBtnClosure = self.secondBtnClosure {
             secondBtnClosure()

+ 57 - 0
QuickSearchLocation/Classes/EventHandle/QSEventHandle.swift

@@ -0,0 +1,57 @@
+//
+//  QSEventHandle.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/11.
+//
+
+import UIKit
+import GravityEngineSDK
+
+class QSEventHandle: NSObject {
+    
+    static func gravityPush(eventName: String, eventProps: [String:Any] = [:]){
+        GravityEngineSDK.sharedInstance()?.track(eventName, properties: eventProps)
+    }
+
+    /// 上传单次事件到服务器
+    ///
+    /// - Parameters:
+    ///   - eventType: 事件类型(如 "track")暂时只有track 可以不传
+    ///   - eventName: 事件名称(如 "vip_center_exposure")
+    ///   - eventProps: 事件属性(字典形式,如 `["is_member": false, "entry_point": "open_now"]`)
+    ///
+    /// - Example:
+    ///   ```
+    ///   eventPush(
+    ///       eventType: "track",
+    ///       eventName: "button_click",
+    ///       eventProps: ["button_id": "submit"]
+    ///   )
+    ///   ```
+    ///
+    static func eventPush(eventType: String = "track", eventName: String, eventProps: [String:Any] = [:]){
+        GravityEngineSDK.sharedInstance()?.track(eventName, properties: eventProps)
+        QSLCentralEventManager.shared.uploadEvent(eventType: "track", eventName: eventName, eventProps: eventProps)
+    }
+    
+    /// 上传多次事件到服务器
+    ///
+    /// - Parameters:
+    ///   - eventType: 事件类型(如 "track")暂时只有track 可以不传
+    ///   - eventName: 事件名称(如 "vip_center_exposure")
+    ///   - eventProps: 事件属性(字典数组形式,如 `[["is_member": false, "entry_point": "open_now"],...]`)
+    ///
+    /// - Example:
+    ///   ```
+    ///   eventPush(
+    ///       eventType: "track",
+    ///       eventName: "button_click",
+    ///       eventProps: ["button_id": "submit"]
+    ///   )
+    ///   ```
+    ///
+    static func eventArrPush(eventType: String = "track", eventName: String, eventPropsArr: [[String:Any]] = []){
+        QSLCentralEventManager.shared.uploadEvent(eventType: "track", eventName: eventName, eventPropsArr: eventPropsArr)
+    }
+}

+ 77 - 0
QuickSearchLocation/Classes/EventHandle/QSLCentralEventManager.swift

@@ -0,0 +1,77 @@
+//
+//  QSLCentralEventManager.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/13.
+//
+
+import Foundation
+import UIKit
+import AppTrackingTransparency
+import AdSupport
+import StoreKit
+import AdServices
+
+class QSLCentralEventManager {
+    // 中台
+    static let centralUrl = "https://project-api.atmob.com"
+    
+    static let appKey = "a3794176067047728826578522a34e5f"
+    
+    static let bundleId = "com.manbu.shouji"
+    
+    static let event_push = "/central/open/v1/event/push"
+    
+    static let ssid_detail = "/central/open/v1/ssid/detail"
+    
+    static let shared = QSLCentralEventManager()
+    
+    private init() {}
+
+}
+
+extension QSLCentralEventManager {
+
+    func uploadEvent(eventType: String, eventName: String, eventProps: [String:Any]) {
+        
+        let timestamp = Int(Date.milliStamp) ?? 0
+        var currentPropos = eventProps;
+        currentPropos["$snid"] = QSLDeviceTool.shared.sessionId
+
+        baseEventUpload(param: ["ak":QSLCentralEventManager.appKey,"cp":baseDic(),"ft":timestamp, "es":[["ti":timestamp, "ty":eventType, "ev":eventName,"pr":currentPropos]]])
+    }
+    
+    func uploadEvent(eventType: String, eventName: String, eventPropsArr: [[String:Any]]) {
+  
+        let timestamp = Int(Date.milliStamp) ?? 0
+        
+        baseEventUpload(param: ["ak":QSLCentralEventManager.appKey,"cp":baseDic(),"ft":timestamp, "es":eventPropsArr])
+    }
+    
+    func baseDic() -> [String:Any]{
+        // 获取包名
+        var bundleId = QSLCentralEventManager.bundleId
+        if let bundleIdentifier = Bundle.main.bundleIdentifier {
+            bundleId = bundleIdentifier
+        }
+
+        var cpDict : [String : Any] = ["$aplf":2, "$chnl":"Appstore"]
+        cpDict["$pkg"] = bundleId
+        cpDict["$aver"] = QSLDeviceTool.shared.appVersionName
+        cpDict["$avec"] = QSLDeviceTool.shared.appVersionCode
+        cpDict["$modl"] = QSLDeviceTool.shared.phoneModel
+        cpDict["$osv"] = QSLDeviceTool.shared.OSVersion
+        cpDict["$idfa"] = QSLDeviceTool.shared.idfa
+        cpDict["$idfv"] = QSLDeviceTool.shared.idfv
+        
+        return cpDict
+    }
+    
+    func baseEventUpload(param: [String:Any]) {
+        QSLCentralNetwork().request(.eventPush(dict: param)) { response in
+            debugPrint("上报事件成功")
+        } fail: { code, error in
+            debugPrint("上报事件失败")
+        }
+    }
+}

+ 101 - 0
QuickSearchLocation/Classes/EventHandle/QSLCentralNetwork.swift

@@ -0,0 +1,101 @@
+//
+//  QSLCentralNetwork.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/11.
+//
+
+import UIKit
+import Foundation
+import Moya
+import MoyaMapper
+
+enum QSLCentralNetworkAPI {
+    case getEventPushToken(dict: [String : Any])
+    case eventPush(dict: [String : Any])
+}
+
+let QSLCentralNetworkProvider = MoyaProvider<QSLCentralNetworkAPI>(plugins: [networkLoggerPlugin, MoyaMapperPlugin(NetParameter())])
+
+
+extension QSLCentralNetworkAPI: TargetType {
+    // 地址
+    public var baseURL: URL {
+        return URL(string: QSLCentralEventManager.centralUrl)!
+    }
+    
+    var path: String {
+        switch self {
+        case .eventPush: return QSLCentralEventManager.event_push
+        case .getEventPushToken: return QSLCentralEventManager.ssid_detail
+        }
+    }
+    
+    var method: Moya.Method { return .post }
+    
+    var task: Task {
+        var parameters : [String:Any] = [:]
+        switch self {
+        case let .eventPush(Dict):
+            for (key, value) in Dict {
+                parameters[key] = value
+            }
+        case let .getEventPushToken(Dict):
+            for (key, value) in Dict {
+                parameters[key] = value
+            }
+        }
+        
+        debugPrint(parameters)
+        return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
+    }
+    
+    var sampleData: Data { return "".data(using: String.Encoding.utf8)! }
+    
+    var headers: [String : String]? {
+        return ["AppKey": QSLCentralEventManager.appKey]
+    }
+}
+
+struct QSLCentralNetwork {
+    
+    ///先添加一个闭包用于成功时后台返回数据的回调
+    typealias completeCallback = ((Response) -> (Void))
+    typealias failCallback = ((Int, String) -> (Void))
+    
+    func request(_ target: QSLCentralNetworkAPI, success: @escaping completeCallback, fail: @escaping failCallback){
+
+        QSLCentralNetworkProvider.request(target) { (result) in
+            
+            switch result {
+            case let .success(response):
+                
+                if response.statusCode == 200 {
+                    if response.toJSON(modelKey: "code") == 0 {
+                        success(response)
+                    } else {
+                        fail(response.toJSON(modelKey: "code").intValue, response.toJSON(modelKey: "msg").stringValue)
+                    }
+                } else if response.statusCode == 1006 {
+                    if QSLBaseManager.shared.isLogin() {
+                        QSLBaseManager.shared.logOut()
+                    }
+                    UIApplication.keyWindow?.toast(text: "登录状态失效")
+                } else {
+                    fail(response.statusCode, response.toJSON(modelKey: "msg").stringValue)
+                }
+                 
+                #if DEBUG
+                print("data:\(response.fetchJSONString())")
+                #endif
+                
+                break
+            case let .failure(error):
+                fail(error.errorCode, "网络错误,请检查后重试")
+                //网络连接失败,提示用户
+                UIApplication.keyWindow?.toast(text: "网络错误,请检查后重试")
+                break
+            }
+        }
+    }
+}

+ 4 - 1
QuickSearchLocation/Classes/Main/AppDelegate.swift

@@ -18,6 +18,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         Thread.sleep(forTimeInterval: 1)
         IQKeyboardManager.shared.enable = true
         AMapServices.shared().apiKey = QSLConfig.MapKey
+        QSLDeviceTool.shared.configure(autoRefresh: true)
+        
         return true
     }
 
@@ -36,7 +38,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         // 仅在 App 被用户主动退出或系统正常终止时触发(强制杀死进程时可能不调用)
         // 可在此做最后的数据保存(操作需快速完成,系统可能限制时间)
         ///埋点app退出
-        gravityInstance?.track(QSLGravityConst.app_exit, properties: ["id": 02002])
+        
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.app_exit, eventProps: ["id": 02002])
     }
 }
 

+ 5 - 5
QuickSearchLocation/Classes/Main/CustomTabBarController.swift

@@ -37,7 +37,7 @@ class CustomTabBarController: UITabBarController {
             UserDefaults.standard.set("YES", forKey: "MANAGER_APP_ONLY_LAUNCH")
             UserDefaults.standard.synchronize()
             //只有app第一次启动才会埋点
-            gravityInstance?.track(QSLGravityConst.app_launch, properties: ["id": 02001])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.app_launch, eventProps: ["id": 02001])
             return
         }
     }
@@ -66,16 +66,16 @@ extension CustomTabBarController: UITabBarControllerDelegate {
     override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
         switch item.tag {
         case 0:
-            gravityInstance?.track(QSLGravityConst.tab_friend)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.tab_friend)
             break
         case 1:
-            gravityInstance?.track(QSLGravityConst.tab_location)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.tab_location)
             break
         case 2:
-            gravityInstance?.track(QSLGravityConst.tab_message)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.tab_message)
             break
         case 3:
-            gravityInstance?.track(QSLGravityConst.tab_mine)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.tab_mine)
             break
         default:
             break

+ 15 - 18
QuickSearchLocation/Classes/Pages/QSLAdd/Controller/QSLAddController.swift

@@ -148,13 +148,13 @@ class QSLAddController: QSLBaseController {
         if let type = self.type {
             switch type {
             case .homesmall:
-                gravityInstance?.track(QSLGravityConst.add_show, properties: ["id": 1001])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_show, eventProps: ["id": 1001])
             case .homebig:
-                gravityInstance?.track(QSLGravityConst.add_show, properties: ["id": 1002])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_show, eventProps: ["id": 1002])
             case .friend:
-                gravityInstance?.track(QSLGravityConst.add_show, properties: ["id": 1003])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_show, eventProps: ["id": 1003])
             case .homealert:
-                gravityInstance?.track(QSLGravityConst.add_show, properties: ["id": 1004])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_show, eventProps: ["id": 1004])
             }
         }
     }
@@ -163,8 +163,7 @@ class QSLAddController: QSLBaseController {
     @objc func addBtnAction() {
         
         self.view.keyboardEndEditing()
-        
-        gravityInstance?.track(QSLGravityConst.add_click)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.add_click)
         
 //        if !QSLBaseManager.shared.isLogin() {
 //            
@@ -191,12 +190,12 @@ class QSLAddController: QSLBaseController {
         }
         
         if self.phoneTextField.text?.count == 0 {
-            gravityInstance?.track(QSLGravityConst.add_result, properties: ["id": 1001])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.add_result, eventProps: ["id": 1001])
         }
         
         guard let phone = self.phoneTextField.text, phone.count == 11 else {
             self.view.toast(text: "请输入正确的电话号码")
-            gravityInstance?.track(QSLGravityConst.add_result, properties: ["id": 1002])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.add_result, eventProps: ["id": 1002])
             return
         }
         
@@ -207,8 +206,7 @@ class QSLAddController: QSLBaseController {
     }
     
     @objc func addressBookAction() {
-        
-        gravityInstance?.track(QSLGravityConst.add_addressBook)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.add_addressBook)
         
         let status = CNContactStore.authorizationStatus(for: .contacts)
         if status != .authorized {
@@ -238,8 +236,7 @@ class QSLAddController: QSLBaseController {
     }
     
     @objc func addBackBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.add_back)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.add_back)
         
         self.backBtnAction()
     }
@@ -258,30 +255,30 @@ extension QSLAddController {
             self.view.toast(text: "已发送好友请求")
             if QSLBaseManager.shared.isVip() {
                 ///输入手机号添加成功
-                gravityInstance?.track(QSLGravityConst.vip_friend_add_success_phone, properties: ["id": 04003])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_friend_add_success_phone, eventProps: ["id": 04003])
             }
 
         } fail: { code, error in
             self.view.toast(text: error)
             if QSLBaseManager.shared.isVip() {
                 ///输入手机号添加失败
-                gravityInstance?.track(QSLGravityConst.vip_friend_add_fail_phone, properties: ["id": 04004])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_friend_add_fail_phone, eventProps: ["id": 04004])
             }
             switch code {
             case 1102:
                 // 该好友已在好友列表
-                gravityInstance?.track(QSLGravityConst.add_result, properties: ["id": 1003])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_result, eventProps: ["id": 1003])
                 break
             case 1103:
                 // 不能添加自己
-                gravityInstance?.track(QSLGravityConst.add_result, properties: ["id": 1005])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_result, eventProps: ["id": 1005])
                 break
             case 1100:
                 // 好友未注册
-                gravityInstance?.track(QSLGravityConst.add_result, properties: ["id": 1005])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_result, eventProps: ["id": 1005])
                 break
             default:
-                gravityInstance?.track(QSLGravityConst.add_result, properties: ["id": 1006])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.add_result, eventProps: ["id": 1006])
                 break
             }
         }

+ 14 - 17
QuickSearchLocation/Classes/Pages/QSLContact/Controller/QSLContactController.swift

@@ -156,9 +156,9 @@ class QSLContactController: QSLBaseController {
         
         if let type = self.type {
             if type == .mine {
-                gravityInstance?.track(QSLGravityConst.contact_show, properties: ["id": 1002])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_show, eventProps: ["id": 1002])
             } else {
-                gravityInstance?.track(QSLGravityConst.contact_show, properties: ["id": 1001])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_show, eventProps: ["id": 1001])
             }
         }
     }
@@ -193,8 +193,7 @@ extension QSLContactController {
     }
     
     @objc func sendAllBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.contact_resort_all)
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_all)
 //        QSLContactSendFailAlertView.alert(view: self.view, contactList: self.contactList!)
         QSLNetwork().request(.contactMaydayAll(dict: [:])) { response in
             
@@ -202,14 +201,14 @@ extension QSLContactController {
                 print(failList)
                 if failList.count > 0 {
                     QSLContactSendFailAlertView.alert(view: self.view, contactList: failList)
-                    gravityInstance?.track(QSLGravityConst.contact_resort_all_fail_alert)
+                    QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_all_fail_alert)
                 } else {
                     self.view.toast(text: "求助消息发送成功")
-                    gravityInstance?.track(QSLGravityConst.contact_resort_all_success)
+                    QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_all_success)
                 }
             }
         } fail: { code, error in
-            gravityInstance?.track(QSLGravityConst.contact_resort_all_fail)
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_all_fail)
             self.view.toast(text: "求助消息发送失败,请稍后重试")
         }
     }
@@ -218,19 +217,18 @@ extension QSLContactController {
 extension QSLContactController: QSLContactCellDelegate {
     
     func resortClickAction(model: QSLContactModel) {
-        
-        gravityInstance?.track(QSLGravityConst.contact_resort_click)
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_click)
         QSLAlertView.alert(view: self.view, title: "紧急求助", content: "确认向\(model.phone)发送短信求助?", isOneBtn: true, oneBtnText: "确认", oneBtnClosure:  {
-            gravityInstance?.track(QSLGravityConst.contact_resort_confirm)
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_confirm)
             QSLNetwork().request(.contactMayday(dict: ["phone": model.phone])) { reponse in
                 self.view.toast(text: "求助消息发送成功")
-                gravityInstance?.track(QSLGravityConst.contact_resort_success)
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_success)
             } fail: { code, error in
                 self.view.toast(text: "求助消息发送失败,请核实手机号码")
-                gravityInstance?.track(QSLGravityConst.contact_resort_fail)
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_fail)
             }
         }, closeBtnClosure:  {
-            gravityInstance?.track(QSLGravityConst.contact_resort_cancel)
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_resort_cancel)
         })
     }
     
@@ -245,12 +243,11 @@ extension QSLContactController: QSLContactCellDelegate {
     }
     
     func deleteClickAction(model: QSLContactModel) {
-        
-        gravityInstance?.track(QSLGravityConst.contact_delete)
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_delete)
         QSLAlertView.alert(view: self.view, title: "移除紧急联系人", content: "您确定要将\n\(model.phone)移除紧急联系人吗?", isOneBtn: false, firstBtnClosure: {
-            gravityInstance?.track(QSLGravityConst.contact_delete_cancel)
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_delete_cancel)
         }, secondBtnClosure:  {
-            gravityInstance?.track(QSLGravityConst.contact_delete_confirm)
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.contact_delete_confirm)
             QSLNetwork().request(.contactDelete(dict: ["phone": model.phone])) { reponse in
                 self.view.toast(text: "删除联系人成功")
                 NotificationCenter.default.post(name: QSLNotification.QSLRefreshContact, object: nil)

+ 2 - 4
QuickSearchLocation/Classes/Pages/QSLContact/View/QSLContactAddAlertView.swift

@@ -130,8 +130,7 @@ class QSLContactAddAlertView: UIView {
     }
     
     @objc func addBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.contact_add)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.contact_add)
         
         guard let text = self.phoneTextField.text, text.count == 11 else {
             self.vc?.view.toast(text: "请输入正确的电话号码")
@@ -147,8 +146,7 @@ class QSLContactAddAlertView: UIView {
     }
     
     @objc func addressBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.contact_addressbook)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.contact_addressbook)
         
         self.removeView()
             

+ 2 - 2
QuickSearchLocation/Classes/Pages/QSLFriend/Cell/QSLFriendTableViewCell.swift

@@ -169,10 +169,10 @@ extension QSLFriendTableViewCell {
         
         if QSLBaseManager.shared.isVip() {
             //点击搜索埋点
-            gravityInstance?.track(QSLGravityConst.vip_location_click_queryTrack, properties: ["id": 03008])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_location_click_queryTrack, eventProps: ["id": 03008])
         } else {
             //点击搜索埋点
-            gravityInstance?.track(QSLGravityConst.location_click_queryTrack, properties: ["id": 03009])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.location_click_queryTrack, eventProps: ["id": 03009])
         }
         
         if let model = self.userModel {

+ 11 - 17
QuickSearchLocation/Classes/Pages/QSLFriend/Controller/QSLFriendController.swift

@@ -108,18 +108,17 @@ extension QSLFriendController {
         
         if QSLBaseManager.shared.isVip() {
             ///点击添加好友埋点
-            gravityInstance?.track(QSLGravityConst.vip_friend_click_add, properties: ["id": 04001])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_friend_click_add, eventProps: ["id": 04001])
         } else {
             ///点击添加好友埋点
-            gravityInstance?.track(QSLGravityConst.friend_click_add, properties: ["id": 04002])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.friend_click_add, eventProps: ["id": 04002])
         }
         
         QSLJumpManager.shared.pushToAdd(type: .friend)
     }
     
     @objc func resortBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.contact_shortcut_send)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.contact_shortcut_send)
         QSLNetwork().request(.contactMaydayFavor(dict: [:])) { response in
             self.view.toast(text: "求助信息发送成功")
         } fail: { code, error in
@@ -214,18 +213,15 @@ extension QSLFriendController: QSLFriendTableViewCellDelegate {
     
     // 删除好友
     func deleteFri(model: QSLUserModel) {
-        
-        gravityInstance?.track(QSLGravityConst.friend_delete)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_delete)
         if let view = self.tabBarController?.view {
             QSLAlertView.alert(view: view, title: "温馨提示", content: "互删好友后,双方将停止位置的分享,以及清除相关定位记录,是否确认互删?", isOneBtn: false, secondBtnClosure:  {
                 QSLNetwork().request(.friendDelete(dict: ["friendId": model.friendId])) { response in
-                    
-                    gravityInstance?.track(QSLGravityConst.friend_delete_success)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.friend_delete_success)
                     self.view.toast(text: "删除成功")
                     NotificationCenter.default.post(name: QSLNotification.QSLRefreshFriend, object: nil)
                 } fail: { code, error in
-                    
-                    gravityInstance?.track(QSLGravityConst.friend_delete_fail)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.contact_shortcut_send)
                 }
             })
         }
@@ -233,8 +229,7 @@ extension QSLFriendController: QSLFriendTableViewCellDelegate {
     
     // 修改备注
     func editRemark(model: QSLUserModel) {
-        
-        gravityInstance?.track(QSLGravityConst.friend_remark)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_remark)
         if let view = self.tabBarController?.view {
             QSLFriendRemarkAlertView.alert(view: view) { remark in
                 
@@ -253,9 +248,9 @@ extension QSLFriendController: QSLFriendTableViewCellDelegate {
     func blockHime(model: QSLUserModel) {
         
         if model.blockedHim {
-            gravityInstance?.track(QSLGravityConst.friend_not_block_him)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.friend_not_block_him)
         } else {
-            gravityInstance?.track(QSLGravityConst.friend_block_him)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.friend_block_him)
         }
         
         QSLNetwork().request(.friendBlocked(dict: ["friendId": model.friendId, "blocked": !model.blockedHim])) { response in
@@ -268,11 +263,10 @@ extension QSLFriendController: QSLFriendTableViewCellDelegate {
     
     // 查看手机号码
     func checkPhoneNum(model: QSLUserModel) {
-        
-        gravityInstance?.track(QSLGravityConst.friend_phoneNum)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_phoneNum)
         if let view = self.tabBarController?.view {
             QSLAlertView.alert(view: view, title: "Ta的手机号", content: model.phone, isOneBtn: true, oneBtnText: "复制号码", oneBtnClosure:  {
-                gravityInstance?.track(QSLGravityConst.friend_phoneNum_click)
+                QSEventHandle.eventPush(eventName: QSLGravityConst.friend_phoneNum_click)
                 UIPasteboard.general.string = model.phone
                 view.toast(text: "复制成功")
             })

+ 3 - 5
QuickSearchLocation/Classes/Pages/QSLFriend/View/QSLFriendRemarkAlertView.swift

@@ -97,7 +97,7 @@ class QSLFriendRemarkAlertView: UIView {
         window.secondBtnClosure = secondBtnClosure
         view.addSubview(window)
         
-        gravityInstance?.track(QSLGravityConst.friend_remark_show)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_remark_show)
         
         UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) {
             window.backgroundColor = .hexStringColor(hexString: "#000000", alpha: 0.7)
@@ -117,15 +117,13 @@ class QSLFriendRemarkAlertView: UIView {
     
     // 取消按钮点击事件
     @objc func firstBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.friend_remark_cancel)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_remark_cancel)
         removeView()
     }
     
     // 确认按钮点击事件
     @objc func secondBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.friend_remark_click)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.friend_remark_click)
         
         guard let text = self.remarkTextField.text, text.count > 0 else {
             UIApplication.keyWindow?.toast(text: "请输入名称")

+ 7 - 6
QuickSearchLocation/Classes/Pages/QSLGuide/QSLGuideController.swift

@@ -81,13 +81,13 @@ class QSLGuideController: QSLBaseController {
         
         switch cycleScrollView.currentSelectIndex {
         case 0:
-            gravityInstance?.track(QSLGravityConst.guide_first_click)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.guide_first_click)
             break
         case 1:
-            gravityInstance?.track(QSLGravityConst.guide_second_click)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.guide_second_click)
             break
         case 2:
-            gravityInstance?.track(QSLGravityConst.guide_third_click)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.guide_third_click)
             break
         default:
             break
@@ -124,13 +124,14 @@ extension QSLGuideController: GKCycleScrollViewDataSource, GKCycleScrollViewDele
     func cycleScrollView(_ cycleScrollView: GKCycleScrollView!, didScrollCellTo index: Int) {
         switch index {
         case 0:
-            gravityInstance?.track(QSLGravityConst.guide_first_show)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.guide_first_show)
             break
         case 1:
-            gravityInstance?.track(QSLGravityConst.guide_second_show)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.guide_second_show)
             break
         case 2:
-            gravityInstance?.track(QSLGravityConst.guide_third_show)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.guide_third_show)
+            
             break
         default:
             break

+ 2 - 2
QuickSearchLocation/Classes/Pages/QSLHome/Cell/QSLHomeFriendTableViewCell.swift

@@ -127,9 +127,9 @@ class QSLHomeFriendTableViewCell: UITableViewCell {
     @objc func checkButtonAction() {
         ///点击轨迹
         if QSLBaseManager.shared.isVip() {
-            gravityInstance?.track(QSLGravityConst.vip_location_click_Track, properties: ["id": 03006])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.location_click_Track, eventProps: ["id": 03006])
         } else {
-            gravityInstance?.track(QSLGravityConst.location_click_Track, properties: ["id": 03007])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.location_click_Track, eventProps: ["id": 03007])
         }
         
         if let model = self.model {

+ 7 - 6
QuickSearchLocation/Classes/Pages/QSLHome/Controller/QSLHomeController.swift

@@ -82,7 +82,7 @@ class QSLHomeController: QSLBaseController {
             UserDefaults.standard.set("YES", forKey: "FIRST_ENTER_LOCATION_HOMEPAGE")
             UserDefaults.standard.synchronize()
             ///第一次进入埋点
-            gravityInstance?.track(QSLGravityConst.location_enter_first_homepage, properties: ["id": 03005])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.location_enter_first_homepage, eventProps: ["id": 03005])
             return
         }
     }
@@ -409,7 +409,7 @@ extension QSLHomeController: MAMapViewDelegate, AMapLocationManagerDelegate {
         if self.isFirstLocatScuess {
             self.isFirstLocatScuess = false
             //始终允许定位成功
-            gravityInstance?.track(QSLGravityConst.location_success_always, properties: ["id": 03003])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.location_success_always, eventProps: ["id": 03003])
         }
         
         // 获取电话和名字
@@ -538,11 +538,11 @@ extension QSLHomeController: MAMapViewDelegate, AMapLocationManagerDelegate {
           case .authorizedAlways, .authorizedWhenInUse:
               //print("定位权限已授权")
               //支付成功埋点
-              gravityInstance?.track(QSLGravityConst.location_allow_permission, properties: ["id": 03001])
+              QSEventHandle.gravityPush(eventName: QSLGravityConst.location_allow_permission, eventProps: ["id": 03001])
           case .denied:
               //print("定位权限被拒绝")
               //拒绝定位权限
-              gravityInstance?.track(QSLGravityConst.location_deny_permission, properties: ["id": 03002])
+              QSEventHandle.gravityPush(eventName: QSLGravityConst.location_allow_permission, eventProps: ["id": 03002])
           default:
               break
           }
@@ -563,7 +563,7 @@ extension QSLHomeController: MAMapViewDelegate, AMapLocationManagerDelegate {
       // 定位结果回调
       func amapLocationManager(_ manager: AMapLocationManager, didFailWithError error: Error) {
           print("定位失败: \(error.localizedDescription)")
-          gravityInstance?.track(QSLGravityConst.location_fail_always, properties: ["id": 03004])
+          QSEventHandle.gravityPush(eventName: QSLGravityConst.location_fail_always, eventProps: ["id": 03004])
       }
     
 }
@@ -687,7 +687,8 @@ extension QSLHomeController: QSLHomeEmptyViewDelegate, QSLHomeFriendViewDelegate
     
     func refreshBtnAction() {
         
-        gravityInstance?.track(QSLGravityConst.home_locate)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.home_locate)
+        
         self.loadData()
     }
     

+ 2 - 1
QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeFriendView.swift

@@ -304,7 +304,8 @@ extension QSLHomeFriendView {
 // MARK: - 点击事件
 extension QSLHomeFriendView {
     @objc func unlockBtnAction(){
-        gravityInstance?.track(QSLGravityConst.home_coupon_click, properties: [:])
+        QSEventHandle.eventPush(eventName: QSLGravityConst.home_coupon_click)
+
         QSLJumpManager.shared.unlockBtnAction()
     }
     

+ 17 - 20
QuickSearchLocation/Classes/Pages/QSLLogin/Controller/QSLLoginViewController.swift

@@ -212,17 +212,17 @@ class QSLLoginViewController: QSLBaseController {
         if let type = self.type {
             switch type {
             case .mine:
-                gravityInstance?.track(QSLGravityConst.login_show, properties: ["id": 1001])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_show, eventProps: ["id": 1001])
             case .add:
-                gravityInstance?.track(QSLGravityConst.login_show, properties: ["id": 1002])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_show, eventProps: ["id": 1002])
             case .road:
-                gravityInstance?.track(QSLGravityConst.login_show, properties: ["id": 1003])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_show, eventProps: ["id": 1003])
             case .contact:
-                gravityInstance?.track(QSLGravityConst.login_show, properties: ["id": 1004])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_show, eventProps: ["id": 1004])
             case .onQucikLogin:
-                gravityInstance?.track(QSLGravityConst.login_show, properties: ["id": 1005])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_show, eventProps: ["id": 1005])
             case .member:
-                gravityInstance?.track(QSLGravityConst.login_show, properties: ["id": 1006])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_show, eventProps: ["id": 1006])
             }
         }
     }
@@ -247,36 +247,33 @@ extension QSLLoginViewController {
     }
     
     @objc func selectButtonAction() {
-        
-        gravityInstance?.track(QSLGravityConst.login_agree)
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.login_agree)
+
         self.selectBtn.isSelected = !self.selectBtn.isSelected
     }
     
     // 验证码
     @objc func codeButtonAction() {
-                
-        gravityInstance?.track(QSLGravityConst.login_code)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.login_code)
+   
         if let phone = self.phoneTextField.text, phone.count == 11 {
             
             codeButton.countDown(60)
             QSLNetwork().request(.userCode(dict: ["phone": phone]), success: { response in
                 
             }, fail: { code, error in
-                
-                gravityInstance?.track(QSLGravityConst.login_code_fail, properties: ["id": 1001])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_code_fail, eventProps: ["id": 1001])
                 self.view.toast(text: "发送失败")
             })
         } else {
-            
-            gravityInstance?.track(QSLGravityConst.login_code_fail, properties: ["id": 1002])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.login_code_fail, eventProps: ["id": 1002])
             self.view.toast(text: "请输入正确的手机号码")
         }
     }
     
     // 登录按钮
     @objc func loginButtonAction() {
-        
-        gravityInstance?.track(QSLGravityConst.login_click)
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.login_click)
         
         guard let phone = self.phoneTextField.text, phone.count == 11 else {
             self.view.toast(text: "请输入正确的手机号码")
@@ -289,7 +286,7 @@ extension QSLLoginViewController {
         }
         
         if !self.selectBtn.isSelected {
-            gravityInstance?.track(QSLGravityConst.login_fail, properties: ["id": 1001])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.login_fail, eventProps: ["id": 1001])
             self.view.toast(text: "请先阅读并同意《隐私权政策》和《用户协议》")
             return
         }
@@ -302,7 +299,7 @@ extension QSLLoginViewController {
             QSLBaseManager.shared.loginUpdateUser(authToken: authToken, phone: phone)
             UIApplication.keyWindow?.toast(text: "登录成功")
             
-            gravityInstance?.track(QSLGravityConst.login_success)
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.login_success)
             // 发送通知
             NotificationCenter.default.post(name: QSLNotification.QSLLogin, object: nil)
             // 发送通知
@@ -318,9 +315,9 @@ extension QSLLoginViewController {
         }, fail: { code, error in
             
             if code == 1005 {
-                gravityInstance?.track(QSLGravityConst.login_fail, properties: ["id": 1002])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_fail, eventProps: ["id": 1002])
             } else {
-                gravityInstance?.track(QSLGravityConst.login_fail, properties: ["id": 1003])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_fail, eventProps: ["id": 1003])
             }
             
             QSLLoading.hide()

+ 4 - 5
QuickSearchLocation/Classes/Pages/QSLMessage/Controller/QSLMessageController.swift

@@ -119,11 +119,11 @@ extension QSLMessageController {
             
             for message in self.messageList {
                 if message.type == 2 {
-                    gravityInstance?.track(QSLGravityConst.message_disagree_show)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.message_disagree_show)
                 } else if message.type == 3 {
-                    gravityInstance?.track(QSLGravityConst.message_agree_show)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.message_agree_show)
                 } else if message.type == 4 {
-                    gravityInstance?.track(QSLGravityConst.message_resort_show)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.message_resort_show)
                 }
             }
             self.messageTableView.reloadData()
@@ -137,8 +137,7 @@ extension QSLMessageController: QSLMessageHeaderViewDelegate, QSLMessageTableVie
     
     // 电话联系
     func contactBtnAction(phone: String) {
-        
-        gravityInstance?.track(QSLGravityConst.message_resort_click)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.message_resort_click)
         // 创建电话拨号的URL
         if let url = URL(string: "tel://\(phone)"), UIApplication.shared.canOpenURL(url) {
             // 打开URL

+ 2 - 2
QuickSearchLocation/Classes/Pages/QSLMessage/QSLRequest/QSLRequestCell.swift

@@ -88,7 +88,7 @@ class QSLRequestCell: UITableViewCell {
     @objc func refuseBtnAction() {
         
         ///拒绝好友申请埋点
-        gravityInstance?.track(QSLGravityConst.friend_reject_request, properties: ["id": 04006])
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.friend_reject_request, eventProps: ["id": 04006])
         
         if let model = self.model {
             delegate?.refuseBtnAction(model: model)
@@ -98,7 +98,7 @@ class QSLRequestCell: UITableViewCell {
     @objc func agreeBtnAction() {
         
         ///拒绝好友申请埋点
-        gravityInstance?.track(QSLGravityConst.friend_agree_request, properties: ["id": 04005])
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.friend_agree_request, eventProps: ["id": 04005])
         
         if let model = self.model {
             delegate?.accpetBtnAction(model: model)

+ 3 - 4
QuickSearchLocation/Classes/Pages/QSLMessage/QSLRequest/QSLRequestController.swift

@@ -42,8 +42,7 @@ class QSLRequestController: QSLBaseController {
         requestTableView.cr.beginHeaderRefresh()
         
         NotificationCenter.default.addObserver(self, selector: #selector(requestRequestList), name: QSLNotification.QSLRefreshRequest, object: nil)
-        
-        gravityInstance?.track(QSLGravityConst.message_request_show)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.message_request_show)
     }
     
     override func viewWillAppear(_ animated:Bool) {
@@ -81,8 +80,8 @@ extension QSLRequestController: QSLRequestCellDelegate {
     
     // 拒绝点击
     func refuseBtnAction(model: QSLRequestModel) {
-        
-        gravityInstance?.track(QSLGravityConst.message_request_disagree)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.message_request_disagree)
+
         QSLNetwork().request(.requestRefuse(dict: ["id": model.requestId])) { response in
             
             // 发送通知

+ 2 - 2
QuickSearchLocation/Classes/Pages/QSLMessage/View/QSLMessageHeaderView.swift

@@ -102,7 +102,7 @@ class QSLMessageHeaderView: UIView {
     @objc func refuseBtnAction() {
         
         ///拒绝好友申请埋点
-        gravityInstance?.track(QSLGravityConst.friend_reject_request, properties: ["id": 04006])
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.friend_reject_request, eventProps: ["id": 04006])
         
         if let model = self.model {
             delegate?.refuseBtnAction(model: model)
@@ -112,7 +112,7 @@ class QSLMessageHeaderView: UIView {
     @objc func agreeBtnAction() {
         
         ///拒绝好友申请埋点
-        gravityInstance?.track(QSLGravityConst.friend_agree_request, properties: ["id": 04005])
+        QSEventHandle.gravityPush(eventName: QSLGravityConst.friend_agree_request, eventProps: ["id": 04005])
         
         if let model = self.model {
             delegate?.accpetBtnAction(model: model)

+ 8 - 17
QuickSearchLocation/Classes/Pages/QSLMine/Controller/QSLMineController.swift

@@ -115,11 +115,6 @@ extension QSLMineController {
             })
         }
         
-        /*if !QSLBaseManager.shared.isLogin() {
-            
-            gravityInstance?.track(QSLGravityConst.mine_login)
-            QSLJumpManager.shared.pushToLogin(type: .mine)
-        }*/
     }
 }
 
@@ -127,8 +122,7 @@ extension QSLMineController: QSLMineVipViewDelegate {
     
     // 跳转到vip页面
     func unlockBtnAction() {
-        
-        gravityInstance?.track(QSLGravityConst.mine_vip)
+        QSEventHandle.eventPush( eventName: QSLGravityConst.mine_vip)
         QSLJumpManager.shared.pushToVip(type: .mine)
     }
 }
@@ -166,16 +160,14 @@ extension QSLMineController: QSLMineFuncViewDelegate {
     }
     
     func jumpToContact() {
-        
-        gravityInstance?.track(QSLGravityConst.mine_contact)
+        QSEventHandle.eventPush( eventName: QSLGravityConst.mine_contact)
         QSLJumpManager.shared.pushToContact(type: .mine)
 //        let vc = QSLContactController()
 //        self.navigationController?.pushViewController(vc, animated: true)
     }
     
     func jumpToInfo() {
-        
-        gravityInstance?.track(QSLGravityConst.mine_about)
+        QSEventHandle.eventPush( eventName: QSLGravityConst.mine_about)
         let vc = QSLAppInfoController()
         vc.title = "关于我们"
         self.navigationController?.pushViewController(vc, animated: true)
@@ -183,8 +175,7 @@ extension QSLMineController: QSLMineFuncViewDelegate {
     
     // MARK: - 权限
     func authAction() {
-        
-        gravityInstance?.track(QSLGravityConst.mine_auth)
+        QSEventHandle.eventPush( eventName: QSLGravityConst.mine_auth)
         if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
             
             UIApplication.shared.open(url)
@@ -204,13 +195,13 @@ extension QSLMineController: QSLMineFuncViewDelegate {
     
     // MARK: - 退出登录
     func logoutAction() {
-        
-        gravityInstance?.track(QSLGravityConst.mine_logout)
+        QSEventHandle.eventPush( eventName: QSLGravityConst.mine_logout)
+
         if let view = self.tabBarController?.view {
             QSLAlertView.alert(view: view, title: "温馨提示", content: "确认退出登录吗?", firstBtnClosure: {
-                gravityInstance?.track(QSLGravityConst.mine_logout_cancel)
+                QSEventHandle.eventPush( eventName: QSLGravityConst.mine_logout_cancel)
             }, secondBtnClosure:  {
-                gravityInstance?.track(QSLGravityConst.mine_logout_confirm)
+                QSEventHandle.eventPush( eventName: QSLGravityConst.mine_logout_confirm)
                 self.view.toast(text: "退出登录成功")
                 QSLBaseManager.shared.logOut()
             })

+ 6 - 5
QuickSearchLocation/Classes/Pages/QSLMine/QSQuickLogon/QSQuickLogonHandle.swift

@@ -47,7 +47,7 @@ class QSQuickLogonHandle: NSObject {
                         QSLLoading.hide()
                         ///去登录
                         if !QSLBaseManager.shared.isLogin() {
-                            gravityInstance?.track(QSLGravityConst.mine_login)
+                            QSEventHandle.eventPush( eventName: QSLGravityConst.mine_login)
                             QSLJumpManager.shared.pushToLogin(type: .mine)
                         }
                     }
@@ -249,7 +249,8 @@ class QSQuickLogonHandle: NSObject {
             Task { @MainActor in
                 self.showMyToast(showText:  "登录成功")
             }
-            gravityInstance?.track(QSLGravityConst.login_success)
+            QSEventHandle.eventPush( eventName: QSLGravityConst.login_success)
+
             // 发送通知
             NotificationCenter.default.post(name: QSLNotification.QSLLogin, object: nil)
             // 发送通知
@@ -262,9 +263,9 @@ class QSQuickLogonHandle: NSObject {
             
         }, fail: { code, error in
             if code == 1005 {
-                gravityInstance?.track(QSLGravityConst.login_fail, properties: ["id": 1002])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_fail, eventProps: ["id": 1002])
             } else {
-                gravityInstance?.track(QSLGravityConst.login_fail, properties: ["id": 1003])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.login_fail, eventProps: ["id": 1003])
             }
             QSLLoading.hide()
             //self.currentVC?.view.toast(text: error)
@@ -289,7 +290,7 @@ class QSQuickLogonHandle: NSObject {
         print("验证码登录按钮点击")
         ///去登录
         if !QSLBaseManager.shared.isLogin() {
-            gravityInstance?.track(QSLGravityConst.mine_login)
+            QSEventHandle.eventPush( eventName: QSLGravityConst.mine_login)
             
             let longinvc = QSLLoginViewController()
             longinvc.type = .onQucikLogin

+ 8 - 22
QuickSearchLocation/Classes/Pages/QSLRoad/Controller/QSLRoadController.swift

@@ -175,9 +175,9 @@ class QSLRoadController: QSLBaseController {
         
         if let type = self.type {
             if type == .home {
-                gravityInstance?.track(QSLGravityConst.road_show, properties: ["id": 1001])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.road_show, eventProps: ["id": 1001])
             } else {
-                gravityInstance?.track(QSLGravityConst.road_show, properties: ["id": 1002])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.road_show, eventProps: ["id": 1002])
             }
         }
     }
@@ -294,18 +294,7 @@ extension QSLRoadController:MAMapViewDelegate, AMapLocationManagerDelegate {
     }
     
     func mapView(_ mapView: MAMapView!, didSingleTappedAt coordinate: CLLocationCoordinate2D) {
-          /*// 直接获取被点击的轨迹线(支持多段线同时选中)
-          let hittedPolylines = mapView.getHittedPolylines(with: coordinate, traverseAll: false)
-          
-          if let polyline = hittedPolylines?.first as? MAPolyline {
-              print("点击了轨迹线,包含 \(polyline.pointCount) 个点")
-              ///点击轨迹
-              if QSLBaseManager.shared.isVip() {
-                  gravityInstance?.track(QSLGravityConst.vip_location_click_Track, properties: ["id": 03006])
-              } else {
-                  gravityInstance?.track(QSLGravityConst.location_click_Track, properties: ["id": 03007])
-              }
-          }*/
+         
       }
     
 //    // 查询个人位置
@@ -533,8 +522,7 @@ extension QSLRoadController:MAMapViewDelegate, AMapLocationManagerDelegate {
 extension QSLRoadController: QSLRoadMainViewDelegate {
     
     func searchClickAction() {
-        
-        gravityInstance?.track(QSLGravityConst.road_search)
+        QSEventHandle.eventPush(eventName: QSLGravityConst.road_search)
         self.requestRoad()
     }
     
@@ -544,7 +532,7 @@ extension QSLRoadController: QSLRoadMainViewDelegate {
         self.startDatePicker.selectDate = self.startDate
         self.startDatePicker.show()
         self.startDatePicker.resultBlock = { [weak self] date, value in
-            gravityInstance?.track(QSLGravityConst.road_time_confirm)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.road_time_confirm)
             self?.mainView.startTimeLabel.text = "开始时间:\(value ?? "")"
             
             if let date = date {
@@ -568,8 +556,7 @@ extension QSLRoadController: QSLRoadMainViewDelegate {
         }
         
         self.startDatePicker.cancelBlock = {
-            
-            gravityInstance?.track(QSLGravityConst.road_time_cancel)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.road_time_cancel)
         }
     }
     
@@ -579,7 +566,7 @@ extension QSLRoadController: QSLRoadMainViewDelegate {
         self.endDatePicker.selectDate = self.endDate
         self.endDatePicker.show()
         self.endDatePicker.resultBlock = { [weak self] date, value in
-            gravityInstance?.track(QSLGravityConst.road_time_confirm)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.road_time_confirm)
             self?.mainView.endTimeLabel.text = "结束时间:\(value ?? "")"
             
             if let date = date {
@@ -589,8 +576,7 @@ extension QSLRoadController: QSLRoadMainViewDelegate {
         }
         
         self.endDatePicker.cancelBlock = {
-            
-            gravityInstance?.track(QSLGravityConst.road_time_cancel)
+            QSEventHandle.eventPush(eventName: QSLGravityConst.road_time_cancel)
         }
     }
 }

+ 10 - 14
QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLActivityVipVC.swift

@@ -19,7 +19,7 @@ class QSLActivityVipVC: QSLBaseController {
     override func viewDidLoad() {
         super.viewDidLoad()
         
-        gravityInstance?.track(QSLGravityConst.activity_vip_show, properties: [:])
+        QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_show)
         
         self.initializeView()
         
@@ -64,22 +64,22 @@ class QSLActivityVipVC: QSLBaseController {
         }
         switch self.selectGood?.level {
         case 100 :
-            gravityInstance?.track(QSLGravityConst.activity_vip_click, properties: ["package_type": "day"])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "day"])
             break
         case 700:
-            gravityInstance?.track(QSLGravityConst.activity_vip_click, properties: ["package_type": "weekly"])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "weekly"])
             break;
         case 3100:
-            gravityInstance?.track(QSLGravityConst.activity_vip_click, properties: ["package_type": "monthly"])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "monthly"])
             break;
         case 9200:
-            gravityInstance?.track(QSLGravityConst.activity_vip_click, properties: ["package_type": "quarterly"])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "quarterly"])
             break;
         case 36600:
-            gravityInstance?.track(QSLGravityConst.activity_vip_click, properties: ["package_type": "yearly"])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "yearly"])
             break;
         case 3660000:
-            gravityInstance?.track(QSLGravityConst.activity_vip_click, properties: ["package_type": "lifetime"])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "lifetime"])
             break;
         default:
             break;
@@ -114,7 +114,7 @@ class QSLActivityVipVC: QSLBaseController {
                     QSWikiHandle.shared.addEventResultAttribution(eventDict: ["event_name": "pay", "event_val": selectGood.amount])
                     #endif
                     
-                    gravityInstance?.track(QSLGravityConst.activity_vip_result, properties: ["purchase_result": "success","pay_amount":Int32(selectGood.amount)])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_result, eventProps: ["purchase_result": "success","pay_amount":Int32(selectGood.amount)])
 
                     DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                         self.dismiss(animated: false)
@@ -128,13 +128,12 @@ class QSLActivityVipVC: QSLBaseController {
                     }
                     
                 } else if status == .cancel {
-                    gravityInstance?.track(QSLGravityConst.activity_vip_result, properties: ["purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_result, eventProps: ["purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
                     QSLLoading.error(text: "支付取消")
 //                    payFailAlertTip()
                     self.isCancel = true
                 } else if status == .fail {
-                    gravityInstance?.track(QSLGravityConst.activity_vip_result, properties: ["purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
-                    gravityInstance?.track(QSLGravityConst.vip_fail)
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_result, eventProps: ["purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
                     QSLLoading.error(text: "支付失败")
 //                    payFailAlertTip()
                     self.isCancel = true
@@ -144,7 +143,6 @@ class QSLActivityVipVC: QSLBaseController {
     }
     
     func payFailAlertTip() {
-//        gravityInstance?.track(QSLGravityConst.activity_vip_retention_show, properties: ["trigger_type":"cancel_payment"])
         var yearGood = self.selectGood
         for subGood in self.goodList{
             if(subGood.level == 36600){
@@ -157,9 +155,7 @@ class QSLActivityVipVC: QSLBaseController {
             QSLRetainPopUpAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure:  { [weak self] in
                 self?.selectGood = yearGood
                 self?.payBtnAction()
-//                gravityInstance?.track(QSLGravityConst.activity_vip_retention_click, properties: ["button":"continue_payment"])
             },secondBtnClosure: {
-//                gravityInstance?.track(QSLGravityConst.activity_vip_retention_click, properties: ["button":"close"])
             })
             
         }

+ 54 - 56
QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLVipController.swift

@@ -472,24 +472,24 @@ class QSLVipController: QSLBaseController {
 //        }else{
 //            self.resumeBtn.isHidden = true
 //        }
-
+        
         if let type = self.type {
             switch type {
             case .homeRoad:
-                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1001])
-                gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"track"])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_show, eventProps: ["id": 1001])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_show, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"track"])
             case .add:
-                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1002])
-                gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"find_friend"])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_show, eventProps: ["id": 1002])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_show, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"find_friend"])
             case .friendRoad:
-                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1003])
-                gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"find_track"])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_show, eventProps: ["id": 1003])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_show, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"find_track"])
             case .contact:
-                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1004])
-                gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"contact"])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_show, eventProps: ["id": 1004])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_show, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"contact"])
             case .mine:
-                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1006])
-                gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"open_now"])
+                QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_show, eventProps: ["id": 1006])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_show, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"open_now"])
             case .guideComments:
                 print("")
             }
@@ -583,28 +583,28 @@ extension QSLVipController {
         
         switch self.selectGood?.level {
         case 100 :
-            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1006])
-            gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "day"])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_buy_click, eventProps: ["id": 1006])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "day"])
             break
         case 700:
-            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1005])
-            gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "weekly"])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_buy_click, eventProps: ["id": 1005])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "weekly"])
             break;
         case 3100:
-            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1004])
-            gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "monthly"])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_buy_click, eventProps: ["id": 1004])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "monthly"])
             break;
         case 9200:
-            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1003])
-            gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "quarterly"])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_buy_click, eventProps: ["id": 1003])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "quarterly"])
             break;
         case 36600:
-            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1002])
-            gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "yearly"])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_buy_click, eventProps: ["id": 1002])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "yearly"])
             break;
         case 3660000:
-            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1001])
-            gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "lifetime"])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_buy_click, eventProps: ["id": 1001])
+            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "lifetime"])
             break;
         default:
             break;
@@ -628,9 +628,8 @@ extension QSLVipController {
                 if status == .success {
                     QSLLoading.success(text: "支付成功")
                     self.isCancel = true
-                    gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(selectGood.amount)])
-                    //支付成功埋点
-                    gravityInstance?.track(QSLGravityConst.vip_submit_success, properties: ["id": 01001])
+
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(selectGood.amount)])
                     //弹出是否好评的弹窗
 //                    QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(QSLGuideusersToCommentType.member)
                     
@@ -648,15 +647,15 @@ extension QSLVipController {
                     if let type = self.type {
                         switch type {
                         case .homeRoad:
-                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1001])
+                            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1001])
                         case .add:
-                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1002])
+                            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1002])
                         case .friendRoad:
-                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1003])
+                            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1003])
                         case .contact:
-                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1004])
+                            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1004])
                         case .mine:
-                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1006])
+                            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1006])
                         case .guideComments:
                             print("")
                         }
@@ -664,22 +663,22 @@ extension QSLVipController {
 
                     switch self.selectGood?.level {
                     case 100 :
-                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 1])
+                        QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_good, eventProps: ["id": 1])
                         break
                     case 700:
-                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 5])
+                        QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_good, eventProps: ["id": 5])
                         break;
                     case 3100:
-                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 9])
+                        QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_good, eventProps: ["id": 9])
                         break;
                     case 9200:
-                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 13])
+                        QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_good, eventProps: ["id": 13])
                         break;
                     case 36600:
-                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 17])
+                        QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_good, eventProps: ["id": 17])
                         break;
                     case 3660000:
-                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 21])
+                        QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_good, eventProps: ["id": 21])
                         break;
                     default:
                         break;
@@ -695,16 +694,15 @@ extension QSLVipController {
                     }
                     
                 } else if status == .cancel {
-                    gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
                     QSLLoading.error(text: "支付取消")
                     payFailAlertTip()
-                    gravityInstance?.track(QSLGravityConst.new_vip_retention_show, properties: ["trigger_type":"cancel_payment"])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_show, eventProps: ["trigger_type":"cancel_payment"])
                 } else if status == .fail {
-                    gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
-                    gravityInstance?.track(QSLGravityConst.vip_fail)
                     QSLLoading.error(text: "支付失败")
                     payFailAlertTip()
-                    gravityInstance?.track(QSLGravityConst.new_vip_retention_show, properties: ["trigger_type":"fail"])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
+                    QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_show, eventProps: ["trigger_type":"fail"])
                 }
             }
         }
@@ -715,9 +713,9 @@ extension QSLVipController {
             self.isCancel = true
             QSLRetainPopUpAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure:  { [weak self] in
                 self?.unlockBtnAction()
-                gravityInstance?.track(QSLGravityConst.new_vip_retention_click, properties: ["button":"continue_payment"])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_click, eventProps: ["button":"continue_payment"])
             },closeBtnClosure: {
-                gravityInstance?.track(QSLGravityConst.new_vip_retention_click, properties: ["button":"close"])
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_click, eventProps: ["button":"close"])
             })
         }
     }
@@ -738,22 +736,22 @@ extension QSLVipController {
         
         switch self.selectGood?.level {
         case 100 :
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1006])
             break
         case 700:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1005])
             break;
         case 3100:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1004])
             break;
         case 9200:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1003])
             break;
         case 36600:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1002])
             break;
         case 3660000:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1001])
             break;
         default:
             break;
@@ -889,22 +887,22 @@ extension QSLVipController: UICollectionViewDelegate, UICollectionViewDataSource
         
         switch self.selectGood?.level {
         case 100 :
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1006])
             break
         case 700:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1005])
             break;
         case 3100:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1004])
             break;
         case 9200:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1003])
             break;
         case 36600:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1002])
             break;
         case 3660000:
-            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
+            QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_good_select, eventProps: ["id": 1001])
             break;
         default:
             break;

+ 2 - 5
QuickSearchLocation/Macro/QSLApi.swift

@@ -28,11 +28,6 @@ struct QSLApi {
     
     static let prodWSUrl = "ws://loc-api.v8dashen.com"
     
-    // 中台
-    static let centralUrl = "https://project-api.atmob.com"
-    
-    static let appKey = "c70327c169214b269a6cde5405d9f130"
-    
     static var params : [String:Any] = [
         "channelName": "appstore",
         "appPlatform": 2,
@@ -68,6 +63,8 @@ struct QSLApi {
     static func getIDFA(newIDFA: String) {
         self.idfa = newIDFA
         params["idfa"] = newIDFA
+        
+        QSLDeviceTool.shared.idfa = newIDFA
     }
     
     // 更新IDFV值

+ 183 - 26
QuickSearchLocation/Tools/QSLDeviceTool.swift

@@ -8,50 +8,128 @@
 import Foundation
 import UIKit
 import AdSupport
+import Security
+import AppTrackingTransparency
 
 /// 设备各种信息
 class QSLDeviceTool: NSObject {
+    static let shared = QSLDeviceTool()
     
+    private override init() {}
+    
+    // 在 QSLDeviceTool 中添加
+    public func configure(autoRefresh: Bool = true) {
+        enableAutoRefresh = autoRefresh
+    }
+    
+    private let configQueue = DispatchQueue(label: "com.qsl.deviceTool.config")
+    public var enableAutoRefresh: Bool = true {
+        didSet {
+            configQueue.async {
+                if self.enableAutoRefresh {
+                    self.setupObservers()
+                } else {
+                    self.removeObservers()
+                }
+            }
+        }
+    }
+    
+    private func removeObservers() {
+        if #available(iOS 13.0, *) {
+            NotificationCenter.default.removeObserver(
+                self,
+                name: UIScene.didEnterBackgroundNotification,
+                object: nil
+            )
+        }else{
+            NotificationCenter.default.removeObserver(
+                self,
+                name: UIApplication.didEnterBackgroundNotification,
+                object: nil
+            )
+        }
+    }
+    
+    // MARK: - 监听 App 生命周期
+    private func setupObservers() {
+        removeObservers() // 先移除旧监听
+        
+        if #available(iOS 13.0, *) {
+            NotificationCenter.default.addObserver(
+                self,
+                selector: #selector(sceneDidEnterBackground(_:)),
+                name: UIScene.didEnterBackgroundNotification,
+                object: nil
+            )
+            
+        } else {
+            // Fallback 到 App 生命周期监听(iOS 12 及以下)
+            NotificationCenter.default.addObserver(
+                self,
+                selector: #selector(appDidEnterBackground),
+                name: UIApplication.didEnterBackgroundNotification,
+                object: nil
+            )
+        }
+    }
+    
+    func refreshSessionId() {
+        sessionId = UUID().uuidString.replacingOccurrences(of: "-", with: "")
+        print("SessionID 已更新: \(sessionId)")
+    }
+    
+    @objc private func appDidEnterBackground() {
+        // App 退到后台时更新 SessionID
+        refreshSessionId()
+    }
+    
+    @objc private func sceneDidEnterBackground(_ notification: Notification) {
+        // App 退到后台时更新 SessionID
+        refreshSessionId()
+    }
+       
     // MARK: 1、App 名称
     /// App 名称
-    var appDisplayName: String {
-        return (Bundle.main.infoDictionary!["CFBundleDisplayName"] as? String) ?? ""
-    }
+    lazy var appDisplayName: String = {
+        return (Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String) ?? ""
+    }()
+    
     
     // MARK: 2、App 平台 安卓为1 iOS为2
     /// App 平台
-    var platform: Int {
+    lazy var platform: Int = {
         return 2;
-    }
+    }()
     
     // MARK: 3、渠道名称
     /// 渠道名称
-    var channelName: String {
+    lazy var channelName: String = {
         return "appstore";
-    }
+    }()
     
     // MARK: 4、版本
     /// 版本
-    var OSVersion: String {
+    lazy var OSVersion: String = {
         return String.init(format: "%@%@", UIDevice.current.systemName, UIDevice.current.systemVersion)
-    }
+    }()
     
     // MARK: 5、包名
     /// 包名
-    var packageName: String {
-        return Bundle.appBundleIdentifier;
-    }
+    lazy var packageName: String = {
+        return Bundle.main.bundleIdentifier ?? ""
+    }()
     
     // MARK: 6、版本号 1.0.0
     /// 版本号
-    var appVersionName: String {
-        return Bundle.appVersion;
-    }
+    lazy var appVersionName: String = {
+        return (Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String) ?? "";
+    }()
     
     // MARK: 6、版本号 100
     /// 版本号
-    var appVersionCode: String {
-        let versionSubStrings = self.appDisplayName.components(separatedBy: ".")
+    lazy var appVersionCode: String = {
+        let versionSubStrings = self.appVersionName.components(separatedBy: ".")
         var versionCode = ""
         for subString in versionSubStrings {
             versionCode.append(subString)
@@ -60,29 +138,44 @@ class QSLDeviceTool: NSObject {
             versionCode.append("0")
         }
         return versionCode
-    }
+    }()
     
     // MARK: 7、品牌
     /// 品牌
-    var brand: String {
+    lazy var brand: String = {
         return "Apple"
-    }
+    }()
     
     // MARK: 8、idfa
     /// idfa
-    var idfa: String {
-        return ASIdentifierManager.shared().advertisingIdentifier.uuidString;
-    }
+    lazy var idfa: String = {
+        if #available(iOS 14.0, *) {
+            return ""
+        } else {
+            // 检查用户是否授权应用使用广告标识符
+            if ASIdentifierManager.shared().isAdvertisingTrackingEnabled {
+                let idfa = ASIdentifierManager.shared().advertisingIdentifier
+                return idfa.uuidString
+            } else {
+                return ""
+            }
+        }
+    }()
     
     // MARK: 8、idfv
     /// idfv
-    var idfv: String {
+    lazy var idfv: String = {
         return UIDevice.current.identifierForVendor?.uuidString ?? "";
-    }
+    }()
+    
+    //设备唯一码 卸载删除还是一致
+    lazy var deviceID: String = {
+        return QSLDeviceUniqueIDTool.shared.deviceUniqueID
+    }()
     
     // MARK: 9、型号
     /// 型号
-    var model: String {
+    lazy var phoneModel: String = {
         var systemInfo = utsname()
         uname(&systemInfo)
         let machineMirror = Mirror(reflecting: systemInfo.machine)
@@ -91,5 +184,69 @@ class QSLDeviceTool: NSObject {
             return identifier + String(UnicodeScalar(UInt8(value)))
         }
         return identifier
+    }()
+    
+    lazy var sessionId: String = {
+        let uuidString = UUID().uuidString.replacingOccurrences(of: "-", with: "")
+        return uuidString
+    }()
+}
+
+class QSLDeviceUniqueIDTool {
+    static let shared = QSLDeviceUniqueIDTool()
+    
+    // Keychain 存储的 key
+    private let keychainService = QSLCentralEventManager.bundleId + ".deviceUniqueID"
+    private let keychainAccount = "deviceUniqueID"
+    
+    // 获取或生成设备唯一码
+    var deviceUniqueID: String {
+        // 1. 尝试从 Keychain 读取
+        if let existingID = retrieveDeviceUniqueIDFromKeychain() {
+            return existingID
+        }
+        // 2. 如果没有,生成新的 UUID 并存储到 Keychain
+        else {
+            let newID = UUID().uuidString
+            saveDeviceUniqueIDToKeychain(newID)
+            return newID
+        }
+    }
+    
+    // MARK: - Keychain 操作
+    
+    /// 从 Keychain 读取 UUID
+    private func retrieveDeviceUniqueIDFromKeychain() -> String? {
+        let query: [CFString: Any] = [
+            kSecClass: kSecClassGenericPassword,
+            kSecAttrService: keychainService,
+            kSecAttrAccount: keychainAccount,
+            kSecReturnData: true,
+            kSecMatchLimit: kSecMatchLimitOne
+        ]
+        
+        var dataTypeRef: AnyObject?
+        let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
+        
+        if status == errSecSuccess, let data = dataTypeRef as? Data {
+            return String(data: data, encoding: .utf8)
+        }
+        return nil
+    }
+    
+    /// 存储 UUID 到 Keychain
+    private func saveDeviceUniqueIDToKeychain(_ id: String) {
+        let query: [CFString: Any] = [
+            kSecClass: kSecClassGenericPassword,
+            kSecAttrService: keychainService,
+            kSecAttrAccount: keychainAccount,
+            kSecValueData: id.data(using: .utf8)!
+        ]
+        
+        // 先删除旧的(如果有)
+        SecItemDelete(query as CFDictionary)
+        
+        // 存储新的
+        SecItemAdd(query as CFDictionary, nil)
     }
 }