소스 검색

[new] 会员引导页

zhujieshan 2 달 전
부모
커밋
97db2bfe5a
37개의 변경된 파일1962개의 추가작업 그리고 11개의 파일을 삭제
  1. BIN
      .DS_Store
  2. 13 1
      QuickSearchLocation.xcodeproj/project.pbxproj
  3. 2 2
      QuickSearchLocation/Base.lproj/LaunchScreen.storyboard
  4. 7 0
      QuickSearchLocation/Classes/Network/QSLNetwork.swift
  5. 0 0
      QuickSearchLocation/Classes/Pages/QSLFriend/View/QSLAddFriendSuccessAlertView.swift
  6. 8 5
      QuickSearchLocation/Classes/Pages/QSLHome/Controller/QSLHomeController.swift
  7. 377 0
      QuickSearchLocation/Classes/Pages/QSLVip/Cell/QSLActivityVipCell.swift
  8. 1 0
      QuickSearchLocation/Classes/Pages/QSLVip/Cell/QSLVipGoodCollectionViewCell.swift
  9. 898 0
      QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLActivityVipController.swift
  10. 477 0
      QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLActivityVipVC.swift
  11. 2 0
      QuickSearchLocation/Macro/QSLApi.swift
  12. 1 1
      QuickSearchLocation/Resources/Assets.xcassets/Launch/launch_icon.imageset/Contents.json
  13. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Launch/launch_icon.imageset/Group 42959 2.png
  14. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Launch/launch_icon.imageset/launch_icon@3x.png
  15. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/.DS_Store
  16. 1 2
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/Contents.json
  17. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/Group 42959 1.png
  18. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/mine_about_logo@2x.png
  19. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/mine_about_logo@3x.png
  20. 6 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/Contents.json
  21. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_1.imageset/Contents.json
  22. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_1.imageset/Group 40471 1.png
  23. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_2.imageset/Contents.json
  24. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_2.imageset/Group 40471 3 (1).png
  25. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_3.imageset/Contents.json
  26. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_3.imageset/Group 40471 2.png
  27. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_s.imageset/Contents.json
  28. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_s.imageset/Group 40405.png
  29. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_uns.imageset/Contents.json
  30. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_uns.imageset/Group 42961.png
  31. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_bg.imageset/Contents.json
  32. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_bg.imageset/Mask group.png
  33. 22 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_diamond.imageset/Contents.json
  34. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_diamond.imageset/Subtract-1.png
  35. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_diamond.imageset/Subtract.png
  36. 21 0
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_title.imageset/Contents.json
  37. BIN
      QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_title.imageset/文字.png

BIN
.DS_Store


+ 13 - 1
QuickSearchLocation.xcodeproj/project.pbxproj

@@ -121,6 +121,9 @@
 		FE9139C92DE6B018001A8E42 /* QSLVipMostGoodCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE9139C82DE6B018001A8E42 /* QSLVipMostGoodCell.swift */; };
 		FE94B4F42D23F09100D2B001 /* LoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE94B4F32D23F09100D2B001 /* LoadingViewController.swift */; };
 		FEC010E72D9E8B06008B8B0A /* QSLSubscriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC010E62D9E8AFE008B8B0A /* QSLSubscriptionModel.swift */; };
+		FEC3D9542E8274CF007164A9 /* QSLActivityVipController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC3D9532E8274CF007164A9 /* QSLActivityVipController.swift */; };
+		FEC3D9562E8276CB007164A9 /* QSLActivityVipVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC3D9552E8276CB007164A9 /* QSLActivityVipVC.swift */; };
+		FEC3D9582E82973C007164A9 /* QSLActivityVipCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEC3D9572E82973C007164A9 /* QSLActivityVipCell.swift */; };
 		FED298C42E37267100F1E0F0 /* QSLVipAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED298C32E37267100F1E0F0 /* QSLVipAlertView.swift */; };
 		FED298C62E38AB5500F1E0F0 /* QSLVipResultsAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED298C52E38AB5500F1E0F0 /* QSLVipResultsAlertView.swift */; };
 		FED298C82E38B51400F1E0F0 /* QSLVipResultsNoMemberAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED298C72E38B51400F1E0F0 /* QSLVipResultsNoMemberAlertView.swift */; };
@@ -257,6 +260,9 @@
 		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>"; };
 		FEC010E62D9E8AFE008B8B0A /* QSLSubscriptionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLSubscriptionModel.swift; sourceTree = "<group>"; };
+		FEC3D9532E8274CF007164A9 /* QSLActivityVipController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLActivityVipController.swift; sourceTree = "<group>"; };
+		FEC3D9552E8276CB007164A9 /* QSLActivityVipVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLActivityVipVC.swift; sourceTree = "<group>"; };
+		FEC3D9572E82973C007164A9 /* QSLActivityVipCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLActivityVipCell.swift; sourceTree = "<group>"; };
 		FED298C32E37267100F1E0F0 /* QSLVipAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLVipAlertView.swift; sourceTree = "<group>"; };
 		FED298C52E38AB5500F1E0F0 /* QSLVipResultsAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLVipResultsAlertView.swift; sourceTree = "<group>"; };
 		FED298C72E38B51400F1E0F0 /* QSLVipResultsNoMemberAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QSLVipResultsNoMemberAlertView.swift; sourceTree = "<group>"; };
@@ -310,7 +316,6 @@
 				04B666CA2BC922120020BFBD /* QSLHomeFriendView.swift */,
 				FE8360B62D02F7A600978E03 /* QSLHomeAnnotatinView.swift */,
 				FE8360B82D02F9B500978E03 /* QSLHomeCallOutView.swift */,
-				FEF9D30D2E824870001F4660 /* QSLAddFriendSuccessAlertView.swift */,
 				FEF9D30F2E82521D001F4660 /* QSLHomeAddFriendAlertView.swift */,
 			);
 			path = View;
@@ -723,6 +728,7 @@
 		FE83606D2CF5CFF400978E03 /* View */ = {
 			isa = PBXGroup;
 			children = (
+				FEF9D30D2E824870001F4660 /* QSLAddFriendSuccessAlertView.swift */,
 				FE8360B02D01BFE500978E03 /* QSLFriendRemarkAlertView.swift */,
 			);
 			path = View;
@@ -792,6 +798,8 @@
 			isa = PBXGroup;
 			children = (
 				FE8360802CF723FA00978E03 /* QSLVipController.swift */,
+				FEC3D9552E8276CB007164A9 /* QSLActivityVipVC.swift */,
+				FEC3D9532E8274CF007164A9 /* QSLActivityVipController.swift */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -813,6 +821,7 @@
 				FE8360832CF8450C00978E03 /* QSLVipGoodCollectionViewCell.swift */,
 				FE8360852CF86E2800978E03 /* QSLVipCommentCellView.swift */,
 				FE9139C82DE6B018001A8E42 /* QSLVipMostGoodCell.swift */,
+				FEC3D9572E82973C007164A9 /* QSLActivityVipCell.swift */,
 			);
 			path = Cell;
 			sourceTree = "<group>";
@@ -1054,6 +1063,7 @@
 				FE638AA02D082FC400858121 /* QSLLoading.swift in Sources */,
 				FED298DD2E3C682600F1E0F0 /* QSLRetainPopUpAlertView.swift in Sources */,
 				FE638ADA2D23E31B00858121 /* PhotoClassifier.swift in Sources */,
+				FEC3D9582E82973C007164A9 /* QSLActivityVipCell.swift in Sources */,
 				04B6B5262BCE196000777EB4 /* QSLMineFuncView.swift in Sources */,
 				FE8360692CF5B06700978E03 /* QSLLoginViewController.swift in Sources */,
 				FE5B42442CF485B9000AACCB /* QSLHomeFriendFooterView.swift in Sources */,
@@ -1100,11 +1110,13 @@
 				FE9139C92DE6B018001A8E42 /* QSLVipMostGoodCell.swift in Sources */,
 				FE638AA92D09858C00858121 /* QSLContactController.swift in Sources */,
 				04B6B52D2BCE2C9200777EB4 /* QSLMineViewModel.swift in Sources */,
+				FEC3D9542E8274CF007164A9 /* QSLActivityVipController.swift in Sources */,
 				04B666CB2BC922120020BFBD /* QSLHomeFriendView.swift in Sources */,
 				FE638AAE2D099B0F00858121 /* QSLContactCell.swift in Sources */,
 				04B666C32BC7E3760020BFBD /* CAGradientLayer+Extension.swift in Sources */,
 				04B666C72BC8D7F30020BFBD /* QSLFriendAddAlertView.swift in Sources */,
 				FE83606B2CF5C73F00978E03 /* NSMutableAttributedString+Extension.swift in Sources */,
+				FEC3D9562E8276CB007164A9 /* QSLActivityVipVC.swift in Sources */,
 				04F33BE72BC69318003E2111 /* QSLHomeController.swift in Sources */,
 				FED298D22E3B0EDD00F1E0F0 /* QSLGuideusersToCommentManager.swift in Sources */,
 				04F33BD52BC67CEB003E2111 /* Bundle+Extension.swift in Sources */,

+ 2 - 2
QuickSearchLocation/Base.lproj/LaunchScreen.storyboard

@@ -20,7 +20,7 @@
                                 <rect key="frame" x="0.0" y="721" width="393" height="131"/>
                             </imageView>
                             <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_icon" translatesAutoresizingMaskIntoConstraints="NO" id="KRc-qV-WiP">
-                                <rect key="frame" x="156.66666666666666" y="189" width="80" height="80"/>
+                                <rect key="frame" x="148.66666666666666" y="189" width="96" height="96"/>
                             </imageView>
                             <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_title" translatesAutoresizingMaskIntoConstraints="NO" id="qVj-8G-b1M">
                                 <rect key="frame" x="96" y="715.33333333333337" width="201" height="62.666666666666629"/>
@@ -50,7 +50,7 @@
     </scenes>
     <resources>
         <image name="launch_bottom_bg" width="360" height="131"/>
-        <image name="launch_icon" width="80" height="80"/>
+        <image name="launch_icon" width="96" height="96"/>
         <image name="launch_title" width="167" height="52"/>
     </resources>
 </document>

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

@@ -38,6 +38,7 @@ enum QSLNetworkAPI {
     case friendGet(dict: [String: Any])
     case locationTrackQuery(dict: [String: Any])
     case vipItemList(dict: [String: Any])
+    case vipActivityItemList(dict: [String: Any])
     case vipOrderSubmitAndPay(dict: [String: Any])
     case vipOrderPayStatus(dict: [String: Any])
     case vipMemberResume(dict: [String: Any])
@@ -86,6 +87,7 @@ extension QSLNetworkAPI: TargetType {
         case .friendGet: return QSLApi.friend_get
         case .locationTrackQuery: return QSLApi.location_track_query
         case .vipItemList: return QSLApi.vip_item_list
+        case .vipActivityItemList: return QSLApi.vip_activity_item_list
         case .vipOrderSubmitAndPay: return QSLApi.vip_order_submitAndPay
         case .vipOrderPayStatus: return QSLApi.vip_order_payStatus
         case .vipMemberResume: return QSLApi.vip_subscription_resume
@@ -189,6 +191,11 @@ extension QSLNetworkAPI: TargetType {
                 parameters[key] = value
             }
             break
+        case let .vipActivityItemList(Dict):
+            for (key, value) in Dict {
+                parameters[key] = value
+            }
+            break
         case let .vipOrderSubmitAndPay(Dict):
             for (key, value) in Dict {
                 parameters[key] = value

QuickSearchLocation/Classes/Pages/QSLHome/View/QSLAddFriendSuccessAlertView.swift → QuickSearchLocation/Classes/Pages/QSLFriend/View/QSLAddFriendSuccessAlertView.swift


+ 8 - 5
QuickSearchLocation/Classes/Pages/QSLHome/Controller/QSLHomeController.swift

@@ -43,11 +43,14 @@ class QSLHomeController: QSLBaseController {
         //处理第一次进入首页定位
         firstEnterLocationHomepage()
         
-        if let currentWindow = UIApplication.keyWindow {
-            QSLHomeAddFriendView.alert(view: currentWindow) {
-                QSLJumpManager.shared.pushToAdd(type: .homealert)
-            }
-        }
+//        if let currentWindow = UIApplication.keyWindow {
+//            QSLHomeAddFriendView.alert(view: currentWindow) {
+//                QSLJumpManager.shared.pushToAdd(type: .homealert)
+//            }
+//        }
+        
+        let vc = QSLActivityVipVC()
+        self.rootViewController()?.pushVC(vc: vc)
         
     }
     

+ 377 - 0
QuickSearchLocation/Classes/Pages/QSLVip/Cell/QSLActivityVipCell.swift

@@ -0,0 +1,377 @@
+//
+//  QSLActivityVipCell.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/9/23.
+//
+
+import UIKit
+
+class QSLActivityVipCell: UICollectionViewCell {
+    
+    struct UX {
+        static let topMainViewWidth = (QSLConst.qsl_kScreenW - 32.0.rpx)
+        static let topMainViewHeight = 112.0.rpx
+        static let smallMainViewWidth = (QSLConst.qsl_kScreenW-50.rpx)/2.0
+        static let smallMainViewHeight = 112.0.rpx
+        static let bigMainViewWidth = (QSLConst.qsl_kScreenW - 32.0.rpx)
+        static let bigMainViewHeight = 72.0.rpx
+    }
+    
+    var type: GoodCellType = .small {
+        didSet {
+            self.updateUI()
+        }
+    }
+    
+    var goodModel: QSLGoodModel?
+    
+    lazy var bgView: UIImageView = {
+       
+        let view = UIImageView()
+        return view
+    }()
+    
+    lazy var mainView: UIView = {
+       
+        let view = UIView(frame: CGRect(x: 0, y: 0, width: UX.smallMainViewWidth, height: UX.smallMainViewHeight))
+        view.addFourCorner(topLeft: 11, topRight: 11, bottomLeft: 0, bottomRight: 0)
+        view.backgroundColor = .white
+        return view
+    }()
+
+    lazy var goodNameLabel: UILabel = {
+        
+        let label = UILabel()
+        label.text("年度会员")
+        label.boldFont(16)
+        label.textColor = .hexStringColor(hexString: "#333333")
+        return label
+    }()
+    
+    lazy var priceLabel: UILabel = {
+       
+        let label = UILabel()
+        label.textAlignment = .center
+        label.text("¥128")
+        label.mediumFont(24)
+        label.textColor = .hexStringColor(hexString: "#404040")
+        label.setSpecificTextColorFont("¥", color: .hexStringColor(hexString: "#404040"), font: UIFont.systemFont(ofSize: 14, weight: .medium))
+        return label
+    }()
+    
+    lazy var originPriceLabel: UILabel = {
+        
+        let label = UILabel()
+        label.text("¥299")
+        label.font(13)
+        label.textAlignment = .center
+        label.textColor = .hexStringColor(hexString: "#96BEBA")
+        label.centerLineText(lineValue: 1, underlineColor: .hexStringColor(hexString: "#96BEBA"))
+        return label
+    }()
+    
+    lazy var goodDailyPriceLabel: UILabel = {
+        
+        let label = UILabel()
+        let text = "仅需¥9.2/天,时刻守护Ta的安全"
+        label.text(text)
+        label.font(9)
+        label.textColor = .hexStringColor(hexString: "#5EA69D")
+        label.setSpecificTextColorFont("¥", color: .hexStringColor(hexString: "#5EA69D"), font: UIFont.systemFont(ofSize: 9, weight: .heavy))
+        
+        if let yuanIndex = text.firstIndex(of: "¥") {
+            
+            // 获取文本最后一位的index
+            let lastIndex = text.index(before: text.endIndex)
+            
+            // 创建从¥后面一个字符到文本最后一位的range
+            let contentRange = text.index(after: yuanIndex)..<lastIndex
+            
+            // 将Swift的Range转换为NSRange
+            let nsRange = NSRange(
+                contentRange,
+                in: text
+            )
+            
+            label.setRangeFontText(font: UIFont.systemFont(ofSize: 12, weight: .heavy), range: nsRange)
+        }
+        
+        return label
+    }()
+    
+    lazy var selectBtn: UIButton = {
+      
+        let btn = UIButton()
+        btn.setBackgroundImage(UIImage(named: "vip_good_unselect_big"), for: .normal)
+        btn.setBackgroundImage(UIImage(named: "vip_good_select_big"), for: .selected)
+        return btn
+    }()
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        
+        initView()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    func config(model: QSLGoodModel, type: GoodCellType) {
+        
+        self.goodModel = model
+        self.type = type
+        
+        
+        let text = model.content
+        self.goodDailyPriceLabel.text = text
+        self.goodNameLabel.text = model.name
+        
+        if(type == .top){
+            self.bgView.layer.cornerRadius = 0
+            self.bgView.layer.masksToBounds = true
+            self.bgView.layer.borderWidth = 0
+            if model.isSelect {
+                self.bgView.image = UIImage(named: "vip_activity_item_s")
+            }else{
+                self.bgView.image = UIImage(named: "vip_activity_item_uns")
+            }
+            self.selectBtn.isHidden = true
+            self.priceLabel.textColor = .red
+            self.goodDailyPriceLabel.textColor = UIColor.hexStringColor(hexString: "#5EA69D")
+            self.originPriceLabel.textColor = UIColor.hexStringColor(hexString: "#96BEBA")
+            
+            return
+        }
+        
+        self.priceLabel.textColor = .hexStringColor(hexString: "#333333")
+        self.selectBtn.isHidden = false
+        self.selectBtn.isSelected = model.isSelect
+        self.bgView.image = UIImage.init()
+        
+        self.bgView.layer.cornerRadius = 14.rpx
+        self.bgView.layer.masksToBounds = true
+        self.bgView.layer.borderWidth = 2
+        self.goodDailyPriceLabel.textColor = UIColor.init(white: 0, alpha: 0.4)
+        self.originPriceLabel.textColor = UIColor.init(white: 0, alpha: 0.4)
+        
+        if model.isSelect {
+            self.bgView.layer.borderColor = UIColor.hexStringColor(hexString: "#003D46").cgColor
+            
+            if let yuanIndex = text.firstIndex(of: "¥") {
+                
+                // 获取文本最后一位的index
+                let lastIndex = text.index(before: text.endIndex)
+                
+                // 创建从¥后面一个字符到文本最后一位的range
+                let contentRange = text.index(after: yuanIndex)...lastIndex
+                
+                // 将Swift的Range转换为NSRange
+                let nsRange = NSRange(
+                    contentRange,
+                    in: text
+                )
+                
+                self.goodDailyPriceLabel.setRangeFontText(font: UIFont.systemFont(ofSize: 12, weight: .heavy), range: nsRange)
+            }
+            
+        } else {
+            self.bgView.layer.borderColor = UIColor.hexStringColor(hexString: "#DDDDDD").cgColor
+            
+            if let yuanIndex = text.firstIndex(of: "¥") {
+                
+                // 获取文本最后一位的index
+                let lastIndex = text.index(before: text.endIndex)
+                
+                // 创建从¥后面一个字符到文本最后一位的range
+                let contentRange = text.index(after: yuanIndex)...lastIndex
+                
+                // 将Swift的Range转换为NSRange
+                let nsRange = NSRange(
+                    contentRange,
+                    in: text
+                )
+                
+                self.goodDailyPriceLabel.setRangeFontText(font: UIFont.systemFont(ofSize: 12, weight: .heavy), range: nsRange)
+            }
+        }
+
+        var priceText = ""
+        if model.amount.truncatingRemainder(dividingBy: 100) == 0 {
+            priceText = "¥\(Int(model.amount / 100))"
+        } else {
+            priceText = String(format: "¥%.2lf", model.amount / 100 )
+        }
+        self.priceLabel.text = priceText
+        self.priceLabel.setSpecificTextColorFont("¥", color: .hexStringColor(hexString: "#404040"), font: UIFont.systemFont(ofSize: 14, weight: .medium))
+
+        var orinalPriceText = ""
+        if model.originalAmount.truncatingRemainder(dividingBy: 100) == 0 {
+            orinalPriceText = "¥\(Int(model.originalAmount / 100))"
+        } else {
+            orinalPriceText = String(format: "¥%.2lf", model.originalAmount / 100 )
+        }
+        self.originPriceLabel.text = orinalPriceText
+    }
+}
+
+extension QSLActivityVipCell {
+    
+    func updateUI() {
+        self.goodNameLabel.textAlignment = .left
+        self.priceLabel.textAlignment = .left
+        self.originPriceLabel.textAlignment = .left
+        self.goodDailyPriceLabel.textAlignment = .left
+        if self.type == .top {
+            self.mainView.backgroundColor = UIColor.init(white: 0, alpha: 0)
+            self.mainView.frame = CGRect(x: 0, y: 0, width: UX.topMainViewWidth, height: UX.topMainViewHeight)
+            
+            goodNameLabel.snp.remakeConstraints { make in
+                make.left.equalTo(89.rpx)
+                make.top.equalTo(48.rpx)
+                make.width.equalTo(100.rpx)
+                make.height.equalTo(22.rpx)
+            }
+            
+            priceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(16.rpx)
+                make.top.equalTo(48.rpx)
+                make.width.equalTo(80.rpx)
+                make.height.equalTo(22.rpx)
+            }
+            
+            originPriceLabel.snp.remakeConstraints { make in
+                make.width.equalTo(80.rpx)
+                make.height.equalTo(22.rpx)
+                make.left.equalTo(16.rpx)
+                make.top.equalTo(priceLabel.snp.bottom).offset(0.rpx)
+            }
+            
+            goodDailyPriceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(89.rpx)
+                make.top.equalTo(77.rpx)
+                make.right.equalTo(-10.rpx)
+                make.height.equalTo(12.rpx)
+            }
+            
+        } else if self.type == .big {
+            
+            self.mainView.backgroundColor = UIColor.white
+            self.mainView.frame = CGRect(x: 0, y: 0, width: UX.bigMainViewWidth, height: UX.bigMainViewHeight)
+            
+            goodNameLabel.snp.remakeConstraints { make in
+                make.left.equalTo(89.rpx)
+                make.top.equalTo(15.rpx)
+                make.width.equalTo(100.rpx)
+                make.height.equalTo(22.rpx)
+            }
+            
+            priceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(16.rpx)
+                make.top.equalTo(15.rpx)
+                make.width.equalTo(80.rpx)
+                make.height.equalTo(22.rpx)
+            }
+            
+            originPriceLabel.snp.remakeConstraints { make in
+                make.width.equalTo(80.rpx)
+                make.height.equalTo(22.rpx)
+                make.left.equalTo(16.rpx)
+                make.top.equalTo(priceLabel.snp.bottom).offset(0.rpx)
+            }
+            
+            goodDailyPriceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(89.rpx)
+                make.top.equalTo(goodNameLabel.snp.bottom).offset(2.rpx)
+                make.right.equalTo(-10.rpx)
+                make.height.equalTo(12.rpx)
+            }
+        } else {
+            self.goodNameLabel.textAlignment = .center
+            self.priceLabel.textAlignment = .center
+            self.originPriceLabel.textAlignment = .center
+            self.goodDailyPriceLabel.textAlignment = .center
+            self.mainView.backgroundColor = UIColor.white
+            self.mainView.frame = CGRect(x: 0, y: 0, width: UX.smallMainViewWidth, height: UX.smallMainViewHeight)
+            
+            goodNameLabel.snp.remakeConstraints { make in
+                make.left.equalTo(10.rpx)
+                make.right.equalTo(-10.rpx)
+                make.top.equalTo(10.rpx)
+                make.height.equalTo(14.rpx)
+            }
+            
+            priceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(10.rpx)
+                make.right.equalTo(-10.rpx)
+                make.top.equalTo(goodNameLabel.snp.bottom).offset(10.rpx)
+                make.height.equalTo(30.rpx)
+            }
+            
+            originPriceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(10.rpx)
+                make.right.equalTo(-10.rpx)
+                make.top.equalTo(priceLabel.snp.bottom).offset(0)
+                make.height.equalTo(15.rpx)
+            }
+            
+            goodDailyPriceLabel.snp.remakeConstraints { make in
+                make.left.equalTo(10.rpx)
+                make.right.equalTo(-10.rpx)
+                make.top.equalTo(originPriceLabel.snp.bottom).offset(8.rpx)
+                make.height.equalTo(15.rpx)
+            }
+        }
+       
+        self.mainView.addFourCorner(topLeft: 11, topRight: 11, bottomLeft: 0, bottomRight: 0)
+    }
+    
+    func initView() {
+        
+        self.contentView.addSubview(bgView)
+        bgView.snp.makeConstraints { make in
+            make.top.left.right.bottom.equalTo(0)
+        }
+        
+        self.bgView.addSubview(mainView)
+        mainView.snp.makeConstraints { make in
+            make.top.equalTo(2.rpx)
+            make.left.equalTo(2.rpx)
+            make.right.equalTo(-2)
+            make.height.equalTo(72.rpx)
+        }
+        
+        self.mainView.addSubview(goodNameLabel)
+        goodNameLabel.snp.makeConstraints { make in
+            make.left.equalTo(10.rpx)
+            make.top.equalTo(15.rpx)
+        }
+        
+        self.mainView.addSubview(priceLabel)
+        priceLabel.snp.makeConstraints { make in
+            make.top.equalTo(40.rpx)
+            make.left.equalTo(10.rpx)
+        }
+        
+        self.mainView.addSubview(originPriceLabel)
+        originPriceLabel.snp.makeConstraints { make in
+            make.left.equalTo(10.rpx)
+            make.top.equalTo(priceLabel.snp.bottom).offset(0.rpx)
+        }
+        
+        self.bgView.addSubview(selectBtn)
+        selectBtn.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 16.rpx, height: 16.rpx))
+            make.right.equalTo(-6.rpx)
+            make.bottom.equalTo(-6.rpx)
+        }
+        
+        self.bgView.addSubview(goodDailyPriceLabel)
+        goodDailyPriceLabel.snp.makeConstraints { make in
+            make.left.equalTo(10.rpx)
+            make.centerY.equalTo(selectBtn.snp.centerY)
+        }
+        
+    }
+}

+ 1 - 0
QuickSearchLocation/Classes/Pages/QSLVip/Cell/QSLVipGoodCollectionViewCell.swift

@@ -10,6 +10,7 @@ import UIKit
 enum GoodCellType {
     case big
     case small
+    case top
 }
 
 class QSLVipGoodCollectionViewCell: UICollectionViewCell {

+ 898 - 0
QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLActivityVipController.swift

@@ -0,0 +1,898 @@
+//
+//  QSLActivityVipController.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/9/23.
+//
+
+import UIKit
+
+class QSLActivityVipController: QSLBaseController {
+    
+    // 购买人数
+    static let record_non_member_clicks_to_claim = "RECORD_NON_MEMBER_CLIKS_CLAIM"
+    
+    struct UX {
+        static let mostCellHeight = 113.0.rpx
+        static let collectionRowHeight = 137.0.rpx
+        static let goodsBgHeight = 54.rpx + UX.mostCellHeight + 20.rpx
+    }
+    
+    var type: QSLVipJumpType?
+    
+    var goodList: [QSLGoodModel] = [QSLGoodModel]()
+    
+    ///是否是订阅的产品
+    //var is
+    
+    var selectGood: QSLGoodModel? {
+        didSet {
+            updateSelectGoodUI()
+        }
+    }
+    
+    lazy var vipBg: UIImageView = {
+       
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_bg")
+        return imageView
+    }()
+    
+    lazy var backButton: UIButton = {
+       
+        let button = UIButton()
+        button.image(UIImage(named: "public_back_btn_white"))
+        button.title("会员中心")
+        button.mediumFont(17)
+        button.textColor(.white)
+        button.setImageTitleLayout(.imgLeft, spacing: 4.rpx)
+        button.addTarget(self, action: #selector(backBtnAction), for: .touchUpInside)
+        return button
+    }()
+    
+    lazy var peopleCountView: UIView = {
+       
+        let view = UIView()
+        view.layer.cornerRadius = 12.rpx
+        view.layer.borderColor = UIColor.white.withAlphaComponent(0.16).cgColor
+        view.layer.borderWidth = 1.rpx
+        return view
+    }()
+    
+    lazy var peopleAvatarImageView: UIImageView = {
+       
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_avatars_icon")
+        return imageView
+    }()
+    
+    lazy var peopleCountLabel: UILabel = {
+       
+        let label = UILabel()
+        label.text("1456488人 已开通VIP")
+        label.color("#FFE6C0")
+        label.font(12)
+        return label
+    }()
+    
+    lazy var scrollView: UIScrollView = {
+       
+        let scrollView = UIScrollView()
+//        scrollView.delegate = self
+        scrollView.bounces = false
+        scrollView.showsVerticalScrollIndicator = false
+        scrollView.contentInsetAdjustmentBehavior = .never
+        return scrollView
+    }()
+    
+    lazy var cardBannerImageView: UIImageView = {
+       
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_banner_card")
+        return imageView
+    }()
+    
+    lazy var vipTimeLabel: UILabel = {
+       
+        let label = UILabel()
+        label.text("升级VIP会员,解锁全部功能")
+        label.font(13)
+        label.textColor = .hexStringColor(hexString: "#AF7655")
+        return label
+    }()
+    
+    lazy var funcBannerImageView: UIImageView = {
+       
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_banner_func")
+        return imageView
+    }()
+    
+    lazy var mainView: UIView = {
+       
+        let view = UIView()
+        view.backgroundColor = QSLColor.backGroundColor
+        view.addRadius(radius: 12.rpx)
+        return view
+    }()
+    
+    lazy var goodsBgView: UIView = {
+       
+        let view = UIView()
+        view.gradientBackgroundColor(color1: .hexStringColor(hexString: "#FFF8F2"), color2: .hexStringColor(hexString: "#FFFFFF"), width: QSLConst.qsl_kScreenW, height: UX.goodsBgHeight, direction: .vertical)
+        return view
+    }()
+    
+    lazy var vipGoodsTitleIcon: UIImageView = {
+       
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_title_icon")
+        return imageView
+    }()
+    
+    lazy var resumeBtn: UIButton = {
+       
+        let button = UIButton()
+        button.title("恢复购买")
+        button.setTitleColor(.hexStringColor(hexString: "#000000").withAlphaComponent(0.5), for: .normal)
+        button.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .medium)
+        button.image(UIImage(named: "vip_resume_btn"))
+        button.setImageTitleLayout(.imgLeft, spacing: 2.rpx)
+        button.addTarget(self, action: #selector(resumeBtnAction), for: .touchUpInside)
+        return button
+    }()
+    
+    lazy var mostCell: QSLVipMostGoodCell = {
+        
+        let cell = QSLVipMostGoodCell()
+        
+        cell.isUserInteractionEnabled = true
+        let tap = UITapGestureRecognizer(target: self, action: #selector(firstCellClickAction))
+        cell.addGestureRecognizer(tap)
+        
+        return cell
+    }()
+    
+    lazy var goodsCollectionView: UICollectionView = {
+            
+        let layout = UICollectionViewFlowLayout()
+        layout.minimumLineSpacing = 0
+        layout.scrollDirection = .vertical
+        
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.backgroundColor = .clear
+        
+        collectionView.dataSource = self
+        collectionView.delegate = self
+        
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.bounces = false
+        
+        collectionView.register(cellClass: QSLVipGoodCollectionViewCell.self)
+        
+        return collectionView
+    }()
+    
+    lazy var selectBtn: UIButton = {
+       
+        let btn = UIButton()
+        btn.image(UIImage(named: "public_select_btn_false"), .normal)
+        btn.image(UIImage(named: "public_select_btn_true"), .selected)
+        btn.addTarget(self, action: #selector(selectBtnAction), for: .touchUpInside)
+        return btn
+    }()
+    
+    lazy var bottomContentView: UIView = {
+        let view = UIView()
+        return view
+    }()
+    
+    lazy var bottomTopView: UIView = {
+        let view = UIView()
+        view.isHidden = true
+        view.backgroundColor = .hexStringColor(hexString: "#FFFED8")
+        view.addRadius(radius: 30.rpx)
+        return view
+    }()
+    
+    
+    lazy var bottomTopLabel: UILabel = {
+        let label = UILabel()
+        label.text = ""
+        return label
+    }()
+    
+    func bottomTopLabelInfo(_ goodInfo : QSLGoodModel) {
+        let darkGrayAttributes: [NSAttributedString.Key: Any] = [
+            .foregroundColor: UIColor.hexStringColor(hexString: "#404040"),
+            .font: UIFont.systemFont(ofSize: 11),
+            .paragraphStyle: {
+                let paragraphStyle = NSMutableParagraphStyle()
+                paragraphStyle.alignment = .center
+                return paragraphStyle
+            }(),
+            .kern: -1
+        ]
+
+        // 创建绿色文本样式
+        let greenAttributes: [NSAttributedString.Key: Any] = [
+            .foregroundColor: UIColor.hexStringColor(hexString: "#EE6C1C"),
+            .font:  UIFont.systemFont(ofSize: 15, weight: .black),
+            .paragraphStyle: {
+                let paragraphStyle = NSMutableParagraphStyle()
+                paragraphStyle.alignment = .center
+                return paragraphStyle
+            }(),
+            .kern: -1
+        ]
+        
+        let textArray = goodInfo.text.components(separatedBy: goodInfo.keys.key)
+        if textArray.count > 0 && goodInfo.text.count > 0{
+            bottomTopView.isHidden = false
+            let inputtr = NSMutableAttributedString()
+            let titleOneAttr = NSAttributedString(string: textArray.first ?? "", attributes: darkGrayAttributes)
+            let titleTwoAttr = NSAttributedString(string: " \(goodInfo.keys.value) ", attributes: greenAttributes)
+            inputtr.append(titleOneAttr)
+            inputtr.append(titleTwoAttr)
+            if textArray.count > 1 {
+                let titleThreeAttr = NSAttributedString(string: textArray[1], attributes: darkGrayAttributes)
+                inputtr.append(titleThreeAttr)
+            }
+            bottomTopLabel.attributedText = inputtr
+        } else {
+            bottomTopView.isHidden = true
+        }
+
+    }
+    
+    lazy var bottomView: UIView = {
+       
+        let view = UIView()
+        view.gradientBackgroundColor(color1: .hexStringColor(hexString: "#00434E"), color2: .hexStringColor(hexString: "#0E5E61"), width: QSLConst.qsl_kScreenW - 24.rpx, height: 50.rpx, direction: .horizontal)
+        view.addRadius(radius: 25.rpx)
+        return view
+    }()
+    
+    lazy var unlockBtn: UIButton = {
+       
+        let btn = UIButton()
+        btn.setBackgroundImage(UIImage(named: "vip_unlock_btn_bg"), for: .normal)
+        btn.title("立即解锁")
+        btn.textColor(.hexStringColor(hexString: "#9B3800"))
+        btn.mediumFont(18)
+        btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 30.rpx, bottom: 0, right: 0)
+        btn.addTarget(self, action: #selector(unlockBtnAction), for: .touchUpInside)
+        return btn
+    }()
+    
+    lazy var priceIconLabel: UILabel = {
+       
+        let label = UILabel()
+        label.text("¥")
+        label.textColor = .hexStringColor(hexString: "#FFF8EF")
+        label.font(14)
+        return label
+    }()
+    
+    lazy var priceLabel: UILabel = {
+        
+        let label = UILabel()
+        label.text("168")
+        label.textColor = .hexStringColor(hexString: "#FFF8EF")
+        label.font(24)
+        return label
+    }()
+    
+    lazy var goodTypeLabel: UILabel = {
+        
+        let label = UILabel()
+        label.text("/")
+        label.textColor = .hexStringColor(hexString: "#FFF8EF")
+        label.font(12)
+        return label
+    }()
+    
+    lazy var goodOriginalPriceLabel: UILabel = {
+        
+        let label = UILabel()
+        label.text("原价228")
+        label.textColor = .hexStringColor(hexString: "#FFF8EF")
+        label.font(12)
+        label.centerLineText(lineValue: 1, underlineColor: .hexStringColor(hexString: "#FFF8EF"))
+        return label
+    }()
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        initializeView()
+        
+        updateUI()
+        
+        requestItemList()
+        
+        calculateBuyCount()
+        
+        if let type = self.type {
+            switch type {
+            case .homeRoad:
+                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1001])
+            case .add:
+                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1002])
+            case .friendRoad:
+                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1003])
+            case .contact:
+                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1004])
+            case .mine:
+                gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1006])
+            case .guideComments:
+                print("")
+            }
+        }
+    }
+}
+
+extension QSLActivityVipController {
+    
+    @objc func privacyAction() {
+        
+        let vc = QSLWebViewController()
+        vc.webUrl = QSLConfig.AppPrivacyAgreementLink
+        vc.title = "隐私政策"
+        self.navigationController?.pushViewController(vc, animated: true)
+    }
+    
+    @objc func serviceAction() {
+        
+        let vc = QSLWebViewController()
+        vc.webUrl = QSLConfig.AppServiceAgreementLink
+        vc.title = "服务协议"
+        self.navigationController?.pushViewController(vc, animated: true)
+    }
+    
+    @objc func subscibeAction() {
+        
+        let vc = QSLWebViewController()
+        vc.webUrl = QSLConfig.AppSubscibeAgreementLink
+        vc.title = "续订说明"
+        self.navigationController?.pushViewController(vc, animated: true)
+    }
+    
+    @objc func selectBtnAction() {
+        
+        selectBtn.isSelected = !selectBtn.isSelected
+    }
+    
+    // 恢复按钮点击
+    @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 unlockBtnAction() {
+        
+        switch self.selectGood?.level {
+        case 100 :
+            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1006])
+            break
+        case 700:
+            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1005])
+            break;
+        case 3100:
+            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1004])
+            break;
+        case 9200:
+            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1003])
+            break;
+        case 36600:
+            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1002])
+            break;
+        case 3660000:
+            gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1001])
+            break;
+        default:
+            break;
+        }
+        
+//        if !selectBtn.isSelected {
+//            self.view.toast(text: "请先同意《隐私权政策》和《用户协议》")
+//            return
+//        }
+        
+        let memberModel = QSLBaseManager.shared.userModel.memberModel
+        
+        if let subscriptionExpired = memberModel.subscriptionExpired, !subscriptionExpired {
+            self.view.toast(text: "你已经订阅了")
+            return
+        }
+        
+        if goodList.count > 0, let selectGood = self.selectGood {
+            QSLLoading.show()
+            QSLVipManager.shared.startPay(goods: selectGood) { [self] status, outTradeNo in
+                QSLVipManager.shared.isPaying = false
+                if status == .success {
+                    QSLLoading.success(text: "支付成功")
+                    
+                    //支付成功埋点
+                    gravityInstance?.track(QSLGravityConst.vip_submit_success, properties: ["id": 01001])
+                    
+                    //弹出是否好评的弹窗
+                    QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(QSLGuideusersToCommentType.member)
+                    
+                    // 引力传递支付事件
+                    if let selectGood = self.selectGood {
+                        gravityInstance?.trackPayEvent(withAmount: Int32(selectGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: selectGood.name, withPayMethod: "apple")
+                    }
+                    
+                    #if DEBUG
+                    #else
+                    //苹果广告奇异果传递支付事件
+                    QSWikiHandle.shared.addEventResultAttribution(eventDict: ["event_name": "pay", "event_val": selectGood.amount])
+                    #endif
+                    
+                    if let type = self.type {
+                        switch type {
+                        case .homeRoad:
+                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1001])
+                        case .add:
+                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1002])
+                        case .friendRoad:
+                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1003])
+                        case .contact:
+                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1004])
+                        case .mine:
+                            gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1006])
+                        case .guideComments:
+                            print("")
+                        }
+                    }
+
+                    switch self.selectGood?.level {
+                    case 100 :
+                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 1])
+                        break
+                    case 700:
+                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 5])
+                        break;
+                    case 3100:
+                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 9])
+                        break;
+                    case 9200:
+                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 13])
+                        break;
+                    case 36600:
+                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 17])
+                        break;
+                    case 3660000:
+                        gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 21])
+                        break;
+                    default:
+                        break;
+                    }
+
+                    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
+                        self.navigationController?.popViewController(animated: true)
+                        NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
+                    }
+                    
+                } else if status == .cancel {
+                    QSLLoading.error(text: "支付取消")
+                    payFailAlertTip()
+                } else if status == .fail {
+                    gravityInstance?.track(QSLGravityConst.vip_fail)
+                    QSLLoading.error(text: "支付失败")
+                    payFailAlertTip()
+                } else if status == .searchFail {
+                    QSLLoading.error(text: "查询订单失败,请稍后重试")
+                }
+            }
+        }
+    }
+    
+    func payFailAlertTip() {
+        if let currentWindow = UIApplication.keyWindow {
+            QSLRetainPopUpAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure:  { [weak self] in
+                self?.unlockBtnAction()
+            })
+        }
+    }
+    
+    @objc func firstCellClickAction() {
+        
+        for i in 0..<self.goodList.count {
+            self.goodList[i].isSelect = false
+        }
+        
+        if self.goodList.count > 0 {
+            self.goodList[0].isSelect = true
+            self.selectGood = self.goodList[0]
+            self.mostCell.config(model: self.goodList[0])
+            //选中立即支付
+            unlockBtnAction()
+        }
+        
+        switch self.selectGood?.level {
+        case 100 :
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
+            break
+        case 700:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
+            break;
+        case 3100:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
+            break;
+        case 9200:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
+            break;
+        case 36600:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
+            break;
+        case 3660000:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
+            break;
+        default:
+            break;
+        }
+        
+        self.goodsCollectionView.reloadData()
+    }
+}
+
+extension QSLActivityVipController {
+    
+    // 请求商品列表
+    func requestItemList() {
+        // 定义并赋值 itemListDict(根据条件变化)
+        var itemListDict: [String: Any] = ["itemListType": 2]
+        if UserDefaults.standard.string(forKey: QSLActivityVipController.record_non_member_clicks_to_claim) == nil && self.type == .guideComments {
+            itemListDict = ["itemListType": 2, "showExtraText": true]
+            // 记录非会员点击领取
+            UserDefaults.standard.set("YES", forKey: QSLActivityVipController.record_non_member_clicks_to_claim)
+            UserDefaults.standard.synchronize()
+        }
+        
+        // 网络请求时使用 itemListDict 作为参数(关键修复)
+        QSLNetwork().request(.vipItemList(dict: itemListDict)) { response in
+            // 后续逻辑不变...
+            let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
+            self.goodList = list
+            
+            if self.goodList.count > 0 {
+                self.goodList[0].isSelect = true
+                self.selectGood = self.goodList[0]
+                self.mostCell.config(model: self.goodList[0])
+        
+                let row = ceil(Double(self.goodList.count - 1) / 3.0)
+                let height = UX.goodsBgHeight + (row * UX.collectionRowHeight)
+                self.goodsBgView.gradientBackgroundColor(color1: .hexStringColor(hexString: "#FFF8F2"), color2: .hexStringColor(hexString: "#FFFFFF"), width: QSLConst.qsl_kScreenW, height: height, direction: .vertical)
+                
+                self.goodsBgView.snp.updateConstraints { make in
+                    make.height.equalTo(height)
+                }
+                
+                self.scrollView.snp.makeConstraints { make in
+                    make.bottom.equalTo(self.mainView)
+                }
+                
+                self.checkRenewalOfProducts()
+            }
+            self.goodsCollectionView.reloadData()
+        } fail: { code, error in
+            self.view.toast(text: "加载商品列表失败")
+        }
+    }
+    
+    ///检查有没有续订的产品
+    func checkRenewalOfProducts() {
+        let hasSubscribable = self.goodList.contains(where: { model in
+            return model.subscribable == 1
+        })
+    }
+    
+    // 计算购买人数
+    func calculateBuyCount() {
+        
+        var num = 145883
+        if let localNum = UserDefaults.standard.value(forKey: QSLConfig.user_default_local_buy_count) as? Int {
+            num = localNum
+        }
+        
+        let randomAddCount = Int.random(in: 1...10)
+        num = num + randomAddCount
+        UserDefaults.standard.setValue(num, forKey: QSLConfig.user_default_local_buy_count)
+        self.peopleCountLabel.text("\(num)人 已开通VIP")
+    }
+}
+
+// MARK: - 设置 CollectionView
+extension QSLActivityVipController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
+    
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return goodList.count - 1
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        
+        let cell = collectionView.dequeueReusableCell(cellType: QSLVipGoodCollectionViewCell.self, cellForRowAt: indexPath)
+        let model = self.goodList[indexPath.row + 1]
+        
+        if self.goodList.count - 1 == 2 {
+            cell.config(model: model, type: .big)
+        } else {
+            cell.config(model: model, type: .small)
+        }
+        
+        return cell
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        
+        for i in 0..<self.goodList.count {
+            self.goodList[i].isSelect = false
+        }
+        
+        if self.goodList.count > 0 {
+            self.goodList[indexPath.row + 1].isSelect = true
+            self.selectGood = self.goodList[indexPath.row + 1]
+            self.mostCell.config(model: self.goodList[0])
+            //选中立即支付
+            unlockBtnAction()
+        }
+        
+        switch self.selectGood?.level {
+        case 100 :
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
+            break
+        case 700:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
+            break;
+        case 3100:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
+            break;
+        case 9200:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
+            break;
+        case 36600:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
+            break;
+        case 3660000:
+            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
+            break;
+        default:
+            break;
+        }
+        
+        self.goodsCollectionView.reloadData()
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        
+        var width = (QSLConst.qsl_kScreenW - 42.0.rpx) / 3.0
+        
+        if self.goodList.count - 1 == 2 {
+            width = (QSLConst.qsl_kScreenW - 36.0.rpx) / 2.0
+        }
+        
+        return CGSize(width: width, height: 134.0.rpx)
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+        return 6.rpx
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
+        return 3.rpx
+    }
+}
+
+extension QSLActivityVipController {
+    
+    func updateUI() {
+        
+        if QSLBaseManager.shared.isLogin() && QSLBaseManager.shared.isVip() {
+            let model = QSLBaseManager.shared.userModel.memberModel
+            if model.permanent {
+                
+                self.vipTimeLabel.text("您已是尊贵的永久会员")
+                self.bottomContentView.isHidden = true
+            } else {
+                
+                let level = model.memberLevelString()
+                let endTime = model.endTimestampString()
+                self.vipTimeLabel.text("\(level):\(endTime)到期")
+            }
+        } else {
+            
+            self.vipTimeLabel.text("升级VIP会员,解锁全部功能")
+        }
+    }
+    
+    func updateSelectGoodUI() {
+        var priceText = ""
+        var originalPriceText = ""
+        if let selectGood = self.selectGood {
+            if selectGood.amount.truncatingRemainder(dividingBy: 100) == 0 {
+                priceText = "\(Int(selectGood.amount / 100))"
+            } else {
+                priceText = String(format: "%.2lf", selectGood.amount / 100 )
+            }
+            
+            if selectGood.originalAmount.truncatingRemainder(dividingBy: 100) == 0 {
+                originalPriceText = "\(Int(selectGood.originalAmount / 100))"
+            } else {
+                originalPriceText = String(format: "%.2lf", selectGood.originalAmount / 100 )
+            }
+        }
+        self.priceLabel.text(priceText)
+//        self.goodTypeLabel.text("/ \(self.selectGood?.name ?? "")")
+        self.goodOriginalPriceLabel.text("原价\(originalPriceText)")
+        
+        ///底部内容
+        bottomTopLabelInfo(self.selectGood ?? QSLGoodModel())
+    }
+    
+    func initializeView() {
+        
+        self.view.addSubview(vipBg)
+        vipBg.snp.makeConstraints { make in
+            make.left.top.right.equalTo(0)
+        }
+        
+        self.view.addSubview(backButton)
+        backButton.snp.makeConstraints { make in
+            make.size.equalTo(100.rpx)
+            make.height.equalTo(25.rpx)
+            make.left.equalTo(12.rpx)
+            make.top.equalTo(QSLConst.qsl_kStatusBarFrameH)
+        }
+        
+        self.view.addSubview(peopleCountView)
+        peopleCountView.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 212.rpx, height: 24.rpx))
+            make.right.equalTo(-13.rpx)
+            make.centerY.equalTo(backButton.snp.centerY)
+        }
+        
+        peopleCountView.addSubview(peopleAvatarImageView)
+        peopleAvatarImageView.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 72.rpx, height: 16.6.rpx))
+            make.left.equalTo(3.rpx)
+            make.centerY.equalTo(peopleCountView.snp.centerY)
+        }
+        
+        peopleCountView.addSubview(peopleCountLabel)
+        peopleCountLabel.snp.makeConstraints { make in
+            make.left.equalTo(peopleAvatarImageView.snp.right).offset(7.rpx)
+            make.centerY.equalTo(peopleCountView.snp.centerY)
+        }
+        
+        self.view.addSubview(scrollView)
+        scrollView.snp.makeConstraints { make in
+            make.left.right.equalTo(0)
+            make.top.equalTo(QSLConst.qsl_kNavFrameH)
+            make.bottom.equalTo(0)
+        }
+        
+        scrollView.addSubview(cardBannerImageView)
+        cardBannerImageView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(336.rpx)
+            make.height.equalTo(108.rpx)
+        }
+        
+        cardBannerImageView.addSubview(vipTimeLabel)
+        vipTimeLabel.snp.makeConstraints { make in
+            make.left.equalTo(23.rpx)
+            make.bottom.equalTo(-19.rpx)
+        }
+        
+        scrollView.addSubview(funcBannerImageView)
+        funcBannerImageView.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 336.rpx, height: 172.rpx))
+            make.centerX.equalToSuperview()
+            make.top.equalTo(cardBannerImageView.snp.bottom).offset(14.rpx)
+        }
+        
+        scrollView.addSubview(mainView)
+        mainView.snp.makeConstraints { make in
+            make.left.right.equalTo(0)
+            make.top.equalTo(funcBannerImageView.snp.bottom).offset(-24.rpx)
+            make.width.equalTo(QSLConst.qsl_kScreenW)
+            //            make.height.equalTo(800.rpx)
+        }
+        
+        let goodsBgHeight = 54.rpx + UX.mostCellHeight
+        mainView.addSubview(goodsBgView)
+        goodsBgView.snp.makeConstraints { make in
+            make.top.left.right.equalTo(0)
+            make.width.equalTo(QSLConst.qsl_kScreenW)
+            make.height.equalTo(goodsBgHeight)
+        }
+        
+        goodsBgView.addSubview(vipGoodsTitleIcon)
+        vipGoodsTitleIcon.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 117.rpx, height: 26.rpx))
+            make.left.equalTo(20.rpx)
+            make.top.equalTo(16.rpx)
+        }
+        
+        goodsBgView.addSubview(resumeBtn)
+        resumeBtn.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 75.rpx, height: 16.rpx))
+            make.right.equalTo(-18.rpx)
+            make.centerY.equalTo(vipGoodsTitleIcon.snp.centerY)
+        }
+        
+        goodsBgView.addSubview(mostCell)
+        mostCell.snp.makeConstraints { make in
+            make.left.equalTo(12.rpx)
+            make.right.equalTo(-16.rpx)
+            make.height.equalTo(113.rpx)
+            make.top.equalTo(vipGoodsTitleIcon.snp.bottom).offset(10.rpx)
+        }
+        
+        goodsBgView.addSubview(goodsCollectionView)
+        goodsCollectionView.snp.makeConstraints { make in
+            make.left.equalTo(12.rpx)
+            make.right.equalTo(-18.rpx)
+            make.bottom.equalTo(-20.rpx)
+            make.top.equalTo(mostCell.snp.bottom).offset(3.rpx)
+        }
+        
+        scrollView.snp.makeConstraints { make in
+            make.bottom.equalTo(mainView)
+        }
+        
+        self.view.addSubview(bottomContentView)
+        bottomContentView.snp.makeConstraints { make in
+            make.left.equalTo(12.rpx)
+            make.right.equalTo(-12.rpx)
+            make.bottom.equalTo(-QSLConst.qsl_kTabbarBottom)
+            make.height.equalTo(72.rpx)
+        }
+    }
+        
+}

+ 477 - 0
QuickSearchLocation/Classes/Pages/QSLVip/Controller/QSLActivityVipVC.swift

@@ -0,0 +1,477 @@
+//
+//  QSLActivityVipVC.swift
+//  QuickSearchLocation
+//
+//  Created by Destiny on 2025/9/23.
+//
+
+import UIKit
+import GKCycleScrollView
+
+class QSLActivityVipVC: QSLBaseController {
+    var goodList: [QSLGoodModel] = [QSLGoodModel]()
+    var selectGood: QSLGoodModel? {
+        didSet {
+            updateSelectGoodUI()
+        }
+    }
+    var currentCell: QSLVipMostGoodCell?
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        //gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1001])
+        self.initializeView()
+        
+        self.requestNetwork()
+        
+        
+    }
+    
+    @objc func payBtnAction() {
+        
+    }
+    
+    @objc func requestNetwork() {
+        // 定义并赋值 itemListDict(根据条件变化)
+        let itemListDict: [String: Any] = ["itemListType": 2]
+        
+        // 网络请求时使用 itemListDict 作为参数(关键修复)
+        QSLNetwork().request(.vipActivityItemList(dict: itemListDict)) { response in
+            // 后续逻辑不变...
+            let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
+            self.goodList = list
+            //TODO: 测试
+            self.goodList += list
+            self.goodList += list
+            
+            if self.goodList.count > 0 {
+                self.goodList[0].isSelect = true
+                self.selectGood = self.goodList[0]
+
+                var height = 200.rpx
+                if(self.goodList.count > 2){
+                    let row = (self.goodList.count-1)/2 + 1
+                    height = 124.rpx + row*124.rpx
+                }
+                
+                self.vipItemView.snp.updateConstraints { make in
+                    make.height.equalTo(height)
+                }
+                
+                self.scrollView.snp.makeConstraints { make in
+                    make.bottom.equalTo(self.vipItemView).offset(100)
+                }
+//                
+//                self.checkRenewalOfProducts()
+            }
+            
+            
+            self.goodsCollectionView.reloadData()
+        } fail: { code, error in
+            self.view.toast(text: "加载商品列表失败")
+        }
+    }
+    
+    @objc func resumeBtnAction() {
+        
+    }
+
+    lazy var scrollView: UIScrollView = {
+       
+        let scrollView = UIScrollView()
+//        scrollView.delegate = self
+        scrollView.bounces = false
+        scrollView.showsVerticalScrollIndicator = false
+        scrollView.contentInsetAdjustmentBehavior = .never
+        return scrollView
+    }()
+    
+    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.white
+        return view
+    }()
+    
+    lazy var naviTitleIcon: UILabel = {
+        let label = UILabel()
+        label.text("超值优惠")
+        label.textColor = .white
+        label.mediumFont(17)
+        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 vipBg: UIView = {
+        let imageView = UIView()
+        return imageView
+    }()
+    
+    lazy var vipTopBg: UIImageView = {
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_activity_top_bg")
+        return imageView
+    }()
+    
+    lazy var vipTopTitleView: UIImageView = {
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "vip_activity_top_title")
+        return imageView
+    }()
+    
+    lazy var vipDiamondView: UIButton = {
+        let button = UIButton()
+        button.image(UIImage(named: "vip_activity_top_diamond"))
+        button.title("会员限时福利")
+        button.font(14)
+        button.textColor(.white)
+        button.setImageTitleLayout(.imgLeft, spacing: 4.rpx)
+        button.isUserInteractionEnabled = false
+        return button
+    }()
+    
+    lazy var vipContentView: 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.white
+        return view
+    }()
+    
+    lazy var addTitleIcon: UILabel = {
+        let label = UILabel()
+        label.text("功能介绍")
+        label.textColor = .hexStringColor(hexString: "#202020")
+        label.boldFont(15)
+        return label
+    }()
+    
+    lazy var addTitleIconBg: UIView = {
+        let view = UIView(frame: CGRectMake(0, 0, 117.rpx, 8.rpx))
+        view.addRadius(radius: 4.rpx)
+            
+        // 创建渐变色层
+        let gradientLayer = CAGradientLayer()
+        gradientLayer.colors = [
+            UIColor.hexStringColor(hexString: "#00DDAA",alpha: 1).cgColor,
+            UIColor.hexStringColor(hexString: "#00DDAA",alpha: 0).cgColor
+        ]
+        gradientLayer.startPoint = CGPoint(x: 0, y: 0.4) // 左中
+        gradientLayer.endPoint = CGPoint(x: 1, y: 0.4)   // 右中
+        gradientLayer.frame = view.bounds
+        
+        // 确保在布局变化时更新frame
+        view.layer.insertSublayer(gradientLayer, at: 0)
+        
+        // 添加布局变化的监听
+        view.layoutIfNeeded()
+        view.layoutSubviews()
+        return view
+    }()
+    
+    lazy var cycleScrollView: GKCycleScrollView = {
+      
+        let cycleScrollView = GKCycleScrollView()
+        cycleScrollView.dataSource = self
+        cycleScrollView.delegate = self
+        cycleScrollView.isAutoScroll = true
+        cycleScrollView.isInfiniteLoop = true
+        cycleScrollView.isChangeAlpha = false
+        cycleScrollView.leftRightMargin = 12
+        cycleScrollView.topBottomMargin = 12
+        cycleScrollView.pageControl = pageControl
+        cycleScrollView.reloadData()
+        
+        return cycleScrollView
+    }()
+    
+    lazy var pageControl: GKPageControl = {
+      
+        let pageControl = GKPageControl()
+        pageControl.style = .rectangle
+        pageControl.dotHeight = 5.rpx
+        pageControl.dotWidth = 5.rpx
+        pageControl.dotMargin = 4.rpx
+        pageControl.pageIndicatorTintColor = .hexStringColor(hexString: "#EEEEEE")
+        pageControl.currentPageIndicatorTintColor = QSLColor.themeMainColor
+        return pageControl
+    }()
+    
+    lazy var vipItemView: UIView = {
+        let item = UIView()
+        return item
+    }()
+    
+    lazy var goodsCollectionView: UICollectionView = {
+            
+        let layout = UICollectionViewFlowLayout()
+        layout.minimumLineSpacing = 0
+        layout.scrollDirection = .vertical
+        
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.backgroundColor = .clear
+        
+        collectionView.dataSource = self
+        collectionView.delegate = self
+        
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.bounces = false
+        
+        collectionView.register(cellClass: QSLActivityVipCell.self)
+        
+        return collectionView
+    }()
+    
+}
+
+extension QSLActivityVipVC{
+    
+    func updateSelectGoodUI(){
+        
+    }
+    
+    func initializeView() {
+        
+        self.view.addSubview(scrollView)
+        scrollView.snp.makeConstraints { make in
+            make.bottom.top.left.right.equalTo(0)
+        }
+        
+        self.view.addSubview(vipNaviView)
+        vipNaviView.snp.makeConstraints { make in
+            make.top.left.right.equalTo(0)
+            make.top.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(70.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.scrollView.addSubview(vipBg)
+        vipBg.snp.makeConstraints { make in
+            make.top.bottom.left.equalTo(0)
+            make.width.equalTo(QSLConst.qsl_kScreenW)
+        }
+        
+        vipBg.addSubview(vipTopBg)
+        vipTopBg.snp.makeConstraints { make in
+            make.left.top.right.equalTo(0)
+            make.height.equalTo(185.rpx)
+        }
+        
+        vipTopBg.addSubview(vipTopTitleView)
+        vipTopTitleView.snp.makeConstraints { make in
+            make.left.equalTo(16.rpx)
+            make.bottom.equalTo(vipTopBg.snp.bottom).offset(-16.rpx)
+            make.height.equalTo(22.rpx)
+            make.width.equalTo(183.rpx)
+        }
+        
+        vipTopBg.addSubview(vipDiamondView)
+        vipDiamondView.snp.makeConstraints { make in
+            make.left.equalTo(16.rpx)
+            make.bottom.equalTo(vipTopTitleView.snp.top).offset(-6.rpx)
+            make.height.equalTo(20.rpx)
+            make.width.equalTo(105.rpx)
+        }
+        
+        vipBg.addSubview(vipContentView)
+        vipContentView.snp.makeConstraints { make in
+            make.top.equalTo(185.rpx)
+            make.left.right.equalTo(0.rpx)
+            make.height.equalTo(QSLConst.qsl_kScreenH)
+        }
+        
+        vipContentView.addSubview(addTitleIconBg)
+        addTitleIconBg.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 117.rpx, height: 8.rpx))
+            make.left.equalTo(16.rpx)
+            make.top.equalTo(26.rpx)
+        }
+        
+        vipContentView.addSubview(addTitleIcon)
+        addTitleIcon.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 157.rpx, height: 26.rpx))
+            make.left.equalTo(20.rpx)
+            make.top.equalTo(12.rpx)
+        }
+        
+        vipContentView.addSubview(cycleScrollView)
+        cycleScrollView.snp.makeConstraints { make in
+            make.left.right.equalTo(0)
+            make.height.equalTo(150.rpx)
+            make.top.equalTo(50.rpx)
+        }
+        
+        vipContentView.addSubview(pageControl)
+        pageControl.snp.makeConstraints { make in
+            make.size.equalTo(CGSize(width: 68.rpx, height: 4.rpx))
+            make.centerX.equalToSuperview()
+            make.top.equalTo(cycleScrollView.snp.bottom).offset(17.rpx)
+        }
+        
+        vipContentView.addSubview(vipItemView)
+        vipItemView.snp.makeConstraints { make in
+            make.left.right.equalTo(0)
+            make.height.equalTo(150.rpx)
+            make.top.equalTo(pageControl.snp.bottom).offset(16.rpx)
+        }
+        
+        vipItemView.addSubview(goodsCollectionView)
+        goodsCollectionView.snp.makeConstraints { make in
+            make.left.right.top.bottom.equalTo(0)
+        }
+        
+    }
+}
+
+extension QSLActivityVipVC : GKCycleScrollViewDelegate, GKCycleScrollViewDataSource{
+    func cycleScrollView(_ cycleScrollView: GKCycleScrollView!, cellForViewAt index: Int) -> GKCycleScrollViewCell! {
+        if let cell = cycleScrollView.dequeueReusableCell() {
+            cell.imageView.image = UIImage(named: "vip_activity_banner_\(index+1)")
+            return cell
+        }
+        
+        let cell = GKCycleScrollViewCell()
+        cell.imageView.image = UIImage(named: "vip_activity_banner_\(index+1)")
+        return cell
+
+    }
+    
+    func numberOfCells(in cycleScrollView: GKCycleScrollView!) -> Int {
+        return 3
+    }
+    
+    func sizeForCell(in cycleScrollView: GKCycleScrollView!) -> CGSize {
+        return CGSizeMake(QSLConst.qsl_kScreenW - 90.rpx, 150.rpx);
+    }
+    
+    
+}
+
+extension QSLActivityVipVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
+    
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return goodList.count
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        
+        let cell = collectionView.dequeueReusableCell(cellType: QSLActivityVipCell.self, cellForRowAt: indexPath)
+        let model = self.goodList[indexPath.row]
+        
+        if (indexPath.row == 0) {
+            cell.config(model: model, type: .top)
+        } else {
+            if(self.goodList.count > 2){
+                cell.config(model: model, type: .small)
+            }else{
+                cell.config(model: model, type: .big)
+            }
+        }
+        
+        return cell
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        for index in 0..<self.goodList.count{
+            var submodel = self.goodList[index]
+            submodel.isSelect = false
+        }
+        
+        var model = self.goodList[indexPath.row]
+        model.isSelect = !model.isSelect
+       
+//        switch self.selectGood?.level {
+//        case 100 :
+//            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
+//            break
+//        case 700:
+//            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
+//            break;
+//        case 3100:
+//            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
+//            break;
+//        case 9200:
+//            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
+//            break;
+//        case 36600:
+//            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
+//            break;
+//        case 3660000:
+//            gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
+//            break;
+//        default:
+//            break;
+//        }
+        
+        self.goodsCollectionView.reloadData()
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        
+        if (indexPath.row == 0) {
+            return CGSize(width: QSLConst.qsl_kScreenW-32.rpx, height: 112.rpx)
+        } else {
+            if(self.goodList.count == 2){
+                return CGSize(width: QSLConst.qsl_kScreenW-32.rpx, height: 72.rpx)
+            }else{
+                return CGSize(width: (QSLConst.qsl_kScreenW-50.rpx)/2.0, height: 112.rpx)
+            }
+        }
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
+        return UIEdgeInsets(top: 0, left: 16.rpx, bottom: 0, right: 16.rpx)
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+        return 10.rpx
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
+        if(self.goodList.count == 2){
+            return 10.rpx
+        }else{
+            return 16.rpx
+        }
+    }
+
+}

+ 2 - 0
QuickSearchLocation/Macro/QSLApi.swift

@@ -168,6 +168,8 @@ extension QSLApi {
     // 商品列表
     static let vip_item_list = "/s/v1/item/list"
     
+    static let vip_activity_item_list = "/s/v1/guide/item/list"
+    
     // 创建订单并发起支付
     static let vip_order_submitAndPay = "/s/v1/order/submitAndRequestPay"
     

+ 1 - 1
QuickSearchLocation/Resources/Assets.xcassets/Launch/launch_icon.imageset/Contents.json

@@ -9,7 +9,7 @@
       "scale" : "2x"
     },
     {
-      "filename" : "launch_icon@3x.png",
+      "filename" : "Group 42959 2.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
QuickSearchLocation/Resources/Assets.xcassets/Launch/launch_icon.imageset/Group 42959 2.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Launch/launch_icon.imageset/launch_icon@3x.png


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


+ 1 - 2
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/Contents.json

@@ -5,12 +5,11 @@
       "scale" : "1x"
     },
     {
-      "filename" : "mine_about_logo@2x.png",
+      "filename" : "Group 42959 1.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "mine_about_logo@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/Group 42959 1.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/mine_about_logo@2x.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Mine/mine_about_logo.imageset/mine_about_logo@3x.png


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

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

+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_1.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_1.imageset/Group 40471 1.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_2.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_2.imageset/Group 40471 3 (1).png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_3.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_banner_3.imageset/Group 40471 2.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_s.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_s.imageset/Group 40405.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_uns.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_item_uns.imageset/Group 42961.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_bg.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/activity/vip_activity_top_bg.imageset/Mask group.png


+ 22 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_diamond.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_diamond.imageset/Subtract-1.png


BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_diamond.imageset/Subtract.png


+ 21 - 0
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_title.imageset/Contents.json

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

BIN
QuickSearchLocation/Resources/Assets.xcassets/Vip/activity/vip_activity_top_title.imageset/文字.png