Quellcode durchsuchen

feat:接入推送

zhujieshan vor 1 Monat
Ursprung
Commit
4aef33e4be
64 geänderte Dateien mit 2393 neuen und 313 gelöschten Zeilen
  1. BIN
      .DS_Store
  2. 48 4
      QuickSearchLocation.xcodeproj/project.pbxproj
  3. 4 0
      QuickSearchLocation/Classes/AppleAD/QSWikiHandle.swift
  4. 26 0
      QuickSearchLocation/Classes/Common/Model/QSLConfModel.swift
  5. 24 0
      QuickSearchLocation/Classes/Common/Model/QSLWakeupModel.swift
  6. 25 0
      QuickSearchLocation/Classes/Common/Tool/QSLCacheManager.swift
  7. 49 13
      QuickSearchLocation/Classes/Common/Tool/QSLCountdownManager.swift
  8. 15 27
      QuickSearchLocation/Classes/Common/Tool/QSLGuideusersToCommentManager.swift
  9. 8 1
      QuickSearchLocation/Classes/Common/Tool/QSLJumpManager.swift
  10. 179 0
      QuickSearchLocation/Classes/Common/Tool/QSLTools.swift
  11. 91 0
      QuickSearchLocation/Classes/Common/View/QSLLoadingView.swift
  12. 0 1
      QuickSearchLocation/Classes/EventHandle/QSLCentralNetwork.swift
  13. 66 1
      QuickSearchLocation/Classes/Main/AppDelegate.swift
  14. 20 0
      QuickSearchLocation/Classes/Main/CustomTabBarController.swift
  15. 32 1
      QuickSearchLocation/Classes/Main/SceneDelegate.swift
  16. 2 18
      QuickSearchLocation/Classes/Main/ViewController.swift
  17. 45 0
      QuickSearchLocation/Classes/Network/QSLNetwork.swift
  18. 13 31
      QuickSearchLocation/Classes/Pages/QSLAdd/Controller/QSLAddController.swift
  19. 1 1
      QuickSearchLocation/Classes/Pages/QSLAlert/View/QSLFriendAddAlertView.swift
  20. 21 13
      QuickSearchLocation/Classes/Pages/QSLContact/Controller/QSLContactController.swift
  21. 1 1
      QuickSearchLocation/Classes/Pages/QSLContact/View/QSLContactAddAlertView.swift
  22. 30 14
      QuickSearchLocation/Classes/Pages/QSLFriend/Controller/QSLFriendController.swift
  23. 261 0
      QuickSearchLocation/Classes/Pages/QSLFriend/Controller/QSLSearchFriendVC.swift
  24. 170 66
      QuickSearchLocation/Classes/Pages/QSLHome/Controller/QSLHomeController.swift
  25. 18 3
      QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeAddFriendAlertView.swift
  26. 2 2
      QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeEmptyView.swift
  27. 1 1
      QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeFriendFooterView.swift
  28. 1 1
      QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeFriendView.swift
  29. 106 0
      QuickSearchLocation/Classes/Pages/QSLMine/Controller/QSLFeedbackVC.swift
  30. 8 0
      QuickSearchLocation/Classes/Pages/QSLMine/Controller/QSLMineController.swift
  31. 3 3
      QuickSearchLocation/Classes/Pages/QSLMine/QSQuickLogon/QSQuickLogonHandle.swift
  32. 3 2
      QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLVipController.swift
  33. 470 0
      QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLVipTrialVC.swift
  34. 179 103
      QuickSearchLocation/Classes/Pages/QSLVip/QSLVipManager.swift
  35. 223 0
      QuickSearchLocation/Classes/Pages/QSLVip/View/QSLTrialExpireAlertView.swift
  36. 1 2
      QuickSearchLocation/Info.plist
  37. 22 2
      QuickSearchLocation/Macro/QSLApi.swift
  38. 51 0
      QuickSearchLocation/Macro/QSLConfig.swift
  39. 8 0
      QuickSearchLocation/QuickSearchLocationDebug.entitlements
  40. 8 0
      QuickSearchLocation/QuickSearchLocationRelease.entitlements
  41. 2 2
      QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/Contents.json
  42. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/Group 43677 (1).png
  43. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/Group 43677.png
  44. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/找TA (1).png
  45. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/找TA.png
  46. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/.DS_Store
  47. 22 0
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_func_gift.imageset/Contents.json
  48. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_func_gift.imageset/fuliquan-2.png
  49. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_func_gift.imageset/fuliquan.png
  50. 6 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/Contents.json
  51. 22 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_bg.imageset/Contents.json
  52. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_bg.imageset/Group 43369.png
  53. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_bg.imageset/vip_trial_bottom_bg.png
  54. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_title.imageset/Contents.json
  55. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_title.imageset/vip_trial_bottom_title.png
  56. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_center.imageset/Contents.json
  57. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_center.imageset/图标.png
  58. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top.imageset/Contents.json
  59. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top.imageset/Mask group.png
  60. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_1.imageset/Contents.json
  61. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_1.imageset/精准定位.png
  62. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_2.imageset/Contents.json
  63. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_2.imageset/精准共享 实时当前位置.png
  64. 1 0
      QuickSearchLocation/Tools/QSLDeviceTool.swift

BIN
.DS_Store


+ 48 - 4
QuickSearchLocation.xcodeproj/project.pbxproj

@@ -122,6 +122,12 @@
 		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 */; };
+		FE8645642EAA18D5008A78D4 /* QSLSearchFriendVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8645632EAA18D5008A78D4 /* QSLSearchFriendVC.swift */; };
+		FE8645682EAA3406008A78D4 /* QSLFeedbackVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8645652EAA3406008A78D4 /* QSLFeedbackVC.swift */; };
+		FE86456A2EAA3C05008A78D4 /* QSLVipTrialVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8645692EAA3C05008A78D4 /* QSLVipTrialVC.swift */; };
+		FE86456C2EAA3D15008A78D4 /* QSLTrialExpireAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE86456B2EAA3D15008A78D4 /* QSLTrialExpireAlertView.swift */; };
+		FE86456E2EAA4208008A78D4 /* QSLWakeupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE86456D2EAA4208008A78D4 /* QSLWakeupModel.swift */; };
+		FE8645712EB07D28008A78D4 /* QSLTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE8645702EB07D28008A78D4 /* QSLTools.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 */; };
@@ -137,6 +143,9 @@
 		FED298D42E3B176500F1E0F0 /* QSLGuideIsTriggeredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED298D32E3B176500F1E0F0 /* QSLGuideIsTriggeredModel.swift */; };
 		FED298D62E3B28D800F1E0F0 /* QSLGoodKeysModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED298D52E3B28D800F1E0F0 /* QSLGoodKeysModel.swift */; };
 		FED298DD2E3C682600F1E0F0 /* QSLRetainPopUpAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED298DC2E3C682600F1E0F0 /* QSLRetainPopUpAlertView.swift */; };
+		FEE6AE812EB30921008AC6CE /* QSLLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE6AE802EB30921008AC6CE /* QSLLoadingView.swift */; };
+		FEE6AE832EB30F94008AC6CE /* QSLConfModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEE6AE822EB30F94008AC6CE /* QSLConfModel.swift */; };
+		FEE6AE852EB363DD008AC6CE /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FEE6AE842EB363DC008AC6CE /* UserNotifications.framework */; };
 		FEEB37CA2E28CC8F00BFFD7D /* QSAppleAdHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEB37C92E28CC8F00BFFD7D /* QSAppleAdHandle.swift */; };
 		FEEB37CD2E28CD7A00BFFD7D /* QSWikiHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEB37CC2E28CD7A00BFFD7D /* QSWikiHandle.swift */; };
 		FEF9D30E2E824870001F4660 /* QSLAddFriendSuccessAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEF9D30D2E824870001F4660 /* QSLAddFriendSuccessAlertView.swift */; };
@@ -265,6 +274,13 @@
 		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>"; };
+		FE8645632EAA18D5008A78D4 /* QSLSearchFriendVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLSearchFriendVC.swift; sourceTree = "<group>"; };
+		FE8645652EAA3406008A78D4 /* QSLFeedbackVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLFeedbackVC.swift; sourceTree = "<group>"; };
+		FE8645692EAA3C05008A78D4 /* QSLVipTrialVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLVipTrialVC.swift; sourceTree = "<group>"; };
+		FE86456B2EAA3D15008A78D4 /* QSLTrialExpireAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLTrialExpireAlertView.swift; sourceTree = "<group>"; };
+		FE86456D2EAA4208008A78D4 /* QSLWakeupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLWakeupModel.swift; sourceTree = "<group>"; };
+		FE86456F2EAB1E7C008A78D4 /* QuickSearchLocationRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QuickSearchLocationRelease.entitlements; sourceTree = "<group>"; };
+		FE8645702EB07D28008A78D4 /* QSLTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLTools.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>"; };
@@ -280,6 +296,10 @@
 		FED298D32E3B176500F1E0F0 /* QSLGuideIsTriggeredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLGuideIsTriggeredModel.swift; sourceTree = "<group>"; };
 		FED298D52E3B28D800F1E0F0 /* QSLGoodKeysModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLGoodKeysModel.swift; sourceTree = "<group>"; };
 		FED298DC2E3C682600F1E0F0 /* QSLRetainPopUpAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLRetainPopUpAlertView.swift; sourceTree = "<group>"; };
+		FEE6AE802EB30921008AC6CE /* QSLLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLLoadingView.swift; sourceTree = "<group>"; };
+		FEE6AE822EB30F94008AC6CE /* QSLConfModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLConfModel.swift; sourceTree = "<group>"; };
+		FEE6AE842EB363DC008AC6CE /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
+		FEE6AE862EB36694008AC6CE /* QuickSearchLocationDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = QuickSearchLocationDebug.entitlements; sourceTree = "<group>"; };
 		FEEB37C92E28CC8F00BFFD7D /* QSAppleAdHandle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSAppleAdHandle.swift; sourceTree = "<group>"; };
 		FEEB37CC2E28CD7A00BFFD7D /* QSWikiHandle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSWikiHandle.swift; sourceTree = "<group>"; };
 		FEF9D30D2E824870001F4660 /* QSLAddFriendSuccessAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLAddFriendSuccessAlertView.swift; sourceTree = "<group>"; };
@@ -291,6 +311,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				FEE6AE852EB363DD008AC6CE /* UserNotifications.framework in Frameworks */,
 				FE638ACC2D1964CA00858121 /* AdSupport.framework in Frameworks */,
 				FE638ACA2D1964C500858121 /* AppTrackingTransparency.framework in Frameworks */,
 				FE638AC82D1964B000858121 /* libsqlite3.tbd in Frameworks */,
@@ -365,6 +386,7 @@
 			isa = PBXGroup;
 			children = (
 				04F33BE42BC69305003E2111 /* QSLMineController.swift */,
+				FE8645652EAA3406008A78D4 /* QSLFeedbackVC.swift */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -416,6 +438,8 @@
 		04F33BA42BC6367C003E2111 /* QuickSearchLocation */ = {
 			isa = PBXGroup;
 			children = (
+				FEE6AE862EB36694008AC6CE /* QuickSearchLocationDebug.entitlements */,
+				FE86456F2EAB1E7C008A78D4 /* QuickSearchLocationRelease.entitlements */,
 				FE638ABC2D1963B800858121 /* Frameworks */,
 				04F33BB92BC637B8003E2111 /* Macro */,
 				04F33BBE2BC63B38003E2111 /* Tools */,
@@ -591,6 +615,8 @@
 				FE638AA52D097EDD00858121 /* QSLOrderModel.swift */,
 				FE638AB22D0ACA4D00858121 /* QSLContactModel.swift */,
 				FED298D32E3B176500F1E0F0 /* QSLGuideIsTriggeredModel.swift */,
+				FE86456D2EAA4208008A78D4 /* QSLWakeupModel.swift */,
+				FEE6AE822EB30F94008AC6CE /* QSLConfModel.swift */,
 			);
 			path = Model;
 			sourceTree = "<group>";
@@ -598,6 +624,7 @@
 		174C5FA1328123954EB9B663 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				FEE6AE842EB363DC008AC6CE /* UserNotifications.framework */,
 				FE638ACB2D1964CA00858121 /* AdSupport.framework */,
 				FE638AC92D1964C500858121 /* AppTrackingTransparency.framework */,
 				FE638AC72D1964B000858121 /* libsqlite3.tbd */,
@@ -730,6 +757,7 @@
 			isa = PBXGroup;
 			children = (
 				04F33BE22BC692F1003E2111 /* QSLFriendController.swift */,
+				FE8645632EAA18D5008A78D4 /* QSLSearchFriendVC.swift */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -808,6 +836,7 @@
 			children = (
 				FE8360802CF723FA00978E03 /* QSLVipController.swift */,
 				FEC3D9552E8276CB007164A9 /* QSLActivityVipVC.swift */,
+				FE8645692EAA3C05008A78D4 /* QSLVipTrialVC.swift */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -819,6 +848,7 @@
 				FED298C52E38AB5500F1E0F0 /* QSLVipResultsAlertView.swift */,
 				FED298C72E38B51400F1E0F0 /* QSLVipResultsNoMemberAlertView.swift */,
 				FED298DC2E3C682600F1E0F0 /* QSLRetainPopUpAlertView.swift */,
+				FE86456B2EAA3D15008A78D4 /* QSLTrialExpireAlertView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -867,6 +897,7 @@
 				FE83609F2D00813400978E03 /* QSLPopView.swift */,
 				FE8360A12D00814000978E03 /* QSLPopViewCell.swift */,
 				FE638A9D2D0709C900858121 /* QSLPrivacyAlertView.swift */,
+				FEE6AE802EB30921008AC6CE /* QSLLoadingView.swift */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -890,6 +921,7 @@
 				FE638AD32D1ABB9800858121 /* QSLJumpManager.swift */,
 				FED298CF2E3A2C1700F1E0F0 /* QSLStatisticsUserTimeManager.swift */,
 				FED298D12E3B0EDD00F1E0F0 /* QSLGuideusersToCommentManager.swift */,
+				FE8645702EB07D28008A78D4 /* QSLTools.swift */,
 			);
 			path = Tool;
 			sourceTree = "<group>";
@@ -1070,7 +1102,9 @@
 				FE8360902CFFFAD600978E03 /* QSLAlertView.swift in Sources */,
 				FE8360A42D014EDA00978E03 /* QSLMessageHeaderView.swift in Sources */,
 				FE8360B32D02939600978E03 /* QSLSocketManager.swift in Sources */,
+				FE8645642EAA18D5008A78D4 /* QSLSearchFriendVC.swift in Sources */,
 				FED298C62E38AB5500F1E0F0 /* QSLVipResultsAlertView.swift in Sources */,
+				FEE6AE812EB30921008AC6CE /* QSLLoadingView.swift in Sources */,
 				FE638AB92D195D5000858121 /* QSLGravityConst.swift in Sources */,
 				FE83609A2D004E3400978E03 /* QSLBaseManager.swift in Sources */,
 				FED298C82E38B51400F1E0F0 /* QSLVipResultsNoMemberAlertView.swift in Sources */,
@@ -1109,6 +1143,7 @@
 				FED298D42E3B176500F1E0F0 /* QSLGuideIsTriggeredModel.swift in Sources */,
 				04F33BCD2BC67486003E2111 /* UIView+Extension.swift in Sources */,
 				FE638AB02D0A8FF700858121 /* QSLContactAddAlertView.swift in Sources */,
+				FE86456C2EAA3D15008A78D4 /* QSLTrialExpireAlertView.swift in Sources */,
 				FE3046E22E838ECA00BC44E2 /* QSLCountdownManager.swift in Sources */,
 				FE8360932D003AA300978E03 /* QSLNetwork.swift in Sources */,
 				FED298C42E37267100F1E0F0 /* QSLVipAlertView.swift in Sources */,
@@ -1122,11 +1157,13 @@
 				FE94B4F42D23F09100D2B001 /* LoadingViewController.swift in Sources */,
 				04F33BCF2BC675C5003E2111 /* UIApplication+Extension.swift in Sources */,
 				04F33BF02BC78D54003E2111 /* QSLMapTrackModel.swift in Sources */,
+				FE86456A2EAA3C05008A78D4 /* QSLVipTrialVC.swift in Sources */,
 				04F33BEB2BC6A657003E2111 /* UIImage+Extension.swift in Sources */,
 				FE3046E42E838F0200BC44E2 /* QSLCountdownView.swift in Sources */,
 				FE8360752CF707FE00978E03 /* QSLMessageTableViewCell.swift in Sources */,
 				04B666CF2BC92B3A0020BFBD /* UITableView+Extension.swift in Sources */,
 				04F33BC52BC64566003E2111 /* CustomTabBarController.swift in Sources */,
+				FE8645682EAA3406008A78D4 /* QSLFeedbackVC.swift in Sources */,
 				FE83608D2CFF08A600978E03 /* QSLRoadMainView.swift in Sources */,
 				04B666BA2BC7BD020020BFBD /* UIButton+Extension.swift in Sources */,
 				04B6B51C2BCCFF7000777EB4 /* DateFormatter+Extension.swift in Sources */,
@@ -1159,16 +1196,19 @@
 				FE8360982D0041F300978E03 /* QSLCacheManager.swift in Sources */,
 				FE8360AD2D01A04800978E03 /* QSLRequestModel.swift in Sources */,
 				FED298D02E3A2C1700F1E0F0 /* QSLStatisticsUserTimeManager.swift in Sources */,
+				FE86456E2EAA4208008A78D4 /* QSLWakeupModel.swift in Sources */,
 				04B6B5292BCE1D5C00777EB4 /* QSLMineFuncCollectionViewCell.swift in Sources */,
 				FEEB37CA2E28CC8F00BFFD7D /* QSAppleAdHandle.swift in Sources */,
 				FE638AB32D0ACA4D00858121 /* QSLContactModel.swift in Sources */,
 				04F33BD72BC67E90003E2111 /* QSLDeviceTool.swift in Sources */,
 				04B6B5202BCD1D2C00777EB4 /* QSLMineInfoView.swift in Sources */,
 				04F33BC72BC66F5C003E2111 /* UIColor+Extension.swift in Sources */,
+				FE8645712EB07D28008A78D4 /* QSLTools.swift in Sources */,
 				FE8360C02D06D33500978E03 /* QSLAppInfoController.swift in Sources */,
 				FE638AA22D096E6600858121 /* QSLGoodModel.swift in Sources */,
 				FEEB37CD2E28CD7A00BFFD7D /* QSWikiHandle.swift in Sources */,
 				FE638AA62D097EDD00858121 /* QSLOrderModel.swift in Sources */,
+				FEE6AE832EB30F94008AC6CE /* QSLConfModel.swift in Sources */,
 				FE8360A02D00813400978E03 /* QSLPopView.swift in Sources */,
 				04F33BCB2BC672E4003E2111 /* QSLConfig.swift in Sources */,
 				FE83607C2CF7140200978E03 /* QSLAddController.swift in Sources */,
@@ -1340,9 +1380,10 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = QuickSearchLocation/QuickSearchLocationDebug.entitlements;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 31;
+				CURRENT_PROJECT_VERSION = 32;
 				DEVELOPMENT_TEAM = Q364C8K9BL;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -1355,6 +1396,7 @@
 				INFOPLIST_KEY_NSContactsUsageDescription = "手机关爱定位需要您同意访问通讯录的权限用于添加好友功能";
 				INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限";
 				INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限";
+				INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限";
 				INFOPLIST_KEY_NSUserTrackingUsageDescription = "手机关爱定位为了显示个性化广告需要使用您的广告标识符";
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
@@ -1366,7 +1408,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 1.2.7;
+				MARKETING_VERSION = 1.2.8;
 				PRODUCT_BUNDLE_IDENTIFIER = com.manbu.shouji;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1384,9 +1426,10 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = QuickSearchLocation/QuickSearchLocationRelease.entitlements;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 31;
+				CURRENT_PROJECT_VERSION = 32;
 				DEVELOPMENT_TEAM = Q364C8K9BL;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -1399,6 +1442,7 @@
 				INFOPLIST_KEY_NSContactsUsageDescription = "手机关爱定位需要您同意访问通讯录的权限用于添加好友功能";
 				INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限";
 				INFOPLIST_KEY_NSLocationAlwaysUsageDescription = "手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限";
+				INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限";
 				INFOPLIST_KEY_NSUserTrackingUsageDescription = "手机关爱定位为了显示个性化广告需要使用您的广告标识符";
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
@@ -1410,7 +1454,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 1.2.7;
+				MARKETING_VERSION = 1.2.8;
 				PRODUCT_BUNDLE_IDENTIFIER = com.manbu.shouji;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE_SPECIFIER = "";

+ 4 - 0
QuickSearchLocation/Classes/AppleAD/QSWikiHandle.swift

@@ -45,6 +45,10 @@ class QSWikiHandle {
                 dict["keyword_id"] = keywordId
             }
             
+            if let attribution = payLoad["attribution"] as? Bool {
+                UserDefaults.standard.setValue(attribution, forKey: "QSAttribution")
+            }
+            
             let date = Date()
             let formatter = DateFormatter()
             formatter.timeZone = TimeZone.autoupdatingCurrent

+ 26 - 0
QuickSearchLocation/Classes/Common/Model/QSLConfModel.swift

@@ -0,0 +1,26 @@
+//
+//  QSLConfModel.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/30.
+//
+
+import MoyaMapper
+import SwiftyJSON
+
+struct QSLConfModel: Modelable {
+
+    var searchFriendContent: String = "查找好友"
+    
+    var phoneLocationEnable: Bool = false
+    
+    var authPopEnable: Bool = false
+
+    var loginPayEnable: Bool = true
+    
+    var location: String = ""
+    
+    mutating func mapping(_ json: JSON) {
+        
+    }
+}

+ 24 - 0
QuickSearchLocation/Classes/Common/Model/QSLWakeupModel.swift

@@ -0,0 +1,24 @@
+//
+//  QSLWakeupModel.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/23.
+//
+
+import MoyaMapper
+import SwiftyJSON
+
+struct QSLWakeupModel: Modelable {
+    mutating func mapping(_ json: SwiftyJSON.JSON) {
+        
+    }
+    
+
+    var title: String = ""
+    
+    var subTitle: String = ""
+    
+    var functionType: String = ""
+    
+}
+

+ 25 - 0
QuickSearchLocation/Classes/Common/Tool/QSLCacheManager.swift

@@ -44,6 +44,31 @@ class QSLCacheManager {
             UserDefaults.standard.removeObject(forKey: "QSLUserModel")
         }
     }
+    
+    // 缓存用配置模型
+    static func cacheConfModel(_ model: QSLConfModel) {
+        let encoder = JSONEncoder()
+        do {
+            let data = try encoder.encode(model)
+            UserDefaults.standard.set(data, forKey: "QSLConfModel")
+        } catch {
+            debugPrint("Encode wrong: \(error)")
+        }
+    }
+
+    // 获取
+    static func getConfModel() -> QSLConfModel? {
+        if let data = UserDefaults.standard.data(forKey: "QSLConfModel") {
+            let decoder = JSONDecoder()
+            do {
+                let model = try decoder.decode(QSLConfModel.self, from: data)
+                return model
+            } catch {
+                debugPrint("Decode wrong: \(error)")
+            }
+        }
+        return nil
+    }
 }
 
 // 订单模型

+ 49 - 13
QuickSearchLocation/Classes/Common/Tool/QSLCountdownManager.swift

@@ -22,19 +22,33 @@ class QSLCountdownManager {
             }
         }
     }
-    var remainingSeconds: Int = 900 * 1000 // 15分钟 = 900秒
+    
+    var trialGood: QSLGoodModel?{
+        didSet{
+            if(oldValue != nil){
+                NotificationCenter.default.post(
+                    name: Notification.Name("QSLHomeRefreshCouponViewNoti"),
+                    object: nil,
+                    userInfo: nil
+                )
+            }
+        }
+    }
+    
+    var remainingSeconds: Int = 900 * 1000 // 15分钟 = 900秒  (正常套餐活动倒计时)
+    var trialSeconds: Int = -999 // 15分钟 = 900秒  (试用活动倒计时)
     var updateHandler: ((String) -> Void)?
     var updateHandler1: ((String) -> Void)?
+    var updateTrialHandler: ((String) -> Void)?
     
     var finishHandler: (() -> Void)?
     
     func startCountdown() {
         timer?.invalidate()
         timer = nil
-        if(selectGood == nil){
-            return
-        }
+        
         remainingSeconds = 900 * 1000
+        
         timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(updateCountdown), userInfo: nil, repeats: true)
         RunLoop.current.add(timer!, forMode: .common)
     }
@@ -54,20 +68,42 @@ class QSLCountdownManager {
     }
     
     @objc private func updateCountdown() {
+        
+        
         remainingSeconds -= 1
-        if remainingSeconds <= 0 {
+        trialSeconds -= 1
+        
+        
+        if remainingSeconds <= 0 && trialSeconds <= 0{
             stopCountdown()
         }
         
-        let totalSeconds = remainingSeconds / 1000
-        let minutes = totalSeconds / 60
-        let seconds = totalSeconds % 60
-        let milliseconds = remainingSeconds % 1000
+        if remainingSeconds > 0 {
+            let totalSeconds = remainingSeconds / 1000
+            let minutes = totalSeconds / 60
+            let seconds = totalSeconds % 60
+            let milliseconds = remainingSeconds % 1000
+            
+            // 格式:MM:SS:SSS(例如 "14:59:500")
+            let timeString = String(format: "%02d : %02d : %03d", minutes, seconds, milliseconds)
+            updateHandler?(timeString)
+            updateHandler1?(timeString)
+        }else{
+            remainingSeconds = 0
+        }
         
-        // 格式:MM:SS:SSS(例如 "14:59:500")
-        let timeString = String(format: "%02d : %02d : %03d", minutes, seconds, milliseconds)
-        updateHandler?(timeString)
-        updateHandler1?(timeString)
+        if trialSeconds > 0 {
+            let totalSeconds = trialSeconds / 1000
+            let minutes = totalSeconds / 60
+            let seconds = totalSeconds % 60
+            let milliseconds = trialSeconds % 1000
+            
+            // 格式:MM:SS:SSS(例如 "14:59:500")
+            let timeString = String(format: "%02d : %02d : %03d", minutes, seconds, milliseconds)
+            updateTrialHandler?(timeString)
+        }else{
+            trialSeconds = 0
+        }
     }
     
     deinit {

+ 15 - 27
QuickSearchLocation/Classes/Common/Tool/QSLGuideusersToCommentManager.swift

@@ -78,34 +78,27 @@ class QSLGuideusersToCommentManager: NSObject {
     
     private func timerFired() {
         // Call your existing method here
-        manageWhetherTriggerPopUpWindow(commentType)
+//        manageWhetherTriggerPopUpWindow(commentType)
     }
     
     // MARK: - Existing Methods (unchanged)
     
     //管理处理是否触发好评引导弹窗
-    func manageWhetherTriggerPopUpWindow(_ showType: QSLGuideusersToCommentType) {
+    func manageWhetherTriggerPopUpWindow(_ showType: QSLGuideusersToCommentType, closeBtnClosure: @escaping () -> () = {}) {
         //print("startTimersfsdf---C--\(showType)---\(self.commentType)")
-//        QSLNetwork().request(.guideIsTriggered(dict: [String: Any]())) { response in
-//            let guideIsModel: QSLGuideIsTriggeredModel = response.mapObject(QSLGuideIsTriggeredModel.self, modelKey: "data")
-//            self.commentType = showType
-//            self.guideGobalModel = guideIsModel
-//            if guideIsModel.trigger  && self.areThisTwoChannel(){
-//                DispatchQueue.main.async {
-//                    self.noMemberPositiveReviewPopWindow()
-//                }
-//                /*if showType == .member {
-//                    DispatchQueue.main.async {
-//                        self.memberPositiveReviewPopWindow()
-//                    }
-//                } else {
-//                    DispatchQueue.main.async {
-//                        self.noMemberPositiveReviewPopWindow()
-//                    }
-//                }*/
-//            }
-//        } fail: { code, msg in
-//        }
+        QSLNetwork().request(.guideIsTriggered(dict: [String: Any]())) { response in
+            let guideIsModel: QSLGuideIsTriggeredModel = response.mapObject(QSLGuideIsTriggeredModel.self, modelKey: "data")
+            self.commentType = showType
+            self.guideGobalModel = guideIsModel
+            if guideIsModel.trigger{
+                DispatchQueue.main.async {
+                    self.noMemberPositiveReviewPopWindow(closeBtnClosure: closeBtnClosure)
+                }
+            }else{
+                closeBtnClosure()
+            }
+        } fail: { code, msg in
+        }
     }
     
     //判断是不是这两个渠道 ASA渠道和自然流量两个渠道
@@ -204,11 +197,6 @@ extension QSLGuideusersToCommentManager {
                 // 同步调用
                 QSLInAppReviewmanager.requestReview()
                 
-                // 延迟1秒执行
-                /*DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                    self?.requestForReceivingGoodReviewGuidance()
-                }*/
-                //self?.requestAddFri()
             },closeBtnClosure: {
                 closeBtnClosure()
             })

+ 8 - 1
QuickSearchLocation/Classes/Common/Tool/QSLJumpManager.swift

@@ -25,7 +25,7 @@ class QSLJumpManager: NSObject {
 }
 
 extension QSLJumpManager {
-    
+
     // 跳转到Vip页面
     func pushToVip(type: QSLVipJumpType) {
         
@@ -129,5 +129,12 @@ extension QSLJumpManager {
         vc.type = type
         self.rootViewController()?.pushVC(vc: vc)
     }
+    
+    // 跳转到会员试用页面
+    func pushToVipTrail(type: QSLTrialVipJumpType) {
+        let vc = QSLVipTrialVC()
+        vc.type = type
+        self.rootViewController()?.pushVC(vc: vc)
+    }
 }
 

+ 179 - 0
QuickSearchLocation/Classes/Common/Tool/QSLTools.swift

@@ -0,0 +1,179 @@
+//
+//  QSLTools.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/28.
+//
+
+import UIKit
+
+class QSLTools: NSObject {
+    
+    static let shared = QSLTools()
+    var isOpen = false
+    var urlScheme = ""
+    private override init() {}
+}
+
+extension QSLTools {
+
+    /// 获取设备令牌
+    func getDeviceToken() -> String {
+        if let token = UserDefaults.standard.string(forKey: "deviceToken") {
+            return token
+        } else {
+            return ""
+        }
+    }
+    
+    /// 请求推送权限
+    func requestNotificationPermission() {
+        UNUserNotificationCenter.current().requestAuthorization(
+            options: [.alert, .sound, .badge]
+        ) { granted, error in
+            DispatchQueue.main.async {
+                if granted {
+                    DispatchQueue.main.async {
+                        UIApplication.shared.registerForRemoteNotifications()
+                    }
+                } else if let error = error {
+                    print("Error: \(error.localizedDescription)")
+                }
+            }
+        }
+    }
+    
+    func dealwithScheme(_ scheme: String) {
+        // 将字符串转换为 URL 对象
+        guard let url = URL(string: scheme) else {
+            print("无效的 URL scheme")
+            return
+        }
+        
+        // 检查 scheme 是否为 location
+        guard url.scheme == "location" else {
+            print("不支持的 scheme 类型")
+            return
+        }
+        
+        if #available(iOS 16.0, *) {
+            let host = url.host()
+            let pathComponents = url.lastPathComponent
+            let query = url.query()
+            jumpToPath(path: host ?? "", pathName: pathComponents, param: query ?? "")
+        } else {
+            let currentPath = scheme.replacingOccurrences(of: "location://", with: "")
+            let pathComponents = url.lastPathComponent
+            let queryList = currentPath.components(separatedBy: "?")
+            if(queryList.count > 1){
+                let host = currentPath.replacingOccurrences(of: pathComponents, with: "").replacingOccurrences(of: "/", with: "")
+                let query = currentPath.replacingOccurrences(of: host, with: "")
+                jumpToPath(path: host, pathName: pathComponents.replacingOccurrences(of: "/", with: ""), param: query)
+            }else{
+                let host = currentPath.replacingOccurrences(of: pathComponents, with: "").replacingOccurrences(of: "/", with: "")
+                jumpToPath(path: host, pathName: pathComponents.replacingOccurrences(of: "/", with: ""), param: "")
+            }
+        }
+
+    }
+    
+    func jumpToPath(path:String, pathName:String, param:String = ""){
+        if path == "dialog" {
+            let dialogType = pathName
+            
+            switch dialogType {
+            case "member_trial":
+                QSLJumpManager.shared.pushToVipTrail(type: .notiPush)
+                break;
+            default:
+                print("未知的对话框类型: \(dialogType)")
+            }
+        }else if path == "page" {
+            if(pathName == "QSLVipController"){
+                QSLJumpManager.shared.pushToVip(type: .shortcut)
+                return
+            }
+            let controllerName = pathName
+            navigateToViewController(controllerName)
+        }else if path == "shortcut" {
+            if(pathName == "com.manbu.shouji.member_or_trial"){
+                checkMemeberOrTrial()
+                return
+            }
+          
+        }else{
+            print("未知的路径类型")
+        }
+    }
+    
+    func checkMemeberOrTrial(){
+        QSLNetwork().request(.wakeUpPressCheck(dict: [String: Any]())) { response in
+            let model: QSLWakeupModel = response.mapObject(QSLWakeupModel.self, modelKey: "data")
+            var scheme = "location://page/QSLVipController"
+            if(model.functionType == "trial"){
+                scheme = "location://page/QSLVipTrialVC"
+            }
+            if(QSLTools.shared.isOpen){
+                //处理urlScheme
+                QSLTools.shared.urlScheme = ""
+                QSLTools.shared.dealwithScheme(scheme)
+                return
+            }
+            
+            QSLTools.shared.urlScheme = scheme
+        } fail: { code, msg in
+           
+        }
+    }
+    
+    func navigateToViewController(_ controllerName: String) {
+        
+        // 获取命名空间(Swift 类名通常是 "YourAppName.ViewController")
+        let namespace = Bundle.main.infoDictionary?["CFBundleExecutable"] as? String ?? ""
+        let fullClassName = "\(namespace).\(controllerName)"
+        
+        // 通过类名创建控制器实例
+        guard let controllerClass = NSClassFromString(fullClassName) as? UIViewController.Type else {
+            print("找不到控制器类: \(controllerName)")
+            return
+        }
+        
+        let viewController = controllerClass.init()
+        self.rootViewController()?.pushVC(vc: viewController)
+    }
+    
+    func requestShortcutItem(){
+        //判断登录过没有
+        if QSLBaseManager.shared.isLogin() {
+            var isAttr = false
+            if((UserDefaults.standard.value(forKey: "QSAttribution")) != nil){
+                if let attr = UserDefaults.standard.value(forKey: "QSAttribution") as? Bool {
+                    isAttr = attr
+                }
+            }
+            QSLNetwork().request(.wakeUpPressInfo(dict: ["attribution":isAttr])) { response in
+                let model: QSLWakeupModel = response.mapObject(QSLWakeupModel.self, modelKey: "data")
+                var iconName = "mine_func_gift"
+                if(model.functionType == "feedback"){
+                    iconName = "mine_func_advice"
+                }
+                self.setupShortcutItem(typeName: model.functionType, title: model.title, subTitle: model.subTitle, icon: iconName)
+                
+            } fail: { code, msg in
+                
+            }
+        }
+    }
+    
+    func setupShortcutItem(typeName:String, title: String, subTitle:String, icon:String ){
+        let shortcutItem = UIApplicationShortcutItem(
+            type: "com.manbu.shouji." + typeName,
+            localizedTitle: title,
+            localizedSubtitle: subTitle,
+            icon: UIApplicationShortcutIcon(templateImageName: icon),
+            userInfo: nil
+        )
+        UIApplication.shared.shortcutItems = [shortcutItem]
+    }
+    
+}

+ 91 - 0
QuickSearchLocation/Classes/Common/View/QSLLoadingView.swift

@@ -0,0 +1,91 @@
+//
+//  QSLLoadingView.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/30.
+//
+
+import UIKit
+
+class QSLLoadingView: UIView {
+
+    private let statusLabel = UILabel()
+    private let progressLabel = UILabel()
+    private let progressLayer = CAShapeLayer()
+    private let gradientLayer = CAGradientLayer()
+
+    var progress: CGFloat = 0 {
+        didSet {
+            updateProgress()
+        }
+    }
+
+    var completion: (() -> Void)?
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setupView()
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    private func setupView() {
+        self.gradientBackgroundColor(color1: .hexStringColor(hexString: "#D3FFF6"), color2: .white, width: 170.rpx, height: 170.rpx, direction: .horizontal)
+        self.layer.cornerRadius = 16.rpx
+
+        statusLabel.textAlignment = .center
+        statusLabel.textColor = .red
+        statusLabel.font = UIFont.boldSystemFont(ofSize: 12)
+        statusLabel.translatesAutoresizingMaskIntoConstraints = false
+        self.addSubview(statusLabel)
+
+        progressLabel.textAlignment = .center
+        progressLabel.textColor = .black
+        progressLabel.font = UIFont.boldSystemFont(ofSize: 20)
+        progressLabel.translatesAutoresizingMaskIntoConstraints = false
+        self.addSubview(progressLabel)
+
+        let circularPath = UIBezierPath(arcCenter: CGPoint(x: 85.rpx, y: 85.rpx), radius: 44.rpx, startAngle: -CGFloat.pi / 2, endAngle: 3 * CGFloat.pi / 2, clockwise: true)
+        progressLayer.path = circularPath.cgPath
+        progressLayer.strokeColor = UIColor.gray.cgColor
+        progressLayer.fillColor = UIColor.clear.cgColor
+        progressLayer.lineWidth = 8
+        progressLayer.lineCap = .round
+        self.layer.addSublayer(progressLayer)
+
+        gradientLayer.colors = [UIColor.hexStringColor(hexString: "#19D9B1").cgColor, UIColor.hexStringColor(hexString: "#19BFD9").cgColor]
+        gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
+        gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
+        gradientLayer.frame = self.bounds
+        gradientLayer.mask = progressLayer
+        self.layer.addSublayer(gradientLayer)
+
+        NSLayoutConstraint.activate([
+            statusLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 20),
+            statusLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor),
+
+            progressLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor),
+            progressLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor)
+            
+            
+        ])
+    }
+
+    private func updateProgress() {
+        progressLayer.strokeEnd = progress / 100
+        progressLabel.text = "\(Int(progress))%"
+        print("progress:::\(progress)")
+        if progress < 40 {
+            statusLabel.text = "匹配中"
+            statusLabel.textColor = .hexStringColor(hexString: "#F94848")
+        } else if progress < 99 {
+            statusLabel.text = "处理中"
+            statusLabel.textColor = .hexStringColor(hexString: "#4886F9")
+        } else if progress >= 100 {
+            statusLabel.text = "处理完成"
+            statusLabel.textColor = .hexStringColor(hexString: "#1DBA5E")
+        }
+    }
+}

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

@@ -45,7 +45,6 @@ extension QSLCentralNetworkAPI: TargetType {
                 parameters[key] = value
             }
         }
-        
         debugPrint(parameters)
         return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
     }

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

@@ -8,21 +8,34 @@
 import UIKit
 import AMapFoundationKit
 import IQKeyboardManagerSwift
+import UserNotifications
 
 @main
 class AppDelegate: UIResponder, UIApplicationDelegate {
 
     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
         // Override point for customization after application launch.
+        QSLTools.shared.isOpen = false
+        UIApplication.shared.shortcutItems = []
         
-        Thread.sleep(forTimeInterval: 1)
+        Thread.sleep(forTimeInterval: 0.5)
         IQKeyboardManager.shared.enable = true
         AMapServices.shared().apiKey = QSLConfig.MapKey
         QSLDeviceTool.shared.configure(autoRefresh: true)
         
+        configNoti()
+        
         return true
     }
 
+    func configNoti(){
+        UNUserNotificationCenter.current().delegate = self
+        // 请求静默推送权限
+        UNUserNotificationCenter.current().requestAuthorization(
+            options: [.provisional]
+        ) { granted, error in
+        }
+    }
     
     // MARK: UISceneSession Lifecycle
     func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
@@ -41,5 +54,57 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         
         QSEventHandle.gravityPush(eventName: QSLGravityConst.app_exit, eventProps: ["id": 02002])
     }
+    
+}
+
+extension AppDelegate : UNUserNotificationCenterDelegate{
+    
+    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
+        let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
+        UserDefaults.standard.set(token, forKey: "deviceToken")
+        print("notification token: \(token)")
+
+        QSLNetwork().request(.notiTokenReport(dict: ["deviceToken":token])) { response in
+            
+        } fail: { code, error in
+
+        }
+    }
+    
+    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
+        let userInfo = notification.request.content.userInfo
+        print("Foreground notification received: \(userInfo)")
+        
+        if(userInfo.keys.contains("urlScheme")){
+            dealwithUserifo(scheme: userInfo["urlScheme"] as! String)
+        }
+        
+        // 显示通知
+        completionHandler([.alert, .sound, .badge])
+    }
+    
+    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
+
+        let userInfo = response.notification.request.content.userInfo
+        print("Notification tapped: \(userInfo)")
+        
+        if(userInfo.keys.contains("urlScheme")){
+            dealwithUserifo(scheme: userInfo["urlScheme"] as! String)
+        }
+        
+        completionHandler()
+    }
+    
+    func dealwithUserifo(scheme: String){
+        //这里要判断是否已经处于首页 如果在首页直接打开 不在首页等进首页再打开
+        if(QSLTools.shared.isOpen){
+            //处理urlScheme
+            QSLTools.shared.urlScheme = ""
+            QSLTools.shared.dealwithScheme(scheme)
+            return
+        }
+        
+        QSLTools.shared.urlScheme = scheme
+    }
 }
 

+ 20 - 0
QuickSearchLocation/Classes/Main/CustomTabBarController.swift

@@ -20,6 +20,14 @@ class CustomTabBarController: UITabBarController {
     override func viewDidLoad() {
         super.viewDidLoad()
         
+        if(QSLCacheManager.getModel() == nil){
+            requestConfig()
+            Thread.sleep(forTimeInterval: 1)
+        }else{
+            requestConfig()
+        }
+        
+        
         // 设置 tabbar 样式
         self.setTabBarAppearence()
         // 添加 tab 页
@@ -30,6 +38,18 @@ class CustomTabBarController: UITabBarController {
         managerAppOnlyLaunch()
     }
     
+    func requestConfig(){
+        QSLNetwork().request(.confGlobal(dict: [String: Any]())) { response in
+            var model = response.mapObject(QSLConfModel.self, modelKey: "data")
+            QSLCacheManager.cacheConfModel(model)
+        } fail: { code, msg in
+            if(QSLCacheManager.getModel() == nil){
+                let model = QSLConfModel.init()
+                QSLCacheManager.cacheConfModel(model)
+            }
+        }
+    }
+    
     //管理app启动埋点
     func managerAppOnlyLaunch() {
         

+ 32 - 1
QuickSearchLocation/Classes/Main/SceneDelegate.swift

@@ -14,9 +14,40 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
     var isShowTipView : Bool = true
 
     func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
-        
+        // 检查是否通过捷径启动 未启动状态
+        if connectionOptions.shortcutItem != nil {
+            dealWithShortcutItem(connectionOptions.shortcutItem?.type ?? "")
+        }
         guard let _ = (scene as? UIWindowScene) else { return }
     }
+    
+    func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
+        dealWithShortcutItem(shortcutItem.type)
+        completionHandler(true)
+    }
+    
+    func dealWithShortcutItem(_ type: String){
+        var scheme = ""
+        
+        if type == "com.manbu.shouji.feedback"{
+            scheme = "location://page/QSLFeedbackVC"
+        }else if type == "com.manbu.shouji.trial"{
+            scheme = "location://page/QSLVipTrialVC"
+        }else if type == "com.manbu.shouji.member"{
+            scheme = "location://page/QSLVipController"
+        }else{
+            scheme = "location://shortcut/" + type
+        }
+        if(QSLTools.shared.isOpen){
+            //处理urlScheme
+            QSLTools.shared.urlScheme = ""
+            QSLTools.shared.dealwithScheme(scheme)
+            return
+        }
+        
+        QSLTools.shared.urlScheme = scheme
+       
+    }
 
     func sceneDidDisconnect(_ scene: UIScene) {
         // Called as the scene is being released by the system.

+ 2 - 18
QuickSearchLocation/Classes/Main/ViewController.swift

@@ -11,24 +11,7 @@ class ViewController: UIViewController {
 
     override func viewDidLoad() {
         super.viewDidLoad()
-        
-        let isNotAgreePrivacyKey = UserDefaults.standard.bool(forKey: "isNotAgreePrivacyKey")
-        // 是否同意隐私政策
-        if !isNotAgreePrivacyKey {
-            QSLPrivacyAlertView.alert(view: view) {
-                
-                self.intoMain()
-                
-                UserDefaults.standard.set(true, forKey: "isNotAgreePrivacyKey")
-            } serviceCloure: {
-                self.agreementAction()
-            } privacyClosure: {
-                self.privacyAction()
-            }
-
-        } else {
-            intoMain()
-        }
+        self.intoMain()
     }
     
     func intoMain() {
@@ -51,6 +34,7 @@ class ViewController: UIViewController {
                 sceneDelegate.window?.makeKeyAndVisible()
             }
         }
+        
     }
     
     // 用户协议跳转

+ 45 - 0
QuickSearchLocation/Classes/Network/QSLNetwork.swift

@@ -26,6 +26,8 @@ enum QSLNetworkAPI {
     case userMember(dict: [String: Any])
     case userLogin(dict: [String: Any])
     case userClear(dict: [String: Any])
+    case userPhoneAttribution(dict: [String: Any])
+    
     case friendList(dict: [String: Any])
     case requestSend(dict: [String: Any])
     case requestList(dict: [String: Any])
@@ -54,6 +56,14 @@ enum QSLNetworkAPI {
     case loginOneclick(dict: [String: Any])
     case guideIsTriggered(dict: [String : Any])
     case guideReceiveReward(dict: [String : Any])
+    
+    case wakeupTrialList(dict: [String: Any])
+    case wakeUpPressInfo(dict: [String : Any])
+    case wakeUpPressCheck(dict: [String : Any])
+
+    case confGlobal(dict: [String : Any])
+
+    case notiTokenReport(dict: [String : Any])
 }
 
 extension QSLNetworkAPI: TargetType {
@@ -103,6 +113,16 @@ extension QSLNetworkAPI: TargetType {
         case .loginOneclick: return QSLApi.login_oneclick
         case .guideIsTriggered: return QSLApi.guide_is_triggered
         case .guideReceiveReward: return QSLApi.guide_receisve_reward
+            
+
+        case .wakeupTrialList: return QSLApi.wakeup_trial_list
+        case .wakeUpPressInfo: return QSLApi.wakeup_press_info
+        case .wakeUpPressCheck: return QSLApi.wakeup_press_check
+        case .confGlobal: return QSLApi.conf_global
+            
+        case .userPhoneAttribution: return QSLApi.user_phone_attr
+            
+        case .notiTokenReport: return QSLApi.noti_token_push
         }
     }
     
@@ -268,7 +288,32 @@ extension QSLNetworkAPI: TargetType {
             for (key, value) in Dict {
                 parameters[key] = value
             }
+        case .wakeupTrialList(dict: let dict):
+            for (key, value) in dict {
+                parameters[key] = value
+            }
+        case .wakeUpPressInfo(dict: let dict):
+            for (key, value) in dict {
+                parameters[key] = value
+            }
+        case .wakeUpPressCheck(dict: let dict):
+            for (key, value) in dict {
+                parameters[key] = value
+            }
+        case .confGlobal(dict: let dict):
+            for (key, value) in dict {
+                parameters[key] = value
+            }
+        case .userPhoneAttribution(dict: let dict):
+            for (key, value) in dict {
+                parameters[key] = value
+            }
+        case .notiTokenReport(dict: let dict):
+            for (key, value) in dict {
+                parameters[key] = value
+            }
         }
+
         debugPrint(parameters)
         return .requestParameters(parameters: parameters, encoding: JSONEncoding.default)
     }

Datei-Diff unterdrückt, da er zu groß ist
+ 13 - 31
QuickSearchLocation/Classes/Pages/QSLAdd/Controller/QSLAddController.swift


+ 1 - 1
QuickSearchLocation/Classes/Pages/QSLAlert/View/QSLFriendAddAlertView.swift

@@ -81,7 +81,7 @@ class QSLFriendAddAlertView: UIView {
         let label = UILabel()
         label.mediumFont(20)
         label.textColor = QSLColor.textColor_333
-        label.text = "查找好友"
+        label.text = QSLConfig.addFriendTitle
         return label
     }()
     

+ 21 - 13
QuickSearchLocation/Classes/Pages/QSLContact/Controller/QSLContactController.swift

@@ -169,22 +169,30 @@ extension QSLContactController {
     
     @objc func addBtnAction() {
         
-        if !QSLBaseManager.shared.isLogin() {
-            
-            if let view = self.tabBarController?.view {
+        if(!QSLConfig.loginPayEnable){
+            if !QSLBaseManager.shared.isVip() {
                 
-                QSLAlertView.alert(view: view, title: "温馨提示", content: "登录即可体验查看轨迹记录", secondBtnClosure:  {
-                    
-                    QSLJumpManager.shared.pushToLogin(type: .contact)
-                })
+                QSLJumpManager.shared.pushToVip(type: .homeRoad)
+                return
+            }
+        }else{
+            if !QSLBaseManager.shared.isLogin() {
+                
+                if let view = self.tabBarController?.view {
+                    QSLAlertView.alert(view: view, title: "温馨提示", content: "登录即可体验查看轨迹记录", secondBtnClosure:  {
+                        
+                        QSLJumpManager.shared.pushToLogin(type: .road)
+                    })
+                }
+                
+                return
             }
-            return
-        }
-        
-        if !QSLBaseManager.shared.isVip() {
             
-            QSLJumpManager.shared.pushToVip(type: .contact)
-            return
+            if !QSLBaseManager.shared.isVip() {
+                
+                QSLJumpManager.shared.pushToVip(type: .homeRoad)
+                return
+            }
         }
         
         QSLContactAddAlertView.alert(vc: self) { phone in

+ 1 - 1
QuickSearchLocation/Classes/Pages/QSLContact/View/QSLContactAddAlertView.swift

@@ -133,7 +133,7 @@ class QSLContactAddAlertView: UIView {
         QSEventHandle.eventPush(eventName: QSLGravityConst.contact_add)
         
         guard let text = self.phoneTextField.text, text.count == 11 else {
-            self.vc?.view.toast(text: "请输入正确的电话号码")
+            self.vc?.view.toast(text: "请输入正确的手机格式")
             return
         }
         

+ 30 - 14
QuickSearchLocation/Classes/Pages/QSLFriend/Controller/QSLFriendController.swift

@@ -67,7 +67,7 @@ class QSLFriendController: QSLBaseController {
         btn.addRadius(radius: 22.rpx)
         btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#15CBA1"), color2: .hexStringColor(hexString: "#1FE0BA"), width: QSLConst.qsl_kScreenW - 32.rpx, height: 44.rpx, direction: .horizontal)
         btn.image(UIImage(named: "home_friends_header_add_icon"))
-        btn.title("查找好友")
+        btn.title(QSLConfig.addFriendTitle)
         btn.mediumFont(16)
         btn.textColor(.white)
         btn.setImageTitleLayout(.imgLeft, spacing: 0)
@@ -118,6 +118,14 @@ extension QSLFriendController {
     }
     
     @objc func resortBtnAction() {
+        if !QSLBaseManager.shared.isLogin() {
+            QSQuickLogonHandle.share.currentVC = self
+            QSQuickLogonHandle.share.starOneQuickLogin(loginSuccess: {
+                
+            })
+            return;
+        }
+        
         QSEventHandle.eventPush(eventName: QSLGravityConst.contact_shortcut_send)
         QSLNetwork().request(.contactMaydayFavor(dict: [:])) { response in
             self.view.toast(text: "求助信息发送成功")
@@ -153,22 +161,30 @@ extension QSLFriendController: QSLFriendTableViewCellDelegate {
     
     func roadBtnClickAction(model: QSLUserModel) {
         
-        if !QSLBaseManager.shared.isLogin() {
-            
-            if let view = self.tabBarController?.view {
+        if(!QSLConfig.loginPayEnable){
+            if !QSLBaseManager.shared.isVip() {
                 
-                QSLAlertView.alert(view: view, title: "温馨提示", content: "登录即可体验查看轨迹记录", secondBtnClosure:  {
-                    
-                    QSLJumpManager.shared.pushToLogin(type: .road)
-                })
+                QSLJumpManager.shared.pushToVip(type: .homeRoad)
+                return
+            }
+        }else{
+            if !QSLBaseManager.shared.isLogin() {
+                
+                if let view = self.tabBarController?.view {
+                    QSLAlertView.alert(view: view, title: "温馨提示", content: "登录即可体验查看轨迹记录", secondBtnClosure:  {
+                        
+                        QSLJumpManager.shared.pushToLogin(type: .road)
+                    })
+                }
+                
+                return
             }
-            return
-        }
-        
-        if !QSLBaseManager.shared.isVip() {
             
-            QSLJumpManager.shared.pushToVip(type: .friendRoad)
-            return
+            if !QSLBaseManager.shared.isVip() {
+                
+                QSLJumpManager.shared.pushToVip(type: .homeRoad)
+                return
+            }
         }
         
         QSLJumpManager.shared.pushToRoad(type: .friend, model: model)

+ 261 - 0
QuickSearchLocation/Classes/Pages/QSLFriend/Controller/QSLSearchFriendVC.swift

@@ -0,0 +1,261 @@
+//
+//  QSLSearchFriendVC.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/23.
+//
+
+import UIKit
+import MAMapKit
+import Kingfisher
+import AMapSearchKit
+
+class QSLSearchFriendVC: QSLBaseController {
+    var searchPhone = ""
+    var isMove = false
+    var isLoading = false
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        self.setUI()
+    }
+    
+    func setUI(){
+        
+        setUpMap()
+
+        if(QSLConfig.phoneLocationEnable && searchPhone.count > 0){
+            startLoading()
+            QSLNetwork().request(.userPhoneAttribution(dict: ["phoneNumber":searchPhone])) { response in
+                let model = response.mapObject(QSLConfModel.self, modelKey: "data")
+                if(model.location.count > 0){
+                    var currentSearchKey = model.location
+                    
+                    if(model.location.contains("市") && model.location.contains("省")){
+                        let pattern = "省(.+?市)"
+                        if let regex = try? NSRegularExpression(pattern: pattern),
+                           let match = regex.firstMatch(in: currentSearchKey, range: NSRange(currentSearchKey.startIndex..., in: currentSearchKey)),
+                           let range = Range(match.range(at: 1), in: currentSearchKey) {
+                            currentSearchKey = String(currentSearchKey[range])
+                        }
+                        
+                    }
+                    self.requestAmapLocation(currentSearchKey)
+                    return
+                }
+                
+                self.startLocalMapAnimation()
+                
+            } fail: { code, msg in
+                self.startLocalMapAnimation()
+            }
+        } else{
+            startLocalMapAnimation()
+        }
+    }
+    
+    func requestAmapLocation(_ str : String){
+        let req = AMapDistrictSearchRequest.init()
+        req.keywords = str
+        req.requireExtension = true
+        self.mapSearch.aMapDistrictSearch(req)
+    }
+    
+    func startLocalMapAnimation(){
+        let randomCityCoordinate: (city: String, province: String, latitude: Double, longitude: Double) = [
+            ("北京市", "北京市", 39.90403, 116.40753),
+            ("上海市", "上海市", 31.23037, 121.47370),
+            ("广州市", "广东省", 23.12908, 113.26436),
+            ("武汉市", "湖北省", 30.59276, 114.30525),
+            ("成都市", "四川省", 30.65984, 104.06304),
+            ("西安市", "陕西省", 34.34127, 108.93984),
+            ("沈阳市", "辽宁省", 41.80570, 123.43147),
+            ("南京市", "江苏省", 32.05838, 118.79647),
+            ("郑州市", "河南省", 34.74661, 113.62533),
+            ("乌鲁木齐市", "新疆维吾尔自治区", 43.82559, 87.61688)
+        ].randomElement()!
+        
+        
+        startMapAnimation(longitude: randomCityCoordinate.longitude, latitude: randomCityCoordinate.latitude)
+        
+        startLoading()
+        
+    }
+    
+    func startLoading(){
+        if(!isLoading){
+            let bgView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: QSLConst.qsl_kScreenW, height: QSLConst.qsl_kScreenH))
+            self.view.addSubview(bgView)
+            bgView.backgroundColor = UIColor.init(white: 0, alpha: 0.45)
+            
+            self.loadingView = QSLLoadingView(frame: CGRect(x: 0, y: 0, width: 170.rpx, height: 170.rpx))
+            self.loadingView.center = view.center
+            self.view.addSubview(self.loadingView)
+            self.loadingView.completion = {
+                print("加载完成")
+            }
+            self.loadingView.progress = 0 // 设置进度
+
+            // 模拟进度更新
+            Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
+                self.loadingView.progress += 1
+                if self.loadingView.progress >= 100 {
+                    timer.invalidate()
+                }
+            }
+            
+            isLoading = true
+        }
+    }
+    
+    
+    func startMapAnimation(longitude:Double, latitude:Double){
+        isMove = true
+        
+        roadMapView.setZoomLevel(4, animated: true)
+
+        roadMapView.setCenter(CLLocationCoordinate2D(latitude: latitude, longitude: longitude), animated: true)
+        
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+            self.roadMapView.setZoomLevel(6, animated: true)
+            let randomProgress1 = CGFloat.random(in: 20...35)
+            if self.loadingView.progress < randomProgress1 {
+                self.loadingView.progress = randomProgress1
+            }
+        }
+
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+            self.roadMapView.setZoomLevel(7, animated: true)
+            let randomProgress2 = CGFloat.random(in: 45...70)
+            if self.loadingView.progress < randomProgress2 {
+                self.loadingView.progress = randomProgress2
+            }
+        }
+
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+            self.roadMapView.setZoomLevel(8, animated: true)
+            let randomProgress3 = CGFloat.random(in: 86...100)
+            if self.loadingView.progress < randomProgress3 {
+                self.loadingView.progress = randomProgress3
+            }
+        }
+
+        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
+            self.navigationController?.popViewController(animated: false)
+            QSLJumpManager.shared.pushToVip(type: QSLVipJumpType.add)
+        }
+    }
+    
+    // 初始化高德地图设置
+    func setUpMap() {
+        AMapServices.shared().enableHTTPS = true
+        self.initView()
+    }
+    
+    // 高德地图
+    lazy var roadMapView = {
+        
+        let _mapView = MAMapView()
+        _mapView.delegate = self
+        
+        _mapView.showsUserLocation = false
+        _mapView.isUserInteractionEnabled = false
+        _mapView.zoomLevel = 3;
+        
+        _mapView.isShowsBuildings = false
+        _mapView.showsCompass = false
+        _mapView.showsScale = false
+        _mapView.isRotateCameraEnabled = false
+        
+        _mapView.mapType = .satellite
+        //高德地图用的坐标帮我生成10个 分别是中国10个不同省份的省的市中心坐标
+        return _mapView
+    }()
+    
+    lazy var mapSearch: AMapSearchAPI = {
+        let item = AMapSearchAPI.init()
+        item?.delegate = self
+        return item!
+    }()
+    
+    lazy var loadingView: QSLLoadingView = {
+        let item = QSLLoadingView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
+        return item
+    }()
+
+}
+
+// MARK: - 设置地图相关方法
+extension QSLSearchFriendVC:MAMapViewDelegate {
+    
+    func mapView(_ mapView: MAMapView!, viewFor annotation: (any MAAnnotation)!) -> MAAnnotationView! {
+        
+        if annotation is MAPointAnnotation {
+            
+            let reuseIdentifier = "pointReuseIdentifier"
+            
+            // 尝试从缓存池中重用AnnotationView
+            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier) as? QSLHomeAnnotatinView
+            if annotationView == nil {
+                annotationView = QSLHomeAnnotatinView(annotation: annotation, reuseIdentifier: reuseIdentifier)
+                annotationView?.title = annotation.title
+            }
+            
+            // 设置AnnotationView属性
+            annotationView?.isEnabled = false
+            annotationView?.image = UIImage(named: annotation.subtitle ?? "")
+            
+            annotationView?.canShowCallout = false
+            
+            // 设置偏移量
+            annotationView?.centerOffset = CGPoint(x: 0, y: -18)
+            annotationView?.calloutOffset = CGPoint(x: 0, y: -5)
+            
+            // 判断标题是否是“终点”,决定是否选中
+            annotationView?.isSelected = true
+            
+            return annotationView
+        }
+        return nil
+    }
+    
+    func mapView(_ mapView: MAMapView!, didSingleTappedAt coordinate: CLLocationCoordinate2D) {
+        
+    }
+    
+}
+
+extension QSLSearchFriendVC : AMapSearchDelegate{
+    func onDistrictSearchDone(_ request: AMapDistrictSearchRequest!, response: AMapDistrictSearchResponse!) {
+        if(!isMove){
+            if(response.districts.count > 0){
+                let dist : AMapDistrict = response.districts[0] 
+                startMapAnimation(longitude: dist.center.longitude, latitude: dist.center.latitude)
+                
+            }else{
+                startLocalMapAnimation()
+            }
+        }
+    }
+    
+    func aMapSearchRequest(_ request: Any!, didFailWithError error: (any Error)!) {
+        if(!isMove){
+            startLocalMapAnimation()
+        }
+    }
+}
+
+extension QSLSearchFriendVC {
+    
+    func initView() {
+        
+        self.view.addSubview(roadMapView)
+        roadMapView.snp.makeConstraints { make in
+            make.top.right.left.equalTo(0)
+            make.edges.equalToSuperview()
+        }
+
+    }
+}
+

+ 170 - 66
QuickSearchLocation/Classes/Pages/QSLHome/Controller/QSLHomeController.swift

@@ -10,6 +10,7 @@ import SwiftyJSON
 import MAMapKit
 import AMapFoundationKit
 import AMapLocationKit
+import YYText
 
 class QSLHomeController: QSLBaseController {
     
@@ -22,58 +23,127 @@ class QSLHomeController: QSLBaseController {
     ///判断是不是第一次定位成功
     var isFirstLocatScuess : Bool = true
     
+    var isFirstRequestLoc : Bool = false
+    
+    var isEnterSearchFriend : Bool = false
+    
 //    var friendList: [QSLUserModel] = [QSLUserModel]()
     
     override func viewDidLoad() {
         
         super.viewDidLoad()
         
-        viewModel.initUIData()
-        setUpMap()
-        setUpUI()
-        
-        loadData()
+        checkDialog()
         
-        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLLogin, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLLogout, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLRefreshFriend, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLRefreshRequest, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(requestVip), name: QSLNotification.QSLRefreshMember, object: nil)
+        QSLTools.shared.requestShortcutItem()
+    }
+    
+    func checkDialog(){
+        if UserDefaults.standard.string(forKey: "FIRST_ENTER_LOCATION_HOMEPAGE") == nil{
+            isFirstRequestLoc = true
+        }
         
-        //处理第一次进入首页定位
-        firstEnterLocationHomepage()
+        dealWithMap();
+        QSLTools.shared.isOpen = true
         
+        if(QSLTools.shared.urlScheme.count > 0){
+            
+            if(isFirstRequestLoc){
+                isEnterSearchFriend = true
+            }
+            
+            QSLTools.shared.dealwithScheme(QSLTools.shared.urlScheme)
+            
+            return
+        }
+
+        //会员而且没有好友才弹出来
         if QSLBaseManager.shared.isVip() {
-            if let currentWindow = UIApplication.keyWindow {
-                QSLHomeAddFriendView.alert(view: currentWindow) {
-                    QSLJumpManager.shared.pushToAdd(type: .homealert)
+            QSLNetwork().request(.friendList(dict: [:])) { response in
+                let list = response.mapArray(QSLUserModel.self, modelKey: "data>list")
+                if(list.count == 0){
+                    self.showAddFriendView()
                 }
+            } fail: { code, error in
+  
             }
         }else{
             let vc = QSLActivityVipVC()
             vc.modalPresentationStyle = .fullScreen
             self.present(vc, animated: false)
             vc.dismissHandler = {[weak self] isCancel in
-                if(UserDefaults.standard.value(forKey: "QSLShowHomeReview") != nil){
-                    if let currentWindow = UIApplication.keyWindow {
-                        QSLHomeAddFriendView.alert(view: currentWindow) {
-                            QSLJumpManager.shared.pushToAdd(type: .homealert)
-                        }
-                    }
-                }else{
-                    UserDefaults.standard.setValue("1", forKey: "QSLShowHomeReview")
-                    QSLGuideusersToCommentManager.commentShare.noMemberPositiveReviewPopWindow {
-                        if let currentWindow = UIApplication.keyWindow {
-                            QSLHomeAddFriendView.alert(view: currentWindow) {
-                                QSLJumpManager.shared.pushToAdd(type: .homealert)
-                            }
+                
+                QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(.nonMember){[weak self] in
+                    self?.showAddFriendView(hideBtnClosure: {[weak self] in
+                        DispatchQueue.main.async {
+                            self?.checkLocAgain();
                         }
-                    }
+                    })
                 }
                 
             }
         }
         
+        
+        //试用过期弹窗
+//        QSLTrialExpireAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure:  { [weak self] in
+//            QSLCountdownManager.shared.selectGood = yearGood
+//            self?.unlockBtnAction()
+//            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_click, eventProps: ["button":"continue_payment"])
+//        },closeBtnClosure: {
+//            QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_retention_click, eventProps: ["button":"close"])
+//        })
+    }
+    
+    func checkLocAgain(){
+        homeMapLocationM.startUpdatingLocation()
+        
+        homeMapView.showsUserLocation = true
+        homeMapView.userTrackingMode = .follow
+        
+        self.onceLocation()
+        firstEnterLocationHomepage()
+
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        if(self.isFirstRequestLoc && self.isEnterSearchFriend){
+            self.isEnterSearchFriend = false
+            self.checkLocAgain();
+        }
+    }
+    
+    func showAddFriendView(hideBtnClosure: @escaping () -> () = {}){
+        if let currentWindow = UIApplication.keyWindow {
+            QSLHomeAddFriendView.alert(view: currentWindow, clickBtnClosure: {[weak self] in
+                QSLJumpManager.shared.pushToAdd(type: .homealert)
+                self?.isEnterSearchFriend = true
+            },hideBtnClosure:  {
+                hideBtnClosure()
+            })
+        }
+    }
+    
+    func dealWithMap(){
+        viewModel.initUIData()
+        setUpMap()
+        setUpUI()
+        
+        loadData()
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLLogin, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLLogout, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLRefreshFriend, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(loadData), name: QSLNotification.QSLRefreshRequest, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(requestVip), name: QSLNotification.QSLRefreshMember, object: nil)
+        
+        //处理第一次进入首页定位
+        if(isFirstRequestLoc){
+            return
+        }
+        
+        firstEnterLocationHomepage()
     }
     
     //处理第一次进入首页定位
@@ -101,9 +171,11 @@ class QSLHomeController: QSLBaseController {
         _mapView.showsScale = false
         _mapView.isRotateCameraEnabled = false
         
-        _mapView.showsUserLocation = true
-        _mapView.userTrackingMode = .follow
-        
+        if(!isFirstRequestLoc){
+            _mapView.showsUserLocation = true
+            _mapView.userTrackingMode = .follow
+        }
+
         // 关闭显示精度圈
         let represent = MAUserLocationRepresentation()
         represent.showsAccuracyRing = false
@@ -146,19 +218,37 @@ class QSLHomeController: QSLBaseController {
         QSLJumpManager.shared.pushToAdd(type: .homesmall)
     }
     
-    lazy var homeFriendBtn: UIButton = {
-        let _homeResortBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 56.rpx, height: 56.rpx))
-        _homeResortBtn.image(UIImage(named: "home_find_friend"))
-        _homeResortBtn.addTarget(self, action: #selector(homeFriendBtnAction), for: .touchUpInside)
+    lazy var homeFriendBtn: UIView = {
+        let _homeResortBtn = UIView(frame: CGRect(x: QSLConst.qsl_kScreenW - 40.rpx, y: QSLConst.qsl_kStatusBarFrameH + 28.rpx, width: 34.rpx, height: 44.rpx))
+        
+        let imgView = UIImageView.init(image: UIImage(named: "home_find_friend"))
+        imgView.frame = CGRectMake(0, 0, 34.rpx, 40.rpx)
+        _homeResortBtn.addSubview(imgView)
+        
+        let label = YYLabel.init(frame: CGRectMake(0, 29.rpx, 34.rpx, 15.rpx))
+        // 创建文字属性
+        let attributedString = NSMutableAttributedString(string: QSLConfig.addFriendIconText)
+        attributedString.yy_font = UIFont.boldSystemFont(ofSize: 13)
+        attributedString.yy_color = UIColor.black // 文字颜色为黑色
+        // 创建描边阴影(模拟边框效果)
+        let shadow = YYTextShadow()
+        shadow.color = UIColor.white // 边框颜色
+        shadow.radius = 4 // 边框粗细
+        shadow.offset = CGSize.zero // 偏移量为0,形成描边效果
+
+        // 设置文字描边
+        attributedString.yy_setTextShadow(shadow, range: NSRange(location: 0, length: attributedString.length))
+
+        label.attributedText = attributedString
+        label.textAlignment = .center
+        _homeResortBtn.addSubview(label)
+        
+        let tapG = UIGestureRecognizer.init(target: self, action: #selector(homeFriendBtnAction))
+        _homeResortBtn.addGestureRecognizer(tapG)
+        
         return _homeResortBtn
     }()
     
-//    lazy var homeButtonsView = {
-//        
-//        let _homeButtonsView = QSLHomeButtonView()
-//        return _homeButtonsView
-//    }()
-    
     /// 定位按钮
     lazy var homeLocateBtnView = {
         
@@ -207,7 +297,9 @@ extension QSLHomeController {
 //                make.top.equalTo(friViewTopY)
 //            }
 //        })
-        self.onceLocation()
+        if(!isFirstRequestLoc){
+            self.onceLocation()
+        }
         
         if QSLBaseManager.shared.isLogin() {
             self.initSocket()
@@ -229,7 +321,6 @@ extension QSLHomeController {
         viewModel.friendList.append(QSLBaseManager.shared.userModel)
         
         QSLNetwork().request(.friendList(dict: [:])) { response in
-            
             let list = response.mapArray(QSLUserModel.self, modelKey: "data>list")
             self.viewModel.friendList.append(contentsOf: list)
             self.homeFriendView.viewModel = self.viewModel
@@ -277,6 +368,7 @@ extension QSLHomeController {
             
             QSLBaseManager.shared.saveUserId(id: memberModel.userId)
             
+            QSLTools.shared.requestShortcutItem()
 //            NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
             
         } fail: { code, error in
@@ -295,8 +387,11 @@ extension QSLHomeController: MAMapViewDelegate, AMapLocationManagerDelegate {
         AMapLocationManager.updatePrivacyShow(.didShow, privacyInfo: .didContain)
         AMapLocationManager.updatePrivacyAgree(.didAgree)
         
+        
         homeMapLocationM.locatingWithReGeocode = true
-        homeMapLocationM.startUpdatingLocation()
+        if(!isFirstRequestLoc){
+            homeMapLocationM.startUpdatingLocation()
+        }
     }
     
     // 申请地图定位权限
@@ -546,6 +641,7 @@ extension QSLHomeController: MAMapViewDelegate, AMapLocationManagerDelegate {
           default:
               break
           }
+
       }
       
       // 系统定位权限变化回调
@@ -554,10 +650,16 @@ extension QSLHomeController: MAMapViewDelegate, AMapLocationManagerDelegate {
               let status = locationManager.authorizationStatus
               // 统一处理权限变化
               amapLocationManager(manager, didChangeAuthorization: status)
+              
+              if(status != .notDetermined){
+                  QSLTools.shared.requestNotificationPermission()
+              }
               //print("系统定位权限变化: \(status.rawValue)")
           } else {
               // Fallback on earlier versions
           }
+          
+          
       }
       
       // 定位结果回调
@@ -694,25 +796,32 @@ extension QSLHomeController: QSLHomeEmptyViewDelegate, QSLHomeFriendViewDelegate
     
     // 轨迹
     func routeBtnAction(model: QSLUserModel) {
-        
-        if !QSLBaseManager.shared.isLogin() {
-            
-            if let view = self.tabBarController?.view {
-                QSLAlertView.alert(view: view, title: "温馨提示", content: "登录即可体验查看轨迹记录", secondBtnClosure:  {
-                    
-                    QSLJumpManager.shared.pushToLogin(type: .road)
-                })
+        if(!QSLConfig.loginPayEnable){
+            if !QSLBaseManager.shared.isVip() {
+                
+                QSLJumpManager.shared.pushToVip(type: .homeRoad)
+                return
+            }
+        }else{
+            if !QSLBaseManager.shared.isLogin() {
+                
+                if let view = self.tabBarController?.view {
+                    QSLAlertView.alert(view: view, title: "温馨提示", content: "登录即可体验查看轨迹记录", secondBtnClosure:  {
+                        
+                        QSLJumpManager.shared.pushToLogin(type: .road)
+                    })
+                }
+                
+                return
             }
             
-            return
-        }
-        
-        if !QSLBaseManager.shared.isVip() {
-            
-            QSLJumpManager.shared.pushToVip(type: .homeRoad)
-            return
+            if !QSLBaseManager.shared.isVip() {
+                
+                QSLJumpManager.shared.pushToVip(type: .homeRoad)
+                return
+            }
         }
-        
+
         QSLJumpManager.shared.pushToRoad(type: .home, model: model)
     }
     
@@ -772,11 +881,6 @@ extension QSLHomeController {
         }
         
         view.addSubview(homeFriendBtn)
-        homeFriendBtn.snp.makeConstraints { make in
-            make.size.equalTo(CGSize(width: 56.rpx, height: 56.rpx))
-            make.top.equalTo(QSLConst.qsl_kStatusBarFrameH + 28.rpx)
-            make.right.equalTo(-2.rpx)
-        }
 //        
 //        view.addSubview(homeLocateBtnView)
 //        homeLocateBtnView.snp.makeConstraints { make in

+ 18 - 3
QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeAddFriendAlertView.swift

@@ -46,7 +46,7 @@ class QSLHomeAddFriendView: UIView {
       
         let btn = UIButton()
         btn.addRadius(radius: 22.rpx)
-        btn.title("查找好友")
+        btn.title(QSLConfig.addFriendTitle)
         btn.textColor(.white)
         btn.mediumFont(16)
         btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#15CBA1"), color2: .hexStringColor(hexString: "#1FE0BA"), width: 250.rpx, height: 44.rpx, direction: .horizontal)
@@ -64,13 +64,16 @@ class QSLHomeAddFriendView: UIView {
     }()
     
     var oneBtnClosure: (() -> ())?
+    var hideBtnClosure: (() -> ())?
     
     class func alert(view: UIView,
-                     clickBtnClosure: @escaping () -> () = {}) {
+                     clickBtnClosure: @escaping () -> () = {},
+                     hideBtnClosure: @escaping () -> () = {}) {
         
         let window = QSLHomeAddFriendView(frame: CGRect(x: 0, y: 0, width: QSLConst.qsl_kScreenW, height: QSLConst.qsl_kScreenH))
         view.addSubview(window)
         window.oneBtnClosure = clickBtnClosure
+        window.hideBtnClosure = hideBtnClosure
         
         UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) {
             window.backgroundColor = .hexStringColor(hexString: "#000000", alpha: 0.7)
@@ -94,7 +97,18 @@ class QSLHomeAddFriendView: UIView {
         if let oneBtnClosure = self.oneBtnClosure {
             oneBtnClosure()
         }
-        removeView()
+        removeView1()
+    }
+    
+    @objc func removeView1() {
+        
+        UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) { [weak self] in
+            self?.backgroundColor = UIColor.init(white: 0, alpha: 0)
+            self?.contentView.isHidden = true
+            self?.centerImage.isHidden = true
+        } completion: { [weak self] finished in
+            self?.removeFromSuperview()
+        }
     }
     
     // 移除
@@ -105,6 +119,7 @@ class QSLHomeAddFriendView: UIView {
             self?.contentView.isHidden = true
             self?.centerImage.isHidden = true
         } completion: { [weak self] finished in
+            self?.hideBtnClosure?()
             self?.removeFromSuperview()
         }
     }

+ 2 - 2
QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeEmptyView.swift

@@ -48,7 +48,7 @@ class QSLHomeEmptyView: UIView {
         let _emptyFriTitleLabel = UILabel()
         _emptyFriTitleLabel.boldFont(15)
         _emptyFriTitleLabel.textColor = QSLColor.textColor_333
-        _emptyFriTitleLabel.text = "查找好友"
+        _emptyFriTitleLabel.text = QSLConfig.addFriendTitle
         return _emptyFriTitleLabel
     }()
     
@@ -86,7 +86,7 @@ class QSLHomeEmptyView: UIView {
         let _emptyFriAddLabel = UILabel()
         _emptyFriAddLabel.mediumFont(14)
         _emptyFriAddLabel.textColor = QSLColor.textColor_333
-        _emptyFriAddLabel.text = "查找"
+        _emptyFriAddLabel.text = QSLConfig.addFriendBtn
         return _emptyFriAddLabel
     }()
     

+ 1 - 1
QuickSearchLocation/Classes/Pages/QSLHome/View/QSLHomeFriendFooterView.swift

@@ -37,7 +37,7 @@ class QSLHomeFriendFooterView: UIView {
         btn.addRadius(radius: 22.rpx)
         btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#15CBA1"), color2: .hexStringColor(hexString: "#1FE0BA"), width: 280.rpx, height: 44.rpx, direction: .horizontal)
         btn.image(UIImage(named: "home_friends_header_add_icon"))
-        btn.title("查找好友")
+        btn.title(QSLConfig.addFriendTitle)
         btn.mediumFont(15)
         btn.textColor(.white)
         btn.setImageTitleLayout(.imgLeft, spacing: 0)

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

@@ -142,7 +142,7 @@ class QSLHomeFriendView: UIView {
         let btn = UIButton()
         btn.setBackgroundImage(UIImage(named: "home_friends_header_add_btn_bg"), for: .normal)
         btn.image(UIImage(named: "home_friends_header_add_icon"))
-        btn.title("查找好友")
+        btn.title(QSLConfig.addFriendTitle)
         btn.mediumFont(15)
         btn.textColor(.white)
         btn.setImageTitleLayout(.imgLeft, spacing: 0)

+ 106 - 0
QuickSearchLocation/Classes/Pages/QSLMine/Controller/QSLFeedbackVC.swift

@@ -0,0 +1,106 @@
+//
+//  QSLFeedbackVC.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/23.
+//
+
+import UIKit
+import IQKeyboardManagerSwift
+
+class QSLFeedbackVC: QSLBaseController {
+    
+    override func viewWillAppear(_ animated:Bool) {
+        //super.viewWillAppear(animated)
+        self.navigationController?.setNavigationBarHidden(false, animated: animated)
+    }
+
+    override func viewDidLoad() {
+        self.title = "意见反馈"
+        super.viewDidLoad()
+        self.setUI()
+    }
+    
+    @objc func bottomButtonAction(){
+        if(self.phoneTextField.text?.count ?? 0 > 300){
+            QSLLoading.error(text: "字数超出300")
+            return
+        }
+        
+        if(self.phoneTextField.text?.count ?? 0 == 0){
+            QSLLoading.error(text: "请先输入内容")
+            return
+        }
+        QSLLoading.show()
+        DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
+            QSLLoading.success(text: "提交成功")
+        }
+    }
+    
+    func setUI(){
+        self.view.backgroundColor = .white
+        self.view.addSubview(titleLabel)
+        titleLabel.snp.makeConstraints { make in
+            make.left.equalTo(20.rpx)
+            make.top.equalTo(15.rpx)
+            make.right.equalTo(-20.rpx)
+            make.height.equalTo(20.rpx)
+        }
+        
+        self.view.addSubview(phoneTextField)
+        phoneTextField.snp.makeConstraints { make in
+            make.left.equalTo(20.rpx)
+            make.top.equalTo(titleLabel.snp.bottom).offset(15.rpx)
+            make.right.equalTo(-20.rpx)
+            make.height.equalTo(130.rpx)
+        }
+        
+        self.view.addSubview(bottomButton)
+        bottomButton.snp.makeConstraints { make in
+            make.left.equalTo(28.rpx)
+            make.right.equalTo(-28.rpx)
+            make.height.equalTo(44.rpx)
+            make.top.equalTo(phoneTextField.snp.bottom).offset(20.rpx)
+        }
+    }
+    
+    lazy var titleLabel: UILabel = {
+      
+        let label = UILabel()
+        label.text("意见或建议:")
+        label.mediumFont(16)
+        label.textColor = QSLColor.Color_202020
+        return label
+    }()
+    
+    lazy var phoneTextField: IQTextView = {
+       
+        let textField = IQTextView()
+        textField.backgroundColor = QSLColor.backGroundColor
+        textField.textColor = QSLColor.Color_202020
+        textField.font = UIFont.textF(14)
+
+        let subcribeText = NSMutableAttributedString(string: "请详细描述您的问题")
+        subcribeText.font(14)
+        subcribeText.color(QSLColor.Color_888)
+        textField.attributedPlaceholder = subcribeText
+        
+        return textField
+    }()
+    
+    lazy var bottomButton: UIButton = {
+        let btn = UIButton()
+        btn.addRadius(radius: 22.rpx)
+        btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#15CBA1"), color2: .hexStringColor(hexString: "#1FE0BA"), width: QSLConst.qsl_kScreenW - 32.rpx, height: 44.rpx, direction: .horizontal)
+        btn.title("提交")
+        btn.mediumFont(16)
+        btn.textColor(.white)
+        btn.setImageTitleLayout(.imgLeft, spacing: 0)
+        btn.addTarget(self, action: #selector(bottomButtonAction), for: .touchUpInside)
+        return btn
+    }()
+    
+    
+    
+
+}

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

@@ -160,6 +160,14 @@ extension QSLMineController: QSLMineFuncViewDelegate {
     }
     
     func jumpToContact() {
+        if !QSLBaseManager.shared.isLogin() {
+            QSQuickLogonHandle.share.currentVC = self
+            QSQuickLogonHandle.share.starOneQuickLogin(loginSuccess: {
+                
+            })
+            return;
+        }
+        
         QSEventHandle.eventPush( eventName: QSLGravityConst.mine_contact)
         QSLJumpManager.shared.pushToContact(type: .mine)
 //        let vc = QSLContactController()

+ 3 - 3
QuickSearchLocation/Classes/Pages/QSLMine/QSQuickLogon/QSQuickLogonHandle.swift

@@ -63,14 +63,14 @@ class QSQuickLogonHandle: NSObject {
         
         model.presentDirectionType = .push
         model.authWindowPop = .fullScreen
-        model.backgroundColor =  .hexStringColor(hexString: "#E2E2E2")
+        model.backgroundColor =  .white
 
         // 导航栏
         model.navBarHidden = false
-        model.navBgColor = .hexStringColor(hexString: "#E2E2E2")
+        model.navBgColor = .white
         model.navText = ""
         model.navTextFont = UIFont.systemFont(ofSize: 14)
-        model.navTextColor = .hexStringColor(hexString: "#E2E2E2")
+        model.navTextColor = .white
         model.navTextHidden = false
         if let image = UIImage(named: "public_back_btn") {
             model.navReturnImg = image

+ 3 - 2
QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLVipController.swift

@@ -16,6 +16,7 @@ enum QSLVipJumpType: Int {
     case contact     // 添加紧急联系人
     case mine        //
     case guideComments // 引导评论
+    case shortcut // 捷径
 }
 
 class QSLVipController: QSLBaseController {
@@ -490,7 +491,7 @@ class QSLVipController: QSLBaseController {
             case .mine:
                 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:
+            case .guideComments,.shortcut:
                 print("")
             }
         }
@@ -656,7 +657,7 @@ extension QSLVipController {
                             QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1004])
                         case .mine:
                             QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_success_page, eventProps: ["id": 1006])
-                        case .guideComments:
+                        case .guideComments,.shortcut:
                             print("")
                         }
                     }

+ 470 - 0
QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLVipTrialVC.swift

@@ -0,0 +1,470 @@
+//
+//  QSLVipTrialVC.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/23.
+//
+
+import UIKit
+import YYText
+
+enum QSLTrialVipJumpType: Int {
+    
+    case notiPush
+    case shortcut
+
+}
+
+class QSLVipTrialVC: QSLBaseController {
+
+    var type: QSLTrialVipJumpType?
+    var selectGood: QSLGoodModel?
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        setUI()
+        requestNetwork()
+    }
+    
+    func requestNetwork() {
+        // 网络请求时使用 itemListDict 作为参数(关键修复)
+        QSLNetwork().request(.wakeupTrialList(dict: [String: Any]())) {[weak self] response in
+            // 后续逻辑不变...
+            let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
+ 
+            if list.count > 0 {
+                self?.selectGood = list[0]
+                
+                self?.desLabel.text = self?.selectGood?.content ?? ""
+                
+                //初始化
+                if(QSLCountdownManager.shared.trialSeconds == -999){
+                    QSLCountdownManager.shared.trialSeconds = 900 * 1000
+                }
+                QSLCountdownManager.shared.updateTrialHandler = { [weak self] timeString in
+                    self?.countdownLabel.updateCountdownText(timeString)
+                }
+                QSLCountdownManager.shared.startCountdown()
+
+                NotificationCenter.default.post(
+                    name: Notification.Name("QSLHomeUpdateCouponViewNoti"),
+                    object: nil,
+                    userInfo: ["showCoupon": true, "couponType":"1"]
+                )
+            }
+        } fail: { code, error in
+            self.view.toast(text: "加载商品列表失败")
+        }
+    }
+    
+    // 恢复按钮点击
+    @objc func resumeBtnAction() {
+        
+        let memberModel = QSLBaseManager.shared.userModel.memberModel
+        let expired = memberModel.expired
+        if !expired {
+            QSLLoading.success(text: "您已经在订阅中,无需恢复")
+            return
+        }
+        
+        QSLLoading.show()
+        QSLVipManager.shared.restoreAction { isSuccess in
+            QSLVipManager.shared.isPaying = false
+            if isSuccess {
+                
+                QSLNetwork().request(.userMember(dict: [:])) { response in
+                    
+                    let model = response.mapObject(QSLMemberModel.self, modelKey: "data")
+                    QSLBaseManager.shared.userModel.memberModel = model
+                    
+                    if model.expired {
+                        QSLBaseManager.shared.saveVipExpiredTime(time: 0)
+                    } else {
+                        QSLBaseManager.shared.saveVipExpiredTime(time: model.endTimestamp)
+                    }
+                    
+                    QSLBaseManager.shared.saveUserId(id: model.userId)
+                    
+                    if model.endTimestamp > memberModel.endTimestamp {
+                        QSLLoading.success(text: "恢复成功")
+                        // 支付成功通知
+                        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
+                            self.navigationController?.popViewController(animated: true)
+                        }
+                    } else {
+                        QSLLoading.error(text: "没有可供恢复的订阅")
+                    }
+                    
+                } fail: { code, error in
+                    QSLLoading.error(text: "没有可供恢复的订阅")
+                }
+            } else {
+                QSLLoading.error(text: "没有可供恢复的订阅")
+            }
+        }
+    }
+    
+    @objc func payBtnAction(){
+        let memberModel = QSLBaseManager.shared.userModel.memberModel
+        
+        if let subscriptionExpired = memberModel.subscriptionExpired, !subscriptionExpired {
+            UIApplication.keyWindow?.toast(text: "你已经订阅了")
+            return
+        }
+        
+        guard let currentGood = selectGood else { return  }
+        
+        QSLLoading.show()
+        QSLVipManager.shared.startPay(goods: currentGood) { status, outTradeNo in
+            QSLVipManager.shared.isPaying = false
+            if status == .success {
+                QSLLoading.success(text: "支付成功")
+
+                // 引力传递支付事件
+                gravityInstance?.trackPayEvent(withAmount: Int32(currentGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: currentGood.name, withPayMethod: "apple")
+                
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(currentGood.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)
+                    
+                    if(!QSLBaseManager.shared.isLogin()){
+                        QSLJumpManager.shared.pushToLogin(type: .member)
+                    }
+                }
+                
+            
+            } else if status == .cancel {
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(currentGood.amount)])
+                QSLLoading.error(text: "支付取消")
+            } else if status == .fail {
+                QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(currentGood.amount)])
+                QSLLoading.error(text: "支付失败")
+            }
+        }
+    }
+    
+    @objc func privacyAction() {
+        
+        let vc = QSLWebViewController()
+        vc.webUrl = QSLConfig.AppPrivacyAgreementLink
+        vc.title = "隐私政策"
+        self.present(vc, animated: true)
+    }
+    
+    @objc func serviceAction() {
+        
+        let vc = QSLWebViewController()
+        vc.webUrl = QSLConfig.AppServiceAgreementLink
+        vc.title = "服务协议"
+        self.present(vc, animated: true)
+    }
+    
+    func setUI(){
+        
+        self.view.addSubview(bottomSpaceView)
+        bottomSpaceView.snp.makeConstraints { make in
+            make.left.right.bottom.equalTo(0)
+            make.height.equalTo(QSLConst.qsl_kTabbarBottom/2+1)
+        }
+
+        self.view.addSubview(bottomBgView)
+        bottomBgView.snp.makeConstraints { make in
+            make.left.right.equalTo(0)
+            make.bottom.equalTo(bottomSpaceView.snp.top).offset(0)
+            make.height.equalTo(QSLConst.qsl_kScreenW/1.4)
+        }
+        
+        self.view.addSubview(bgImageView)
+        bgImageView.snp.makeConstraints { make in
+            make.left.top.right.equalTo(0)
+            make.bottom.equalTo(bottomBgView.snp.top).offset(50.rpx)
+        }
+        
+        bgImageView.addSubview(bgTopTit1View)
+        bgTopTit1View.snp.makeConstraints { make in
+            make.centerX.equalTo(bgImageView.snp.centerX)
+            make.top.equalTo(QSLConst.qsl_kNavFrameH+20.rpx)
+        }
+        
+        bgImageView.addSubview(bgTopTit2View)
+        bgTopTit2View.snp.makeConstraints { make in
+            make.centerX.equalTo(bgImageView.snp.centerX)
+            make.top.equalTo(bgTopTit1View.snp.bottom).offset(1)
+        }
+        
+        bgImageView.addSubview(desLabel)
+        desLabel.snp.makeConstraints { make in
+            make.right.left.equalTo(0)
+            make.height.equalTo(17.rpx)
+            make.top.equalTo(bgTopTit2View.snp.bottom).offset(6.rpx)
+        }
+        
+        bgImageView.addSubview(bgCenterView)
+        bgCenterView.snp.makeConstraints { make in
+            make.centerX.equalTo(bgImageView.snp.centerX)
+            make.bottom.equalTo(0)
+        }
+        
+        self.view.addSubview(vipNaviView)
+        vipNaviView.snp.makeConstraints { make in
+            make.top.left.right.equalTo(0)
+            make.height.equalTo(QSLConst.qsl_kNavFrameH)
+        }
+        
+        vipNaviView.addSubview(backButton)
+        backButton.snp.makeConstraints { make in
+            make.width.equalTo(44.rpx)
+            make.height.equalTo(44.rpx)
+            make.left.equalTo(10.rpx)
+            make.top.equalTo(QSLConst.qsl_kStatusBarFrameH)
+        }
+        
+        vipNaviView.addSubview(naviTitleIcon)
+        naviTitleIcon.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.width.equalTo(100.rpx)
+            make.height.equalTo(20.rpx)
+            make.centerY.equalTo(backButton.snp.centerY)
+        }
+        
+        vipNaviView.addSubview(naviResumeBtn)
+        naviResumeBtn.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 70.rpx, height: 18.rpx))
+            make.right.equalTo(-8.rpx)
+            make.centerY.equalTo(backButton.snp.centerY)
+        }
+        
+        self.bottomBgView.addSubview(bottomTitleView)
+        bottomTitleView.snp.makeConstraints { make in
+            make.top.equalTo(50.rpx)
+            make.left.equalTo(32.rpx)
+            make.right.equalTo(-32.rpx)
+        }
+        
+        self.bottomBgView.addSubview(bottomBtnView)
+        bottomBtnView.snp.makeConstraints { make in
+            make.top.equalTo(bottomTitleView.snp.bottom).offset(20.rpx)
+            make.left.right.bottom.equalTo(0)
+        }
+        
+        bottomBtnView.addSubview(countdownView)
+        countdownView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.left.equalTo(12.rpx)
+            make.right.equalTo(-12.rpx)
+            make.height.equalTo(47.rpx)
+        }
+        
+        countdownView.addSubview(countdownLabel)
+        countdownLabel.snp.makeConstraints { make in
+            make.left.right.equalTo(0)
+            make.top.equalTo(5.rpx)
+            make.height.equalTo(17.rpx)
+        }
+        
+        bottomBtnView.addSubview(unlockBtn)
+        unlockBtn.snp.makeConstraints { make in
+            make.left.equalTo(12.rpx)
+            make.right.equalTo(-12.rpx)
+            make.height.equalTo(50.rpx)
+            make.top.equalTo(25.rpx)
+        }
+        
+        bottomBtnView.addSubview(serviceLabel)
+        serviceLabel.snp.makeConstraints { make in
+            make.right.left.equalTo(0)
+            make.height.equalTo(17.rpx)
+            make.top.equalTo(unlockBtn.snp.bottom).offset(8.rpx)
+        }
+        
+        updateServiceLabelText()
+        
+        self.view.bringSubviewToFront(bottomBgView)
+    }
+    
+    // 更新服务条款文本内容
+    func updateServiceLabelText() {
+        let attr = NSMutableAttributedString()
+        
+        // 固定部分:购买即同意
+        let firstAttr = NSMutableAttributedString(string: "购买前请先阅读")
+        firstAttr.font(11)
+        firstAttr.color(UIColor.init(white: 0, alpha: 0.4))
+        attr.append(firstAttr)
+        
+        // 《隐私权政策》
+        let privacyHL = YYTextHighlight()
+        let privacyStr = "隐私政策"
+        let privacyText = NSMutableAttributedString(string: privacyStr)
+        privacyText.font(11)
+        privacyText.color(UIColor.init(white: 0, alpha: 0.7))
+        privacyText.yy_setTextHighlight(privacyHL, range: NSRange(location: 0, length: privacyStr.count))
+        privacyHL.tapAction = { [weak self] containerView, text, range, rect in
+            self?.privacyAction()
+        }
+        let underline1 = YYTextDecoration(style: .single, width: 1, color: UIColor(white: 0, alpha: 0.7))
+        privacyText.yy_textUnderline = underline1
+
+        attr.append(privacyText)
+        
+        let blankAttr = NSMutableAttributedString(string: "&")
+        blankAttr.color(UIColor.init(white: 0, alpha: 0.4))
+        blankAttr.font(11)
+        attr.append(blankAttr)
+        
+        // 《用户协议》
+        let serviceHL = YYTextHighlight()
+        let serviceStr = "服务条款"
+        let serviceText = NSMutableAttributedString(string: serviceStr)
+        serviceText.font(11)
+        serviceText.color(UIColor.init(white: 0, alpha: 0.7))
+        serviceText.yy_setTextHighlight(serviceHL, range: NSRange(location: 0, length: serviceStr.count))
+        serviceHL.tapAction = { [weak self] containerView, text, range, rect in
+            self?.serviceAction()
+        }
+        let underline = YYTextDecoration(style: .single, width: 1, color: UIColor(white: 0, alpha: 0.7))
+        serviceText.yy_textUnderline = underline
+
+        attr.append(serviceText)
+
+        serviceLabel.attributedText = attr
+        serviceLabel.textAlignment = .center
+    }
+    
+    lazy var vipNaviView: UIView = {
+        let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW, QSLConst.qsl_kScreenH))
+        view.addCorner(conrners: [.topLeft,.topRight], radius: 12.rpx)
+        view.backgroundColor = UIColor.clear
+        return view
+    }()
+    
+    lazy var naviTitleIcon: UILabel = {
+        let label = UILabel()
+        label.text("超值福利")
+        label.textColor = .white
+        label.mediumFont(17)
+        label.textAlignment = .center
+        return label
+    }()
+    
+    lazy var naviResumeBtn: UIButton = {
+        let button = UIButton()
+        button.title("恢复订阅")
+        button.setTitleColor(.white, for: .normal)
+        button.titleLabel?.font = UIFont.systemFont(ofSize: 11, weight: .medium)
+        button.image(UIImage(named: "vip_resume_btn")?.withTintColor(UIColor.white))
+        button.setImageTitleLayout(.imgLeft, spacing: 2.rpx)
+        button.addTarget(self, action: #selector(resumeBtnAction), for: .touchUpInside)
+        return button
+    }()
+    
+    lazy var backButton: UIButton = {
+        let button = UIButton()
+        button.image(UIImage(named: "vip_pay_failure_close"))
+        button.addTarget(self, action: #selector(backBtnAction), for: .touchUpInside)
+        return button
+    }()
+    
+    lazy var bgImageView: UIImageView = {
+        let item = UIImageView()
+        item.contentMode = .scaleAspectFill
+        item.image = UIImage(named: "vip_trial_top")
+        item.layer.masksToBounds = true
+        return item
+    }()
+    
+    lazy var bgTopTit1View: UIImageView = {
+        let item = UIImageView()
+        item.contentMode = .scaleAspectFit
+        item.image = UIImage(named: "vip_trial_top_title_1")
+        item.layer.masksToBounds = true
+        return item
+    }()
+    
+    lazy var bgTopTit2View: UIImageView = {
+        let item = UIImageView()
+        item.contentMode = .scaleAspectFit
+        item.image = UIImage(named: "vip_trial_top_title_2")
+        item.layer.masksToBounds = true
+        return item
+    }()
+    
+    lazy var bgCenterView: UIImageView = {
+        let item = UIImageView()
+        item.contentMode = .scaleAspectFit
+        item.image = UIImage(named: "vip_trial_center")
+        item.layer.masksToBounds = true
+        return item
+    }()
+    
+    lazy var bottomSpaceView: UIView = {
+        let item = UIView()
+        item.backgroundColor = .white
+        return item
+    }()
+    
+    lazy var bottomBgView: UIImageView = {
+        let item = UIImageView()
+        item.contentMode = .scaleAspectFill
+        item.image = UIImage(named: "vip_trial_bottom_bg")
+        item.layer.masksToBounds = true
+        return item
+    }()
+    
+    lazy var bottomTitleView: UIImageView = {
+        let item = UIImageView()
+        item.image = UIImage(named: "vip_trial_bottom_title")
+        return item
+    }()
+    
+    lazy var bottomBtnView: UIView = {
+        let item = UIView()
+        return item
+    }()
+    
+    lazy var bottomView: UIView = {
+        let view = UIView()
+        view.backgroundColor = UIColor.white
+        return view
+    }()
+    
+    lazy var countdownView: UIView = {
+        let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW - 24.rpx, 47.rpx))
+        view.addCorner(conrners: [.topLeft,.topRight], radius: 30.rpx)
+        view.backgroundColor = .hexStringColor(hexString: "#FFFED8")
+        return view
+    }()
+    
+    lazy var countdownLabel: QSLCountdownView = {
+        let label = QSLCountdownView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW - 24.rpx, 17.rpx),type: 2)
+        return label
+    }()
+    
+    lazy var unlockBtn: UIButton = {
+        let btn = UIButton()
+        btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#0E5E61"), color2: .hexStringColor(hexString: "#00434E"), width: QSLConst.qsl_kScreenW - 24.rpx, height: 50.rpx, direction: .horizontal)
+        btn.addRadius(radius: 25.rpx)
+        btn.title("立即领取")
+        btn.textColor(.hexStringColor(hexString: "#FFF8EF"))
+        btn.mediumFont(18)
+        btn.addTarget(self, action: #selector(payBtnAction), for: .touchUpInside)
+        return btn
+    }()
+    
+    lazy var serviceLabel: YYLabel = {
+        let label = YYLabel()
+        label.textAlignment = .center
+        return label
+    }()
+
+    lazy var desLabel: YYLabel = {
+        let label = YYLabel()
+        label.textAlignment = .center
+        label.textColor = UIColor.init(white: 1, alpha: 0.4)
+        label.font = UIFont.systemFont(ofSize: 12)
+        return label
+    }()
+}

+ 179 - 103
QuickSearchLocation/Classes/Pages/QSLVip/QSLVipManager.swift

@@ -52,10 +52,80 @@ class QSLVipManager: NSObject {
 
 extension QSLVipManager {
     
-//    func check() {
-//        print("检查自动续费订单")
-//        self.isCheck = true
-//    }
+    //判断是否可以享受优惠
+    func checkCanPay(appleId: String, completion: @escaping (Bool) -> Void) {
+        if #available(iOS 15.0, *) {
+            Task {
+                await self.checkiOS15CanPlay(appleId: appleId, completion: completion)
+            }
+            return
+        }else{
+            completion(false)
+        }
+    }
+    
+    @available(iOS 15.0, *)
+    private func checkiOS15CanPlay(appleId: String, completion: @escaping (Bool) -> Void) async {
+        do {
+            // 获取产品信息
+            let products = try await Product.products(for: [appleId])
+            guard let product = products.first else {
+                completion(false);
+                return
+            }
+               
+            var isEligible = true
+            if let subscription = product.subscription {
+                isEligible = await subscription.isEligibleForIntroOffer
+            }
+
+            completion(isEligible);
+            return
+        } catch {
+            completion(false);
+            return
+        }
+    }
+
+    //判断是否是试用商品
+    func check(appleId: String, completion: @escaping (Bool) -> Void) {
+        if #available(iOS 15.0, *) {
+            Task {
+                await self.checkiOS15(appleId: appleId, completion: completion)
+            }
+            return
+        }else{
+            completion(false)
+        }
+    }
+    
+    @available(iOS 15.0, *)
+    private func checkiOS15(appleId: String, completion: @escaping (Bool) -> Void) async {
+        do {
+            // 获取产品信息
+            let products = try await Product.products(for: [appleId])
+            guard let product = products.first else {
+                completion(false);
+                return
+            }
+                
+            if let subscriptionInfo = product.subscription {
+                if(subscriptionInfo.introductoryOffer == nil){
+                    completion(false);
+                    return
+                }else{
+                    completion(true);
+                    return
+                }
+            }
+
+            completion(false);
+            return
+        } catch {
+            completion(false);
+            return
+        }
+    }
     
     // 开始支付
     func startPay(goods: QSLGoodModel, complete: payComplete?) {
@@ -76,7 +146,13 @@ extension QSLVipManager {
         selectGoods = goods
         payCompleteCloure = complete
         
-        self.requestOrderPay()
+        check(appleId: goods.appleGoodsId) { isTrial in
+            var isNeedReportEvent = false
+            if(isTrial){
+                isNeedReportEvent = true
+            }
+            self.requestOrderPay(isNeedReportEvent)
+        }
     }
     
     // 应用启动后检查未支付完成的订单
@@ -133,140 +209,137 @@ extension QSLVipManager {
     @available(iOS 15.0, tvOS 15.0, *)
     func checkHistoryAction(complete1: ((Bool, [String:Any]) -> Void)?) {
        
-        if #available(iOS 13.0, *) {
+        if #available(iOS 15.0, *) {
             Task{
                 var inSubscribeAppleGoodId = ""
                 var inSubscribeAppAccountToken = ""
 
-
-                if #available(iOS 15.0, *) {
-                    var activeTransactions: [String: StoreKit.Transaction] = [:]  // groupID → transaction
-                    var allActiveProductIDs: [String] = []  // 所有有效的商品ID
-                    var pendingDowngradeProductID: String? = nil
+                var activeTransactions: [String: StoreKit.Transaction] = [:]  // groupID → transaction
+                var allActiveProductIDs: [String] = []  // 所有有效的商品ID
+                var pendingDowngradeProductID: String? = nil
 
 
-                    // 首先检查未完成的交易,获取降级后的商品ID
-                    for await result in Transaction.unfinished {
-                        guard case .verified(let transaction) = result,
-                            transaction.productType == .autoRenewable
-                        else {
-                            continue
-                        }
+                // 首先检查未完成的交易,获取降级后的商品ID
+                for await result in Transaction.unfinished {
+                    guard case .verified(let transaction) = result,
+                        transaction.productType == .autoRenewable
+                    else {
+                        continue
+                    }
 
 
-                        // 检查这个未完成的交易是否是降级交易
-                        if let product = try? await Product.products(for: [transaction.productID]).first {
+                    // 检查这个未完成的交易是否是降级交易
+                    if let product = try? await Product.products(for: [transaction.productID]).first {
 
-                            // 如果未完成的交易购买时间比当前有效订阅晚,很可能是降级
-                            let purchaseDate = transaction.purchaseDate
+                        // 如果未完成的交易购买时间比当前有效订阅晚,很可能是降级
+                        let purchaseDate = transaction.purchaseDate
 
 
-                            // 检查当前有效订阅来判断是否为降级
-                            for await currentResult in Transaction.currentEntitlements {
-                                guard case .verified(let currentTransaction) = currentResult,
-                                    currentTransaction.productType == .autoRenewable
-                                else {
-                                    continue
-                                }
+                        // 检查当前有效订阅来判断是否为降级
+                        for await currentResult in Transaction.currentEntitlements {
+                            guard case .verified(let currentTransaction) = currentResult,
+                                currentTransaction.productType == .autoRenewable
+                            else {
+                                continue
+                            }
 
 
-                                // 如果未完成交易的购买时间晚于当前交易,且产品不同,则可能是降级
-                                if purchaseDate > currentTransaction.purchaseDate
-                                    && transaction.productID != currentTransaction.productID
-                                {
-                                    pendingDowngradeProductID = transaction.productID
-                                    break
-                                }
+                            // 如果未完成交易的购买时间晚于当前交易,且产品不同,则可能是降级
+                            if purchaseDate > currentTransaction.purchaseDate
+                                && transaction.productID != currentTransaction.productID
+                            {
+                                pendingDowngradeProductID = transaction.productID
+                                break
                             }
                         }
                     }
+                }
 
 
-                    // 然后检查当前有效的订阅
-                    for await result in Transaction.currentEntitlements {
-                        guard case .verified(let transaction) = result,
-                            transaction.productType == .autoRenewable
-                        else {
-                            continue
-                        }
+                // 然后检查当前有效的订阅
+                for await result in Transaction.currentEntitlements {
+                    guard case .verified(let transaction) = result,
+                        transaction.productType == .autoRenewable
+                    else {
+                        continue
+                    }
 
 
-                        // 跳过过期或撤销的
-                        if let expirationDate = transaction.expirationDate,
-                            expirationDate < Date()
-                        {
-                            continue
-                        }
-                        if transaction.revocationDate != nil {
-                            continue
-                        }
+                    // 跳过过期或撤销的
+                    if let expirationDate = transaction.expirationDate,
+                        expirationDate < Date()
+                    {
+                        continue
+                    }
+                    if transaction.revocationDate != nil {
+                        continue
+                    }
 
 
-                        // 添加到所有有效商品ID列表
-                        allActiveProductIDs.append(transaction.productID)
+                    // 添加到所有有效商品ID列表
+                    allActiveProductIDs.append(transaction.productID)
 
-                        // 获取订阅组 ID 和产品信息
-                        guard let product = try? await Product.products(for: [transaction.productID]).first,
-                            let groupID = product.subscription?.subscriptionGroupID
-                        else {
-                            continue
-                        }
+                    // 获取订阅组 ID 和产品信息
+                    guard let product = try? await Product.products(for: [transaction.productID]).first,
+                        let groupID = product.subscription?.subscriptionGroupID
+                    else {
+                        continue
+                    }
 
 
-                        // 如果还没找到降级商品,继续通过订阅状态检查
-                        if pendingDowngradeProductID == nil {
-                            do {
-                                let statuses = try await product.subscription?.status ?? []
-                                for status in statuses {
-                                    switch status.state {
-                                    case .subscribed:
-                                        // 检查是否有pending的降级
-                                        if case .verified(let renewalInfo) = status.renewalInfo,
-                                            let autoRenewProductID = renewalInfo.autoRenewPreference,
-                                            autoRenewProductID != transaction.productID
-                                        {
-                                            pendingDowngradeProductID = autoRenewProductID
-                                        }
-                                    default:
-                                        break
+                    // 如果还没找到降级商品,继续通过订阅状态检查
+                    if pendingDowngradeProductID == nil {
+                        do {
+                            let statuses = try await product.subscription?.status ?? []
+                            for status in statuses {
+                                switch status.state {
+                                case .subscribed:
+                                    // 检查是否有pending的降级
+                                    if case .verified(let renewalInfo) = status.renewalInfo,
+                                        let autoRenewProductID = renewalInfo.autoRenewPreference,
+                                        autoRenewProductID != transaction.productID
+                                    {
+                                        pendingDowngradeProductID = autoRenewProductID
                                     }
+                                default:
+                                    break
                                 }
-                            } catch {
-                                print("检查订阅状态失败: \(error)")
                             }
+                        } catch {
+                            print("检查订阅状态失败: \(error)")
                         }
+                    }
 
 
-                        // 每个订阅组只保留最新的
-                        if let current = activeTransactions[groupID] {
-                            if transaction.purchaseDate > current.purchaseDate {
-                                activeTransactions[groupID] = transaction
-                            }
-                        } else {
+                    // 每个订阅组只保留最新的
+                    if let current = activeTransactions[groupID] {
+                        if transaction.purchaseDate > current.purchaseDate {
                             activeTransactions[groupID] = transaction
                         }
+                    } else {
+                        activeTransactions[groupID] = transaction
                     }
+                }
 
-                    // 优先使用通过未完成交易或renewalInfo找到的降级商品ID
-                    if let pendingProductID = pendingDowngradeProductID {
-                        inSubscribeAppleGoodId = pendingProductID
-                        // 对于pending的订阅,我们无法获取appAccountToken,使用当前订阅的
-                        if let transaction = activeTransactions.values.first {
-                            inSubscribeAppAccountToken = transaction.appAccountToken?.uuidString ?? ""
-                        }
-                    } else if let transaction = activeTransactions.values.first {
-                        // 如果有多个订阅组,这里可能需要根据业务逻辑选择合适的订阅
-                        inSubscribeAppleGoodId = transaction.productID
+                // 优先使用通过未完成交易或renewalInfo找到的降级商品ID
+                if let pendingProductID = pendingDowngradeProductID {
+                    inSubscribeAppleGoodId = pendingProductID
+                    // 对于pending的订阅,我们无法获取appAccountToken,使用当前订阅的
+                    if let transaction = activeTransactions.values.first {
                         inSubscribeAppAccountToken = transaction.appAccountToken?.uuidString ?? ""
-
-                        // 如果有多个订阅,打印警告
-                        if activeTransactions.count > 1 {
-                            print("⚠️ 检测到多个订阅组的订阅,当前使用第一个: \(transaction.productID)")
-                            print("所有订阅组的商品ID: \(activeTransactions.values.map { $0.productID })")
-                        }
-                    } else {
-                        print("无当前有效订阅")
                     }
+                } else if let transaction = activeTransactions.values.first {
+                    // 如果有多个订阅组,这里可能需要根据业务逻辑选择合适的订阅
+                    inSubscribeAppleGoodId = transaction.productID
+                    inSubscribeAppAccountToken = transaction.appAccountToken?.uuidString ?? ""
+
+                    // 如果有多个订阅,打印警告
+                    if activeTransactions.count > 1 {
+                        print("⚠️ 检测到多个订阅组的订阅,当前使用第一个: \(transaction.productID)")
+                        print("所有订阅组的商品ID: \(activeTransactions.values.map { $0.productID })")
+                    }
+                } else {
+                    print("无当前有效订阅")
                 }
             
                 if(inSubscribeAppleGoodId.count == 0 || inSubscribeAppAccountToken.count == 0){
@@ -288,12 +361,15 @@ extension QSLVipManager {
 extension QSLVipManager {
     
     // 发起支付请求
-    func requestOrderPay() {
+    func requestOrderPay(_ isNeedReportEvent: Bool = false) {
         
         var dict = [String: Any]()
         dict["itemId"] = self.selectGoods?.goodId
         dict["payPlatform"] = 2
         dict["payMethod"] = 3
+        if(isNeedReportEvent){
+            dict["needReportEvent"] = true
+        }
         
         QSLNetwork().request(.vipOrderSubmitAndPay(dict: dict)) { response in
             self.orderModel = response.mapObject(QSLOrderModel.self, modelKey: "data")

+ 223 - 0
QuickSearchLocation/Classes/Pages/QSLVip/View/QSLTrialExpireAlertView.swift

@@ -0,0 +1,223 @@
+//
+//  QSLTrialExpireAlertView.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/10/23.
+//
+
+import UIKit
+
+class QSLTrialExpireAlertView: UIView {
+        
+    lazy var contentView: UIView = {
+        
+        let contentViewW = QSLConst.qsl_kScreenW - 60.rpx
+        let contentViewH =  152.0.rpx
+        let contentView = UIView(frame: CGRect(x: 0, y: 0, width: contentViewW, height: contentViewH))
+        contentView.backgroundColor = .clear
+        return contentView
+    }()
+    
+    
+    lazy var closeButton: UIButton = {
+        let btn = UIButton()
+        btn.setBackgroundImage(UIImage(named: "vip_pay_failure_close"), for: .normal)
+        btn.addTarget(self, action: #selector(closeBtnAction), for: .touchUpInside)
+        return btn
+    }()
+
+    lazy var popBgImageView : UIImageView = {
+        let popBgImageView = UIImageView()
+        popBgImageView.contentMode = .scaleAspectFit
+        popBgImageView.image = UIImage(named: "vip_pay_failure_back_ground")
+        return popBgImageView
+    }()
+    
+
+    ///中间描述区域
+    lazy var middleView : UIView = {
+        let middleView = UIView()
+        middleView.backgroundColor = .clear
+        return middleView
+    }()
+    
+    lazy var oneButton: UIButton = {
+      
+        let btn = UIButton()
+        btn.addRadius(radius: 20.rpx)
+        btn.title("去登录")
+        btn.textColor(.white)
+        btn.mediumFont(14)
+        btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#7F5737"), color2: .hexStringColor(hexString: "#562B0E"), width: 200.rpx, height: 40.rpx, direction: .horizontal)
+        btn.addTarget(self, action: #selector(oneBtnAction), for: .touchUpInside)
+        return btn
+    }()
+    
+    lazy var firstButton: UIButton = {
+        
+        let btn = UIButton()
+        btn.isHidden = true
+        btn.backgroundColor = .hexStringColor(hexString: "#F8F8F8")
+        btn.addRadius(radius: 20.rpx)
+        btn.title("取消")
+        btn.textColor(.hexStringColor(hexString: "#A7A7A7"))
+        btn.mediumFont(16)
+        btn.addTarget(self, action: #selector(firstBtnAction), for: .touchUpInside)
+        return btn
+    }()
+    
+    lazy var secondButton: UIButton = {
+        
+        let btn = UIButton()
+        btn.isHidden = true
+        btn.addRadius(radius: 20.rpx)
+        btn.title("确认")
+        btn.textColor(.white)
+        btn.mediumFont(16)
+        btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#15CBA1"), color2: .hexStringColor(hexString: "#1FE0BA"), width: 118.rpx, height: 40.rpx, direction: .horizontal)
+        btn.addTarget(self, action: #selector(secondBtnAction), for: .touchUpInside)
+        return btn
+    }()
+    
+
+    var oneBtnClosure: (() -> ())?
+    
+    var firstBtnClosure: (() -> ())?
+    
+    var secondBtnClosure: (() -> ())?
+    
+    var closeBtnClosure: (() -> ())?
+    
+    
+    class func alert(view: UIView,
+                     isOneBtn: Bool = false,
+                     oneBtnText: String = "去登录",
+                     oneBtnClosure: @escaping () -> () = {},
+                     firstBtnClosure: @escaping () -> () = {},
+                     secondBtnClosure: @escaping () -> () = {},
+                     closeBtnClosure: @escaping () -> () = {}) {
+        
+        let window = QSLRetainPopUpAlertView(frame: CGRect(x: 0, y: 0, width: QSLConst.qsl_kScreenW, height: QSLConst.qsl_kScreenH))
+
+        window.oneButton.title(oneBtnText)
+        window.oneButton.isHidden = !isOneBtn
+        window.firstButton.isHidden = isOneBtn
+        window.secondButton.isHidden = isOneBtn
+        window.oneBtnClosure = oneBtnClosure
+        window.firstBtnClosure = firstBtnClosure
+        window.secondBtnClosure = secondBtnClosure
+        window.closeBtnClosure = closeBtnClosure
+        
+        window.contentView.snp.remakeConstraints { make in
+            make.size.equalTo(CGSize(width: QSLConst.qsl_kScreenW - 60.rpx, height: 310.rpx))
+            make.center.equalToSuperview()
+        }
+        view.addSubview(window)
+        
+        UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) {
+            window.backgroundColor = .hexStringColor(hexString: "#000000", alpha: 0.7)
+            window.contentView.isHidden = false
+        }
+    }
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        
+        initView()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    
+    // 单按钮点击事件
+    @objc func oneBtnAction() {
+        if let oneBtnClosure = self.oneBtnClosure {
+            oneBtnClosure()
+        }
+        removeView()
+    }
+    
+    // 取消按钮点击事件
+    @objc func firstBtnAction() {
+        if let firstBtnClosure = self.firstBtnClosure {
+            firstBtnClosure()
+        }
+        removeView()
+    }
+    
+    // 确认按钮点击事件
+    @objc func secondBtnAction() {
+        if let secondBtnClosure = self.secondBtnClosure {
+            secondBtnClosure()
+        }
+        removeView()
+    }
+    
+    // 关闭按钮点击事件
+    @objc func closeBtnAction() {
+        if let closeBtnClosure = self.closeBtnClosure {
+            closeBtnClosure()
+        }
+        removeView()
+    }
+    
+    // 移除
+    @objc func removeView() {
+        
+        UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.95, initialSpringVelocity: 0.05) { [weak self] in
+            self?.backgroundColor = UIColor.init(white: 0, alpha: 0)
+            self?.contentView.isHidden = true
+            self?.closeButton.isHidden = true
+        } completion: { [weak self] finished in
+            self?.removeFromSuperview()
+        }
+    }
+}
+
+extension QSLTrialExpireAlertView {
+    
+    func initView() {
+        
+        addSubview(contentView)
+        contentView.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: QSLConst.qsl_kScreenW - 60.rpx, height: 152.0.rpx))
+            make.center.equalToSuperview()
+        }
+        
+        addSubview(closeButton)
+        closeButton.snp.makeConstraints { make in
+            make.bottom.equalTo(contentView.snp.top).offset(30.hpx)
+            make.right.equalTo(contentView.snp.right).offset(-10.rpx)
+            make.size.equalTo(CGSizeMake(24.rpx, 24.rpx))
+        }
+        
+        contentView.addSubview(popBgImageView)
+        popBgImageView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        contentView.addSubview(oneButton)
+        oneButton.snp.makeConstraints { make in
+            //make.top.equalTo(contentLabel.snp.bottom).offset(24.5.rpx)
+            make.size.equalTo(CGSize(width: 150.rpx, height: 40.rpx))
+            make.centerX.equalToSuperview()
+            make.bottom.equalTo(-38.rpx)
+        }
+        
+        contentView.addSubview(firstButton)
+        firstButton.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 118.rpx, height: 40.rpx))
+            make.left.equalTo(24.rpx)
+            make.bottom.equalTo(-24.rpx)
+        }
+        
+        contentView.addSubview(secondButton)
+        secondButton.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 118.rpx, height: 40.rpx))
+            make.right.equalTo(-24.rpx)
+            make.bottom.equalTo(-24.rpx)
+        }
+    }
+}

+ 1 - 2
QuickSearchLocation/Info.plist

@@ -2,8 +2,6 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
-	<key>NSLocationWhenInUseUsageDescription</key>
-	<string>手机关爱定位为了使用定位轨迹功能需要您同意开启持续定位权限</string>
 	<key>ITSAppUsesNonExemptEncryption</key>
 	<false/>
 	<key>NSAppTransportSecurity</key>
@@ -33,6 +31,7 @@
 	<key>UIBackgroundModes</key>
 	<array>
 		<string>location</string>
+		<string>remote-notification</string>
 	</array>
 </dict>
 </plist>

+ 22 - 2
QuickSearchLocation/Macro/QSLApi.swift

@@ -13,10 +13,10 @@ enum QSLEnvironment: Int {
 
 struct QSLApi {
     
-    static let environment = QSLEnvironment.prod
+    static let environment = QSLEnvironment.local
     
     // 本地
-    static let LocalUrl = "http://wjj.dy.takin.cc"
+    static let LocalUrl = "https://ws00.by.takin.cc"
     
     // 测试
     static let devUrl = ""
@@ -112,6 +112,12 @@ extension QSLApi {
     
     // 一键登录
     static let login_oneclick = "/s/v1/user/login/oneclick"
+    
+    // 手机归属地
+    static let user_phone_attr = "/s/v1/user/phone/attribution"
+    
+    //上报推送信息
+    static let noti_token_push = "/s/v1/notification/report"
 }
 
 // 好友模块
@@ -227,4 +233,18 @@ extension QSLApi {
     
     // 客户端上报设备信息
     static let device_info_upload = "/s/v1/client/device/info/upload"
+    
+    // 全局配置
+    static let conf_global = "/s/v1/conf/global"
+    
+}
+
+extension QSLApi {
+    
+    // 试用商品列表
+    static let wakeup_trial_list = "/s/v1/item/trial/list"
+    // 试用长按显示信息
+    static let wakeup_press_info = "/s/v1/user/wakeUp/press/info"
+    // 试用长按跳转
+    static let wakeup_press_check = "/s/v1/user/wakeUp/press/check"
 }

+ 51 - 0
QuickSearchLocation/Macro/QSLConfig.swift

@@ -35,3 +35,54 @@ extension QSLConfig {
     // 购买人数
     static let quick_logon_key_id = "dc38d3518af74a75b41c345d869fa57d"
 }
+
+//好友查找文案 好友按钮文案 当前用户类型 当前app状态
+extension QSLConfig {
+    
+    //手机归属地
+    static var phoneLocationEnable: Bool {
+        return QSLCacheManager.getConfModel()?.phoneLocationEnable ?? false
+    }
+    
+    //购买流程
+    static var loginPayEnable: Bool {
+        return QSLCacheManager.getConfModel()?.loginPayEnable ?? true
+    }
+    
+    static var addFriendTitle: String {
+        return QSLCacheManager.getConfModel()?.searchFriendContent ?? "查找好友"
+    }
+    
+    static var addFriendBtn: String {
+        let text = QSLCacheManager.getConfModel()?.searchFriendContent ?? "查找好友"
+        if(text.contains("好友")){
+            return text.replacingOccurrences(of: "好友", with: "")
+        }else{
+            return "查找"
+        }
+    }
+    
+    static var addFriendIconText: String {
+        let text = QSLCacheManager.getConfModel()?.searchFriendContent ?? "查找好友"
+        if(text.contains("查")){
+            return "查TA"
+        }else if(text.contains("加")){
+            return "加TA"
+        }else{
+            return "找TA"
+        }
+    }
+    
+    static var addFriendTips: String {
+        if((UserDefaults.standard.value(forKey: "LocAddFriendTips")) != nil){
+            if let status =  UserDefaults.standard.value(forKey: "LocAddFriendTips") as? String{
+                return status
+            }else{
+                return ""
+            }
+        }else{
+            return ""
+        }
+    }
+    
+}

+ 8 - 0
QuickSearchLocation/QuickSearchLocationDebug.entitlements

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>aps-environment</key>
+	<string>development</string>
+</dict>
+</plist>

+ 8 - 0
QuickSearchLocation/QuickSearchLocationRelease.entitlements

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>aps-environment</key>
+	<string>development</string>
+</dict>
+</plist>

+ 2 - 2
QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/Contents.json

@@ -5,12 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "找TA.png",
+      "filename" : "Group 43677.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "找TA (1).png",
+      "filename" : "Group 43677 (1).png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/Group 43677 (1).png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/Group 43677.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/找TA (1).png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Home/home_find_friend.imageset/找TA.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Mine/.DS_Store


+ 22 - 0
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_func_gift.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "fuliquan.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "fuliquan-2.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_func_gift.imageset/fuliquan-2.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_func_gift.imageset/fuliquan.png


+ 6 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_bg.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "vip_trial_bottom_bg.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 43369.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_bg.imageset/Group 43369.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_bg.imageset/vip_trial_bottom_bg.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_title.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "vip_trial_bottom_title.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_bottom_title.imageset/vip_trial_bottom_title.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_center.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "图标.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_center.imageset/图标.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Mask group.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top.imageset/Mask group.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_1.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "精准定位.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_1.imageset/精准定位.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_2.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "精准共享 实时当前位置.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/trial/vip_trial_top_title_2.imageset/精准共享 实时当前位置.png


+ 1 - 0
QuickSearchLocation/Tools/QSLDeviceTool.swift

@@ -24,6 +24,7 @@ class QSLDeviceTool: NSObject {
     
     private let configQueue = DispatchQueue(label: "com.qsl.deviceTool.config")
     public var enableAutoRefresh: Bool = true {
+        
         didSet {
             configQueue.async {
                 if self.enableAutoRefresh {