QSLActivityVipVC.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. //
  2. // QSLActivityVipVC.swift
  3. // QuickSearchLocation
  4. //
  5. // Created by Destiny on 2025/9/23.
  6. //
  7. import UIKit
  8. import GKCycleScrollView
  9. import YYText
  10. class QSLActivityVipVC: QSLBaseController {
  11. var goodList: [QSLGoodModel] = [QSLGoodModel]()
  12. var selectGood: QSLGoodModel?
  13. var currentCell: QSLVipMostGoodCell?
  14. var dismissHandler: ((Bool) -> Void)?
  15. var isCancel = false
  16. override func viewDidLoad() {
  17. super.viewDidLoad()
  18. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_show)
  19. QSLCountdownManager.shared.addDelegate(self)
  20. self.initializeView()
  21. self.requestNetwork()
  22. self.updateServiceLabelText(showSubscribe: false)
  23. // if(QSLBaseManager.shared.isLogin()){
  24. // self.naviResumeBtn.isHidden = false
  25. // }else{
  26. // self.naviResumeBtn.isHidden = true
  27. // }
  28. }
  29. deinit {
  30. QSLCountdownManager.shared.removeDelegate(self)
  31. }
  32. @objc func privacyAction() {
  33. let vc = QSLWebViewController()
  34. vc.webUrl = QSLConfig.AppPrivacyAgreementLink
  35. vc.title = "隐私政策"
  36. self.present(vc, animated: true)
  37. }
  38. @objc func serviceAction() {
  39. let vc = QSLWebViewController()
  40. vc.webUrl = QSLConfig.AppServiceAgreementLink
  41. vc.title = "服务协议"
  42. self.present(vc, animated: true)
  43. }
  44. @objc func subscibeAction() {
  45. let vc = QSLWebViewController()
  46. vc.webUrl = QSLConfig.AppSubscibeAgreementLink
  47. vc.title = "续订说明"
  48. self.present(vc, animated: true)
  49. }
  50. @objc func payBtnAction() {
  51. if(!QSLBaseManager.shared.isLogin()){
  52. if(QSLBaseManager.shared.isVip()){
  53. QSLJumpManager.shared.pushToLogin(type: .member)
  54. return
  55. }
  56. if(QSLConfig.loginPayEnable){
  57. QSLJumpManager.shared.pushToLogin(type: .member)
  58. return
  59. }
  60. }
  61. if let curGood = self.selectGood {
  62. QSLCountdownManager.shared.selectGood = curGood
  63. }
  64. switch self.selectGood?.level {
  65. case 100 :
  66. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "day"])
  67. break
  68. case 700:
  69. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "weekly"])
  70. break;
  71. case 3100:
  72. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "monthly"])
  73. break;
  74. case 9200:
  75. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "quarterly"])
  76. break;
  77. case 36600:
  78. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "yearly"])
  79. break;
  80. case 3660000:
  81. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_click, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "lifetime"])
  82. break;
  83. default:
  84. break;
  85. }
  86. let memberModel = QSLBaseManager.shared.userModel.memberModel
  87. if let subscriptionExpired = memberModel.subscriptionExpired, !subscriptionExpired {
  88. self.view.toast(text: "你已经订阅了")
  89. return
  90. }
  91. if goodList.count > 0, let selectGood = self.selectGood {
  92. QSLLoading.showWithCancel()
  93. QSLVipManager.shared.startPay(goods: selectGood) { [self] status, outTradeNo in
  94. QSLVipManager.shared.isPaying = false
  95. if status == .success {
  96. QSLLoading.success(text: "支付成功")
  97. //弹出是否好评的弹窗
  98. //QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(QSLGuideusersToCommentType.member)
  99. // 引力传递支付事件
  100. if let selectGood = self.selectGood {
  101. gravityInstance?.trackPayEvent(withAmount: Int32(selectGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: selectGood.name, withPayMethod: "apple")
  102. }
  103. #if DEBUG
  104. #else
  105. //苹果广告奇异果传递支付事件
  106. QSWikiHandle.shared.addEventResultAttribution(eventDict: ["event_name": "pay", "event_val": selectGood.amount])
  107. #endif
  108. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_result, eventProps: ["purchase_result": "success","pay_amount":Int32(selectGood.amount)])
  109. DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
  110. self.dismiss(animated: false)
  111. NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
  112. DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
  113. if(!QSLBaseManager.shared.isLogin()){
  114. QSLJumpManager.shared.pushToLogin(type: .member)
  115. }
  116. }
  117. }
  118. } else if status == .cancel {
  119. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_result, eventProps: ["purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
  120. QSLLoading.error(text: "支付取消")
  121. // payFailAlertTip()
  122. self.isCancel = true
  123. } else if status == .fail {
  124. QSEventHandle.eventPush(eventName: QSLGravityConst.activity_vip_result, eventProps: ["purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
  125. QSLLoading.error(text: "支付失败")
  126. // payFailAlertTip()
  127. self.isCancel = true
  128. }
  129. }
  130. }
  131. }
  132. func payFailAlertTip() {
  133. var yearGood = self.selectGood
  134. for subGood in self.goodList{
  135. if(subGood.level == 36600){
  136. yearGood = subGood
  137. break
  138. }
  139. }
  140. if let currentWindow = UIApplication.keyWindow {
  141. QSLRetainPopUpAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure: { [weak self] in
  142. self?.selectGood = yearGood
  143. self?.payBtnAction()
  144. },secondBtnClosure: {
  145. })
  146. }
  147. }
  148. func startTimer(){
  149. // 开始首页商品倒计时
  150. QSLCountdownManager.shared.startCountdown(type: .homeProduct, seconds: 900000) {[weak self] remainingSeconds in
  151. } finishCallback: {
  152. }
  153. }
  154. @objc func requestNetwork() {
  155. // 定义并赋值 itemListDict(根据条件变化)
  156. let itemListDict: [String: Any] = ["itemListType": 2]
  157. // 网络请求时使用 itemListDict 作为参数(关键修复)
  158. QSLNetwork().request(.vipActivityItemList(dict: itemListDict)) { response in
  159. // 后续逻辑不变...
  160. let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
  161. self.goodList = list
  162. if self.goodList.count > 0 {
  163. self.goodList[0].isSelect = true
  164. self.selectGood = self.goodList[0]
  165. var height = 140.rpx
  166. if self.goodList.count == 2 {
  167. height = 200.rpx
  168. } else {
  169. let remainingItems = self.goodList.count - 1
  170. let remainingRows = (remainingItems + 1) / 2
  171. height = Int(134.rpx + CGFloat(remainingRows) * 124.rpx)
  172. }
  173. self.goodsCollectionView.snp.updateConstraints { make in
  174. make.height.equalTo(height)
  175. }
  176. self.scrollView.contentSize = CGSize(width: 0.0, height: 415.rpx+CGFloat(height)+100+QSLConst.qsl_kTabbarBottom/2+12)
  177. QSLCountdownManager.shared.selectGood = self.goodList[0]
  178. self.startTimer()
  179. NotificationCenter.default.post(
  180. name: Notification.Name("QSLHomeUpdateCouponViewNoti"),
  181. object: nil,
  182. userInfo: ["showCoupon": true]
  183. )
  184. }
  185. self.goodsCollectionView.reloadData()
  186. } fail: { code, error in
  187. self.view.toast(text: "加载商品列表失败")
  188. }
  189. }
  190. override func backBtnAction() {
  191. self.dismissHandler?(self.isCancel)
  192. super.backBtnAction()
  193. }
  194. // 恢复按钮点击
  195. @objc func resumeBtnAction() {
  196. let memberModel = QSLBaseManager.shared.userModel.memberModel
  197. let expired = memberModel.expired
  198. if !expired {
  199. QSLLoading.success(text: "您已经在订阅中,无需恢复")
  200. return
  201. }
  202. QSLLoading.show()
  203. QSLVipManager.shared.restoreAction { isSuccess in
  204. QSLVipManager.shared.isPaying = false
  205. if isSuccess {
  206. QSLNetwork().request(.userMember(dict: [:])) { response in
  207. let model = response.mapObject(QSLMemberModel.self, modelKey: "data")
  208. QSLBaseManager.shared.userModel.memberModel = model
  209. if model.expired {
  210. QSLBaseManager.shared.saveVipExpiredTime(time: 0)
  211. } else {
  212. QSLBaseManager.shared.saveVipExpiredTime(time: model.endTimestamp)
  213. }
  214. QSLBaseManager.shared.saveUserId(id: model.userId)
  215. if model.endTimestamp > memberModel.endTimestamp {
  216. QSLLoading.success(text: "恢复成功")
  217. // 支付成功通知
  218. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  219. self.navigationController?.popViewController(animated: true)
  220. }
  221. } else {
  222. QSLLoading.error(text: "没有可供恢复的订阅")
  223. }
  224. } fail: { code, error in
  225. QSLLoading.error(text: "没有可供恢复的订阅")
  226. }
  227. } else {
  228. QSLLoading.error(text: "没有可供恢复的订阅")
  229. }
  230. }
  231. }
  232. // 更新服务条款文本内容
  233. func updateServiceLabelText(showSubscribe: Bool) {
  234. let attr = NSMutableAttributedString()
  235. // 固定部分:购买即同意
  236. let firstAttr = NSMutableAttributedString(string: "购买前请先阅读")
  237. firstAttr.font(11)
  238. firstAttr.color(UIColor.init(white: 0, alpha: 0.4))
  239. attr.append(firstAttr)
  240. // 《隐私权政策》
  241. let privacyHL = YYTextHighlight()
  242. let privacyStr = "隐私政策"
  243. let privacyText = NSMutableAttributedString(string: privacyStr)
  244. privacyText.font(11)
  245. privacyText.color(UIColor.init(white: 0, alpha: 0.7))
  246. privacyText.yy_setTextHighlight(privacyHL, range: NSRange(location: 0, length: privacyStr.count))
  247. privacyHL.tapAction = { [weak self] containerView, text, range, rect in
  248. self?.privacyAction()
  249. }
  250. let underline1 = YYTextDecoration(style: .single, width: 1, color: UIColor(white: 0, alpha: 0.7))
  251. privacyText.yy_textUnderline = underline1
  252. attr.append(privacyText)
  253. let blankAttr = NSMutableAttributedString(string: "&")
  254. blankAttr.color(UIColor.init(white: 0, alpha: 0.4))
  255. blankAttr.font(11)
  256. attr.append(blankAttr)
  257. // 《用户协议》
  258. let serviceHL = YYTextHighlight()
  259. let serviceStr = "服务条款"
  260. let serviceText = NSMutableAttributedString(string: serviceStr)
  261. serviceText.font(11)
  262. serviceText.color(UIColor.init(white: 0, alpha: 0.7))
  263. serviceText.yy_setTextHighlight(serviceHL, range: NSRange(location: 0, length: serviceStr.count))
  264. serviceHL.tapAction = { [weak self] containerView, text, range, rect in
  265. self?.serviceAction()
  266. }
  267. let underline = YYTextDecoration(style: .single, width: 1, color: UIColor(white: 0, alpha: 0.7))
  268. serviceText.yy_textUnderline = underline
  269. attr.append(serviceText)
  270. // 根据条件决定是否添加《续订说明》相关内容
  271. if showSubscribe {
  272. attr.append(blankAttr)
  273. let andAttr = NSMutableAttributedString(string: "和")
  274. andAttr.font(10)
  275. andAttr.color(.hexStringColor(hexString: "#A7A7A7"))
  276. attr.append(andAttr)
  277. attr.append(blankAttr)
  278. let subcribeHL = YYTextHighlight()
  279. let subcribeStr = "《续订说明》"
  280. let subcribeText = NSMutableAttributedString(string: subcribeStr)
  281. subcribeText.font(10)
  282. subcribeText.color(.hexStringColor(hexString: "#E7B983"))
  283. subcribeText.yy_setTextHighlight(subcribeHL, range: NSRange(location: 0, length: subcribeStr.count))
  284. subcribeHL.tapAction = { [weak self] containerView, text, range, rect in
  285. self?.subscibeAction()
  286. }
  287. attr.append(subcribeText)
  288. }
  289. serviceLabel.attributedText = attr
  290. serviceLabel.textAlignment = .center
  291. }
  292. lazy var scrollView: UIScrollView = {
  293. let scrollView = UIScrollView()
  294. // scrollView.delegate = self
  295. scrollView.bounces = false
  296. scrollView.backgroundColor = UIColor.white
  297. scrollView.showsVerticalScrollIndicator = false
  298. scrollView.contentInsetAdjustmentBehavior = .never
  299. return scrollView
  300. }()
  301. lazy var vipNaviView: UIView = {
  302. let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW, QSLConst.qsl_kScreenH))
  303. view.addCorner(conrners: [.topLeft,.topRight], radius: 12.rpx)
  304. view.backgroundColor = UIColor.clear
  305. return view
  306. }()
  307. lazy var naviTitleIcon: UILabel = {
  308. let label = UILabel()
  309. label.text("超值优惠")
  310. label.textColor = .white
  311. label.mediumFont(17)
  312. label.textAlignment = .center
  313. return label
  314. }()
  315. lazy var naviResumeBtn: UIButton = {
  316. let button = UIButton()
  317. button.title("恢复购买")
  318. button.setTitleColor(.white, for: .normal)
  319. button.titleLabel?.font = UIFont.systemFont(ofSize: 11, weight: .medium)
  320. button.image(UIImage(named: "vip_resume_btn")?.withTintColor(UIColor.white))
  321. button.setImageTitleLayout(.imgLeft, spacing: 2.rpx)
  322. button.addTarget(self, action: #selector(resumeBtnAction), for: .touchUpInside)
  323. return button
  324. }()
  325. lazy var backButton: UIButton = {
  326. let button = UIButton()
  327. button.image(UIImage(named: "vip_pay_failure_close"))
  328. button.addTarget(self, action: #selector(backBtnAction), for: .touchUpInside)
  329. return button
  330. }()
  331. lazy var vipTopBg: UIImageView = {
  332. let imageView = UIImageView()
  333. imageView.image = UIImage(named: "vip_activity_top_bg")
  334. return imageView
  335. }()
  336. lazy var vipTopTitleView: UIImageView = {
  337. let imageView = UIImageView()
  338. imageView.image = UIImage(named: "vip_activity_top_title")
  339. return imageView
  340. }()
  341. lazy var vipDiamondView: UIButton = {
  342. let button = UIButton()
  343. button.image(UIImage(named: "vip_activity_top_diamond"))
  344. button.title("会员限时福利")
  345. button.font(14)
  346. button.textColor(.white)
  347. button.setImageTitleLayout(.imgLeft, spacing: 4.rpx)
  348. button.isUserInteractionEnabled = false
  349. return button
  350. }()
  351. lazy var vipContentView: UIView = {
  352. let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW, QSLConst.qsl_kScreenH))
  353. view.addCorner(conrners: [.topLeft,.topRight], radius: 12.rpx)
  354. view.backgroundColor = UIColor.white
  355. return view
  356. }()
  357. lazy var addTitleIcon: UILabel = {
  358. let label = UILabel()
  359. label.text("功能介绍")
  360. label.textColor = .hexStringColor(hexString: "#202020")
  361. label.boldFont(15)
  362. return label
  363. }()
  364. lazy var addTitleIconBg: UIView = {
  365. let view = UIView(frame: CGRectMake(0, 0, 117.rpx, 8.rpx))
  366. view.addRadius(radius: 4.rpx)
  367. // 创建渐变色层
  368. let gradientLayer = CAGradientLayer()
  369. gradientLayer.colors = [
  370. UIColor.hexStringColor(hexString: "#00DDAA",alpha: 1).cgColor,
  371. UIColor.hexStringColor(hexString: "#00DDAA",alpha: 0).cgColor
  372. ]
  373. gradientLayer.startPoint = CGPoint(x: 0, y: 0.4) // 左中
  374. gradientLayer.endPoint = CGPoint(x: 1, y: 0.4) // 右中
  375. gradientLayer.frame = view.bounds
  376. // 确保在布局变化时更新frame
  377. view.layer.insertSublayer(gradientLayer, at: 0)
  378. // 添加布局变化的监听
  379. view.layoutIfNeeded()
  380. view.layoutSubviews()
  381. return view
  382. }()
  383. lazy var cycleScrollView: GKCycleScrollView = {
  384. let cycleScrollView = GKCycleScrollView()
  385. cycleScrollView.dataSource = self
  386. cycleScrollView.delegate = self
  387. cycleScrollView.isAutoScroll = true
  388. cycleScrollView.isInfiniteLoop = true
  389. cycleScrollView.isChangeAlpha = false
  390. cycleScrollView.leftRightMargin = 12
  391. cycleScrollView.topBottomMargin = 12
  392. cycleScrollView.pageControl = pageControl
  393. cycleScrollView.reloadData()
  394. return cycleScrollView
  395. }()
  396. lazy var pageControl: GKPageControl = {
  397. let pageControl = GKPageControl()
  398. pageControl.style = .sizeDot
  399. pageControl.dotHeight = 5.rpx
  400. pageControl.dotWidth = 5.rpx
  401. pageControl.dotMargin = 4.rpx
  402. pageControl.pageIndicatorTintColor = .hexStringColor(hexString: "#EEEEEE")
  403. pageControl.currentPageIndicatorTintColor = QSLColor.themeMainColor
  404. return pageControl
  405. }()
  406. lazy var goodsCollectionView: UICollectionView = {
  407. let layout = UICollectionViewFlowLayout()
  408. layout.minimumLineSpacing = 0
  409. layout.scrollDirection = .vertical
  410. let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
  411. collectionView.backgroundColor = .white
  412. collectionView.dataSource = self
  413. collectionView.delegate = self
  414. collectionView.showsHorizontalScrollIndicator = false
  415. collectionView.bounces = false
  416. collectionView.register(cellClass: QSLActivityVipCell.self)
  417. return collectionView
  418. }()
  419. lazy var bottomView: UIView = {
  420. let view = UIView()
  421. view.backgroundColor = UIColor.white
  422. return view
  423. }()
  424. lazy var countdownView: UIView = {
  425. let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW - 24.rpx, 47.rpx))
  426. view.addCorner(conrners: [.topLeft,.topRight], radius: 30.rpx)
  427. view.backgroundColor = .hexStringColor(hexString: "#FFFED8")
  428. return view
  429. }()
  430. lazy var countdownLabel: QSLCountdownView = {
  431. let label = QSLCountdownView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW - 24.rpx, 17.rpx),type: 2)
  432. return label
  433. }()
  434. lazy var unlockBtn: UIButton = {
  435. let btn = UIButton()
  436. btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#0E5E61"), color2: .hexStringColor(hexString: "#00434E"), width: QSLConst.qsl_kScreenW - 24.rpx, height: 50.rpx, direction: .horizontal)
  437. btn.addRadius(radius: 25.rpx)
  438. btn.title("立即解锁")
  439. btn.textColor(.hexStringColor(hexString: "#FFF8EF"))
  440. btn.mediumFont(18)
  441. btn.addTarget(self, action: #selector(payBtnAction), for: .touchUpInside)
  442. return btn
  443. }()
  444. lazy var serviceLabel: YYLabel = {
  445. let label = YYLabel()
  446. label.textAlignment = .center
  447. return label
  448. }()
  449. }
  450. extension QSLActivityVipVC{
  451. func initializeView() {
  452. self.view.addSubview(scrollView)
  453. scrollView.snp.makeConstraints { make in
  454. make.top.left.equalTo(0)
  455. make.width.equalTo(QSLConst.qsl_kScreenW)
  456. make.height.equalTo(QSLConst.qsl_kScreenH)
  457. }
  458. self.view.addSubview(vipNaviView)
  459. vipNaviView.snp.makeConstraints { make in
  460. make.top.left.right.equalTo(0)
  461. make.height.equalTo(QSLConst.qsl_kNavFrameH)
  462. }
  463. vipNaviView.addSubview(backButton)
  464. backButton.snp.makeConstraints { make in
  465. make.width.equalTo(44.rpx)
  466. make.height.equalTo(44.rpx)
  467. make.left.equalTo(10.rpx)
  468. make.top.equalTo(QSLConst.qsl_kStatusBarFrameH)
  469. }
  470. vipNaviView.addSubview(naviTitleIcon)
  471. naviTitleIcon.snp.makeConstraints { make in
  472. make.centerX.equalToSuperview()
  473. make.width.equalTo(100.rpx)
  474. make.height.equalTo(20.rpx)
  475. make.centerY.equalTo(backButton.snp.centerY)
  476. }
  477. vipNaviView.addSubview(naviResumeBtn)
  478. naviResumeBtn.snp.makeConstraints { make in
  479. make.size.equalTo(CGSize(width: 70.rpx, height: 18.rpx))
  480. make.right.equalTo(-8.rpx)
  481. make.centerY.equalTo(backButton.snp.centerY)
  482. }
  483. self.scrollView.addSubview(vipTopBg)
  484. vipTopBg.snp.makeConstraints { make in
  485. make.left.top.equalTo(0)
  486. make.width.equalTo(QSLConst.qsl_kScreenW)
  487. make.height.equalTo(185.rpx)
  488. }
  489. vipTopBg.addSubview(vipTopTitleView)
  490. vipTopTitleView.snp.makeConstraints { make in
  491. make.left.equalTo(16.rpx)
  492. make.bottom.equalTo(vipTopBg.snp.bottom).offset(-16.rpx)
  493. make.height.equalTo(22.rpx)
  494. make.width.equalTo(183.rpx)
  495. }
  496. vipTopBg.addSubview(vipDiamondView)
  497. vipDiamondView.snp.makeConstraints { make in
  498. make.left.equalTo(16.rpx)
  499. make.bottom.equalTo(vipTopTitleView.snp.top).offset(-6.rpx)
  500. make.height.equalTo(20.rpx)
  501. make.width.equalTo(105.rpx)
  502. }
  503. self.scrollView.addSubview(vipContentView)
  504. vipContentView.snp.makeConstraints { make in
  505. make.top.equalTo(185.rpx)
  506. make.left.equalTo(0)
  507. make.width.equalTo(QSLConst.qsl_kScreenW)
  508. make.height.equalTo(230.rpx)
  509. }
  510. vipContentView.addSubview(addTitleIconBg)
  511. addTitleIconBg.snp.makeConstraints { make in
  512. make.size.equalTo(CGSize(width: 117.rpx, height: 8.rpx))
  513. make.left.equalTo(16.rpx)
  514. make.top.equalTo(26.rpx)
  515. }
  516. vipContentView.addSubview(addTitleIcon)
  517. addTitleIcon.snp.makeConstraints { make in
  518. make.size.equalTo(CGSize(width: 157.rpx, height: 26.rpx))
  519. make.left.equalTo(20.rpx)
  520. make.top.equalTo(12.rpx)
  521. }
  522. vipContentView.addSubview(cycleScrollView)
  523. cycleScrollView.snp.makeConstraints { make in
  524. make.left.right.equalTo(0)
  525. make.height.equalTo(150.rpx)
  526. make.top.equalTo(50.rpx)
  527. }
  528. vipContentView.addSubview(pageControl)
  529. pageControl.snp.makeConstraints { make in
  530. make.size.equalTo(CGSize(width: 68.rpx, height: 4.rpx))
  531. make.centerX.equalToSuperview()
  532. make.top.equalTo(cycleScrollView.snp.bottom).offset(17.rpx)
  533. }
  534. self.scrollView.addSubview(goodsCollectionView)
  535. goodsCollectionView.snp.makeConstraints { make in
  536. make.left.equalTo(0)
  537. make.height.equalTo(150.rpx)
  538. make.width.equalTo(QSLConst.qsl_kScreenW)
  539. make.top.equalTo(vipContentView.snp.bottom).offset(0)
  540. }
  541. self.view.addSubview(bottomView)
  542. bottomView.snp.makeConstraints { make in
  543. make.right.equalTo(-12.rpx)
  544. make.left.equalTo(12.rpx)
  545. make.height.equalTo(100.rpx)
  546. make.bottom.equalTo(-QSLConst.qsl_kTabbarBottom/2)
  547. }
  548. bottomView.addSubview(countdownView)
  549. countdownView.snp.makeConstraints { make in
  550. make.right.left.top.equalTo(0)
  551. make.height.equalTo(47.rpx)
  552. }
  553. countdownView.addSubview(countdownLabel)
  554. countdownLabel.snp.makeConstraints { make in
  555. make.left.right.equalTo(0)
  556. make.top.equalTo(5.rpx)
  557. make.height.equalTo(17.rpx)
  558. }
  559. bottomView.addSubview(unlockBtn)
  560. unlockBtn.snp.makeConstraints { make in
  561. make.right.left.equalTo(0)
  562. make.height.equalTo(50.rpx)
  563. make.top.equalTo(25.rpx)
  564. }
  565. bottomView.addSubview(serviceLabel)
  566. serviceLabel.snp.makeConstraints { make in
  567. make.right.left.equalTo(0)
  568. make.height.equalTo(17.rpx)
  569. make.bottom.equalTo(0)
  570. }
  571. }
  572. }
  573. extension QSLActivityVipVC : GKCycleScrollViewDelegate, GKCycleScrollViewDataSource{
  574. func cycleScrollView(_ cycleScrollView: GKCycleScrollView!, cellForViewAt index: Int) -> GKCycleScrollViewCell! {
  575. if let cell = cycleScrollView.dequeueReusableCell() {
  576. cell.imageView.image = UIImage(named: "vip_activity_banner_\(index+1)")
  577. return cell
  578. }
  579. let cell = GKCycleScrollViewCell()
  580. cell.imageView.image = UIImage(named: "vip_activity_banner_\(index+1)")
  581. return cell
  582. }
  583. func numberOfCells(in cycleScrollView: GKCycleScrollView!) -> Int {
  584. return 3
  585. }
  586. func sizeForCell(in cycleScrollView: GKCycleScrollView!) -> CGSize {
  587. return CGSizeMake(QSLConst.qsl_kScreenW - 90.rpx, 150.rpx);
  588. }
  589. }
  590. extension QSLActivityVipVC: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  591. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  592. return goodList.count
  593. }
  594. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  595. let cell = collectionView.dequeueReusableCell(cellType: QSLActivityVipCell.self, cellForRowAt: indexPath)
  596. let model = self.goodList[indexPath.row]
  597. if (indexPath.row == 0) {
  598. cell.config(model: model, type: .top)
  599. } else {
  600. if(self.goodList.count > 2){
  601. cell.config(model: model, type: .small)
  602. }else{
  603. cell.config(model: model, type: .big)
  604. }
  605. }
  606. return cell
  607. }
  608. func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  609. var list = [QSLGoodModel]()
  610. for index in 0..<self.goodList.count{
  611. var submodel = self.goodList[index]
  612. if(indexPath.row == index){
  613. submodel.isSelect = true
  614. self.selectGood = submodel
  615. }else{
  616. submodel.isSelect = false
  617. }
  618. list.append(submodel)
  619. }
  620. self.goodList = list
  621. self.goodsCollectionView.reloadData()
  622. self.payBtnAction()
  623. }
  624. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  625. if (indexPath.row == 0) {
  626. return CGSize(width: QSLConst.qsl_kScreenW-32.rpx, height: 112.rpx)
  627. } else {
  628. if(self.goodList.count == 2){
  629. return CGSize(width: QSLConst.qsl_kScreenW-32.rpx, height: 72.rpx)
  630. }else{
  631. return CGSize(width: (QSLConst.qsl_kScreenW-50.rpx)/2.0, height: 112.rpx)
  632. }
  633. }
  634. }
  635. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
  636. return UIEdgeInsets(top: 0, left: 16.rpx, bottom: 0, right: 16.rpx)
  637. }
  638. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  639. return 10.rpx
  640. }
  641. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  642. if(self.goodList.count == 2){
  643. return 10.rpx
  644. }else{
  645. return 16.rpx
  646. }
  647. }
  648. }
  649. extension QSLActivityVipVC : QSLCountdownManagerDelegate{
  650. func countdownManager(_ manager: QSLCountdownManager, didUpdateCountdown type: QSLCountdownType, remainingSeconds: Int) {
  651. // 处理倒计时更新
  652. if type == .homeProduct {
  653. let totalSeconds = remainingSeconds / 1000
  654. let minutes = totalSeconds / 60
  655. let seconds = totalSeconds % 60
  656. var milliseconds = remainingSeconds % 1000
  657. if(milliseconds <= 1){
  658. milliseconds = 0
  659. }
  660. // 格式:MM:SS:SSS(例如 "14:59:500")
  661. let timeString = String(format: "%02d : %02d : %03d", minutes, seconds, milliseconds)
  662. self.countdownLabel.updateCountdownText(timeString)
  663. }
  664. }
  665. func countdownManager(_ manager: QSLCountdownManager, didFinishCountdown type: QSLCountdownType) {
  666. // 处理倒计时结束
  667. if type == .homeProduct {
  668. }
  669. }
  670. }