QSLVipController.swift 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. //
  2. // QSLVipController.swift
  3. // QuickSearchLocation
  4. //
  5. // Created by Destiny on 2024/11/27.
  6. //
  7. import UIKit
  8. import YYText
  9. enum QSLVipJumpType: Int {
  10. case homeRoad // 定位查看轨迹
  11. case add // 添加好友
  12. case friendRoad // 好友列表查看轨迹
  13. case contact // 添加紧急联系人
  14. case mine //
  15. }
  16. class QSLVipController: QSLBaseController {
  17. struct UX {
  18. static let mostCellHeight = 113.0.rpx
  19. static let collectionRowHeight = 137.0.rpx
  20. static let goodsBgHeight = 54.rpx + UX.mostCellHeight + 20.rpx
  21. }
  22. var type: QSLVipJumpType?
  23. var goodList: [QSLGoodModel] = [QSLGoodModel]()
  24. var selectGood: QSLGoodModel? {
  25. didSet {
  26. updateSelectGoodUI()
  27. }
  28. }
  29. lazy var vipBg: UIImageView = {
  30. let imageView = UIImageView()
  31. imageView.image = UIImage(named: "vip_bg")
  32. return imageView
  33. }()
  34. lazy var backButton: UIButton = {
  35. let button = UIButton()
  36. button.image(UIImage(named: "public_back_btn_white"))
  37. button.title("会员中心")
  38. button.mediumFont(17)
  39. button.textColor(.white)
  40. button.setImageTitleLayout(.imgLeft, spacing: 4.rpx)
  41. button.addTarget(self, action: #selector(backBtnAction), for: .touchUpInside)
  42. return button
  43. }()
  44. lazy var peopleCountView: UIView = {
  45. let view = UIView()
  46. view.layer.cornerRadius = 12.rpx
  47. view.layer.borderColor = UIColor.white.withAlphaComponent(0.16).cgColor
  48. view.layer.borderWidth = 1.rpx
  49. return view
  50. }()
  51. lazy var peopleAvatarImageView: UIImageView = {
  52. let imageView = UIImageView()
  53. imageView.image = UIImage(named: "vip_avatars_icon")
  54. return imageView
  55. }()
  56. lazy var peopleCountLabel: UILabel = {
  57. let label = UILabel()
  58. label.text("1456488人 已开通VIP")
  59. label.color("#FFE6C0")
  60. label.font(12)
  61. return label
  62. }()
  63. lazy var scrollView: UIScrollView = {
  64. let scrollView = UIScrollView()
  65. // scrollView.delegate = self
  66. scrollView.bounces = false
  67. scrollView.showsVerticalScrollIndicator = false
  68. scrollView.contentInsetAdjustmentBehavior = .never
  69. return scrollView
  70. }()
  71. lazy var cardBannerImageView: UIImageView = {
  72. let imageView = UIImageView()
  73. imageView.image = UIImage(named: "vip_banner_card")
  74. return imageView
  75. }()
  76. lazy var vipTimeLabel: UILabel = {
  77. let label = UILabel()
  78. label.text("升级VIP会员,解锁全部功能")
  79. label.font(13)
  80. label.textColor = .hexStringColor(hexString: "#AF7655")
  81. return label
  82. }()
  83. lazy var funcBannerImageView: UIImageView = {
  84. let imageView = UIImageView()
  85. imageView.image = UIImage(named: "vip_banner_func")
  86. return imageView
  87. }()
  88. lazy var mainView: UIView = {
  89. let view = UIView()
  90. view.backgroundColor = QSLColor.backGroundColor
  91. view.addRadius(radius: 12.rpx)
  92. return view
  93. }()
  94. lazy var goodsBgView: UIView = {
  95. let view = UIView()
  96. view.gradientBackgroundColor(color1: .hexStringColor(hexString: "#FFF8F2"), color2: .hexStringColor(hexString: "#FFFFFF"), width: QSLConst.qsl_kScreenW, height: UX.goodsBgHeight, direction: .vertical)
  97. return view
  98. }()
  99. lazy var vipGoodsTitleIcon: UIImageView = {
  100. let imageView = UIImageView()
  101. imageView.image = UIImage(named: "vip_title_icon")
  102. return imageView
  103. }()
  104. lazy var resumeBtn: UIButton = {
  105. let button = UIButton()
  106. button.title("恢复购买")
  107. button.setTitleColor(.hexStringColor(hexString: "#000000").withAlphaComponent(0.5), for: .normal)
  108. button.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .medium)
  109. button.image(UIImage(named: "vip_resume_btn"))
  110. button.setImageTitleLayout(.imgLeft, spacing: 2.rpx)
  111. button.addTarget(self, action: #selector(resumeBtnAction), for: .touchUpInside)
  112. return button
  113. }()
  114. lazy var mostCell: QSLVipMostGoodCell = {
  115. let cell = QSLVipMostGoodCell()
  116. cell.isUserInteractionEnabled = true
  117. let tap = UITapGestureRecognizer(target: self, action: #selector(firstCellClickAction))
  118. cell.addGestureRecognizer(tap)
  119. return cell
  120. }()
  121. lazy var goodsCollectionView: UICollectionView = {
  122. let layout = UICollectionViewFlowLayout()
  123. layout.minimumLineSpacing = 0
  124. layout.scrollDirection = .vertical
  125. let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
  126. collectionView.backgroundColor = .clear
  127. collectionView.dataSource = self
  128. collectionView.delegate = self
  129. collectionView.showsHorizontalScrollIndicator = false
  130. collectionView.bounces = false
  131. collectionView.register(cellClass: QSLVipGoodCollectionViewCell.self)
  132. return collectionView
  133. }()
  134. lazy var selectBtn: UIButton = {
  135. let btn = UIButton()
  136. btn.image(UIImage(named: "public_select_btn_false"), .normal)
  137. btn.image(UIImage(named: "public_select_btn_true"), .selected)
  138. btn.addTarget(self, action: #selector(selectBtnAction), for: .touchUpInside)
  139. return btn
  140. }()
  141. lazy var serviceLabel: YYLabel = {
  142. let label = YYLabel()
  143. let attr = NSMutableAttributedString()
  144. let firstAttr = NSMutableAttributedString(string: "购买即同意")
  145. firstAttr.font(10)
  146. firstAttr.color(.hexStringColor(hexString: "#A7A7A7"))
  147. attr.append(firstAttr)
  148. let blankAttr = NSMutableAttributedString(string: " ")
  149. blankAttr.font(10)
  150. attr.append(blankAttr)
  151. let privacyHL = YYTextHighlight()
  152. var privacyStr = "《隐私权政策》"
  153. let privacyText = NSMutableAttributedString(string: privacyStr)
  154. privacyText.font(10)
  155. privacyText.color(.hexStringColor(hexString: "#E7B983"))
  156. privacyText.yy_setTextHighlight(privacyHL, range: NSRange(location: 0, length: privacyStr.count))
  157. privacyHL.tapAction = { [weak self] containerView, text, range, rect in
  158. self?.privacyAction()
  159. }
  160. attr.append(privacyText)
  161. attr.append(blankAttr)
  162. let serviceHL = YYTextHighlight()
  163. var serviceStr = "《用户协议》"
  164. let serviceText = NSMutableAttributedString(string: serviceStr)
  165. serviceText.font(10)
  166. serviceText.color(.hexStringColor(hexString: "#E7B983"))
  167. serviceText.yy_setTextHighlight(serviceHL, range: NSRange(location: 0, length: serviceStr.count))
  168. serviceHL.tapAction = { [weak self] containerView, text, range, rect in
  169. self?.serviceAction()
  170. }
  171. attr.append(serviceText)
  172. // attr.append(blankAttr)
  173. //
  174. // let andAttr = NSMutableAttributedString(string: "和")
  175. // andAttr.font(10)
  176. // andAttr.color(.hexStringColor(hexString: "#A7A7A7"))
  177. // attr.append(andAttr)
  178. //
  179. // attr.append(blankAttr)
  180. // let subcribeHL = YYTextHighlight()
  181. // var subcribeStr = "《续订说明》"
  182. //
  183. // let subcribeText = NSMutableAttributedString(string: subcribeStr)
  184. // subcribeText.font(10)
  185. // subcribeText.color(.hexStringColor(hexString: "#E7B983"))
  186. // subcribeText.yy_setTextHighlight(subcribeHL, range: NSRange(location: 0, length: subcribeStr.count))
  187. // subcribeHL.tapAction = { [weak self] containerView, text, range, rect in
  188. // self?.subscibeAction()
  189. // }
  190. //
  191. // attr.append(subcribeText)
  192. label.attributedText = attr
  193. return label
  194. }()
  195. lazy var commentView: UIView = {
  196. let view = UIView()
  197. view.backgroundColor = .white
  198. return view
  199. }()
  200. lazy var commentTitleIcon: UIImageView = {
  201. let imageView = UIImageView()
  202. imageView.image = UIImage(named: "vip_comment_title_icon")
  203. return imageView
  204. }()
  205. lazy var comment1: QSLVipCommentCellView = {
  206. let view = QSLVipCommentCellView()
  207. view.config(name: "用户189****7913", comment: "上班没时间,远程遛娃,非常方便很好用。")
  208. return view
  209. }()
  210. lazy var comment2: QSLVipCommentCellView = {
  211. let view = QSLVipCommentCellView()
  212. view.config(name: "用户189****7913", comment: "用了之后,才发现真的可以找到他。")
  213. return view
  214. }()
  215. lazy var comment3: QSLVipCommentCellView = {
  216. let view = QSLVipCommentCellView()
  217. view.config(name: "用户189****7913", comment: "轨迹很准,一目了然,奶奶出门遇到危险直接一键报警,我就收到信息了")
  218. return view
  219. }()
  220. lazy var tipTitleLabel: UILabel = {
  221. let label = UILabel()
  222. label.text("温馨提示")
  223. label.font(12)
  224. label.textColor = .hexStringColor(hexString: "#000000").withAlphaComponent(0.8)
  225. return label
  226. }()
  227. // lazy var tipContentLabel: UILabel = {
  228. //
  229. // let label = UILabel()
  230. // label.numberOfLines = 0
  231. // label.text("1 订阅后会从您的iTunes账户中扣除相关费用。如需取消续订,请在当前订阅周期结束前,至少24小时内通过手机“账户设置”的订阅管理关闭自动续费功能。\n2 未成年人请在监护者的陪同下进行购买\n3 购买后不支持退款,请仔细审阅《隐私权政策》《用户协议》和《续订说明》")
  232. // label.font(10)
  233. // label.textColor = .hexStringColor(hexString: "#000000").withAlphaComponent(0.6)
  234. // label.changeLineSpace(space: 5)
  235. // return label
  236. // }()
  237. lazy var bottomView: UIView = {
  238. let view = UIView()
  239. view.gradientBackgroundColor(color1: .hexStringColor(hexString: "#00434E"), color2: .hexStringColor(hexString: "#0E5E61"), width: QSLConst.qsl_kScreenW - 24.rpx, height: 50.rpx, direction: .horizontal)
  240. view.addRadius(radius: 25.rpx)
  241. return view
  242. }()
  243. lazy var unlockBtn: UIButton = {
  244. let btn = UIButton()
  245. btn.setBackgroundImage(UIImage(named: "vip_unlock_btn_bg"), for: .normal)
  246. btn.title("立即解锁")
  247. btn.textColor(.hexStringColor(hexString: "#9B3800"))
  248. btn.mediumFont(18)
  249. btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 30.rpx, bottom: 0, right: 0)
  250. btn.addTarget(self, action: #selector(unlockBtnAction), for: .touchUpInside)
  251. return btn
  252. }()
  253. lazy var priceIconLabel: UILabel = {
  254. let label = UILabel()
  255. label.text("¥")
  256. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  257. label.font(14)
  258. return label
  259. }()
  260. lazy var priceLabel: UILabel = {
  261. let label = UILabel()
  262. label.text("168")
  263. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  264. label.font(24)
  265. return label
  266. }()
  267. lazy var goodTypeLabel: UILabel = {
  268. let label = UILabel()
  269. label.text("/")
  270. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  271. label.font(12)
  272. return label
  273. }()
  274. lazy var goodOriginalPriceLabel: UILabel = {
  275. let label = UILabel()
  276. label.text("原价228")
  277. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  278. label.font(12)
  279. label.centerLineText(lineValue: 1, underlineColor: .hexStringColor(hexString: "#FFF8EF"))
  280. return label
  281. }()
  282. override func viewDidLoad() {
  283. super.viewDidLoad()
  284. initializeView()
  285. updateUI()
  286. requestItemList()
  287. calculateBuyCount()
  288. if let type = self.type {
  289. switch type {
  290. case .homeRoad:
  291. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1001])
  292. case .add:
  293. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1002])
  294. case .friendRoad:
  295. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1003])
  296. case .contact:
  297. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1004])
  298. case .mine:
  299. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1006])
  300. }
  301. }
  302. }
  303. }
  304. extension QSLVipController {
  305. @objc func privacyAction() {
  306. let vc = QSLWebViewController()
  307. vc.webUrl = QSLConfig.AppPrivacyAgreementLink
  308. vc.title = "隐私政策"
  309. self.navigationController?.pushViewController(vc, animated: true)
  310. }
  311. @objc func serviceAction() {
  312. let vc = QSLWebViewController()
  313. vc.webUrl = QSLConfig.AppServiceAgreementLink
  314. vc.title = "服务协议"
  315. self.navigationController?.pushViewController(vc, animated: true)
  316. }
  317. @objc func subscibeAction() {
  318. let vc = QSLWebViewController()
  319. vc.webUrl = QSLConfig.AppSubscibeAgreementLink
  320. vc.title = "续订说明"
  321. self.navigationController?.pushViewController(vc, animated: true)
  322. }
  323. @objc func selectBtnAction() {
  324. selectBtn.isSelected = !selectBtn.isSelected
  325. }
  326. // 恢复按钮点击
  327. @objc func resumeBtnAction() {
  328. let memberModel = QSLBaseManager.shared.userModel.memberModel
  329. let expired = memberModel.expired
  330. if !expired {
  331. QSLLoading.success(text: "您已经在订阅中,无需恢复")
  332. return
  333. }
  334. QSLLoading.show()
  335. QSLVipManager.shared.restoreAction { isSuccess in
  336. QSLVipManager.shared.isPaying = false
  337. if isSuccess {
  338. QSLNetwork().request(.userMember(dict: [:])) { response in
  339. let model = response.mapObject(QSLMemberModel.self, modelKey: "data")
  340. QSLBaseManager.shared.userModel.memberModel = model
  341. if model.expired {
  342. QSLBaseManager.shared.saveVipExpiredTime(time: 0)
  343. } else {
  344. QSLBaseManager.shared.saveVipExpiredTime(time: model.endTimestamp)
  345. }
  346. QSLBaseManager.shared.saveUserId(id: model.userId)
  347. if model.endTimestamp > memberModel.endTimestamp {
  348. QSLLoading.success(text: "恢复成功")
  349. // 支付成功通知
  350. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  351. self.navigationController?.popViewController(animated: true)
  352. }
  353. } else {
  354. QSLLoading.error(text: "没有可供恢复的订阅")
  355. }
  356. } fail: { code, error in
  357. QSLLoading.error(text: "没有可供恢复的订阅")
  358. }
  359. } else {
  360. QSLLoading.error(text: "没有可供恢复的订阅")
  361. }
  362. }
  363. }
  364. // 支付按钮点击
  365. @objc func unlockBtnAction() {
  366. switch self.selectGood?.level {
  367. case 100 :
  368. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1006])
  369. break
  370. case 700:
  371. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1005])
  372. break;
  373. case 3100:
  374. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1004])
  375. break;
  376. case 9200:
  377. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1003])
  378. break;
  379. case 36600:
  380. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1002])
  381. break;
  382. case 3660000:
  383. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1001])
  384. break;
  385. default:
  386. break;
  387. }
  388. // if !selectBtn.isSelected {
  389. // self.view.toast(text: "请先同意《隐私权政策》和《用户协议》")
  390. // return
  391. // }
  392. let memberModel = QSLBaseManager.shared.userModel.memberModel
  393. if let subscriptionExpired = memberModel.subscriptionExpired, !subscriptionExpired {
  394. self.view.toast(text: "你已经订阅了")
  395. return
  396. }
  397. if goodList.count > 0, let selectGood = self.selectGood {
  398. QSLLoading.show()
  399. QSLVipManager.shared.startPay(goods: selectGood) { status, outTradeNo in
  400. QSLVipManager.shared.isPaying = false
  401. if status == .success {
  402. QSLLoading.success(text: "支付成功")
  403. // 引力传递支付事件
  404. if let selectGood = self.selectGood {
  405. gravityInstance?.trackPayEvent(withAmount: Int32(selectGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: selectGood.name, withPayMethod: "apple")
  406. }
  407. if let type = self.type {
  408. switch type {
  409. case .homeRoad:
  410. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1001])
  411. case .add:
  412. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1002])
  413. case .friendRoad:
  414. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1003])
  415. case .contact:
  416. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1004])
  417. case .mine:
  418. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1006])
  419. }
  420. }
  421. switch self.selectGood?.level {
  422. case 100 :
  423. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 1])
  424. break
  425. case 700:
  426. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 5])
  427. break;
  428. case 3100:
  429. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 9])
  430. break;
  431. case 9200:
  432. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 13])
  433. break;
  434. case 36600:
  435. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 17])
  436. break;
  437. case 3660000:
  438. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 21])
  439. break;
  440. default:
  441. break;
  442. }
  443. DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
  444. self.navigationController?.popViewController(animated: true)
  445. NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
  446. }
  447. } else if status == .cancel {
  448. QSLLoading.error(text: "支付取消")
  449. } else if status == .fail {
  450. gravityInstance?.track(QSLGravityConst.vip_fail)
  451. QSLLoading.error(text: "支付失败")
  452. } else if status == .searchFail {
  453. QSLLoading.error(text: "查询订单失败,请稍后重试")
  454. }
  455. }
  456. }
  457. }
  458. @objc func firstCellClickAction() {
  459. for i in 0..<self.goodList.count {
  460. self.goodList[i].isSelect = false
  461. }
  462. if self.goodList.count > 0 {
  463. self.goodList[0].isSelect = true
  464. self.selectGood = self.goodList[0]
  465. self.mostCell.config(model: self.goodList[0])
  466. }
  467. switch self.selectGood?.level {
  468. case 100 :
  469. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
  470. break
  471. case 700:
  472. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
  473. break;
  474. case 3100:
  475. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
  476. break;
  477. case 9200:
  478. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
  479. break;
  480. case 36600:
  481. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
  482. break;
  483. case 3660000:
  484. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
  485. break;
  486. default:
  487. break;
  488. }
  489. self.goodsCollectionView.reloadData()
  490. }
  491. }
  492. extension QSLVipController {
  493. // 请求商品列表
  494. func requestItemList() {
  495. QSLNetwork().request(.vipItemList(dict: ["itemListType": 2])) { response in
  496. let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
  497. self.goodList = list
  498. if self.goodList.count > 0 {
  499. self.goodList[0].isSelect = true
  500. self.selectGood = self.goodList[0]
  501. self.mostCell.config(model: self.goodList[0])
  502. let row = ceil(Double(self.goodList.count - 1) / 3.0)
  503. let height = UX.goodsBgHeight + (row * UX.collectionRowHeight)
  504. self.goodsBgView.gradientBackgroundColor(color1: .hexStringColor(hexString: "#FFF8F2"), color2: .hexStringColor(hexString: "#FFFFFF"), width: QSLConst.qsl_kScreenW, height: height, direction: .vertical)
  505. self.goodsBgView.snp.updateConstraints { make in
  506. make.height.equalTo(height)
  507. }
  508. self.scrollView.snp.makeConstraints { make in
  509. make.bottom.equalTo(self.mainView)
  510. }
  511. }
  512. self.goodsCollectionView.reloadData()
  513. } fail: { code, error in
  514. self.view.toast(text: "加载商品列表失败")
  515. }
  516. }
  517. // 计算购买人数
  518. func calculateBuyCount() {
  519. var num = 145883
  520. if let localNum = UserDefaults.standard.value(forKey: QSLConfig.user_default_local_buy_count) as? Int {
  521. num = localNum
  522. }
  523. let randomAddCount = Int.random(in: 1...10)
  524. num = num + randomAddCount
  525. UserDefaults.standard.setValue(num, forKey: QSLConfig.user_default_local_buy_count)
  526. self.peopleCountLabel.text("\(num)人 已开通VIP")
  527. }
  528. }
  529. // MARK: - 设置 CollectionView
  530. extension QSLVipController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  531. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  532. return goodList.count - 1
  533. }
  534. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  535. let cell = collectionView.dequeueReusableCell(cellType: QSLVipGoodCollectionViewCell.self, cellForRowAt: indexPath)
  536. let model = self.goodList[indexPath.row + 1]
  537. if self.goodList.count - 1 == 2 {
  538. cell.config(model: model, type: .big)
  539. } else {
  540. cell.config(model: model, type: .small)
  541. }
  542. return cell
  543. }
  544. func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  545. for i in 0..<self.goodList.count {
  546. self.goodList[i].isSelect = false
  547. }
  548. if self.goodList.count > 0 {
  549. self.goodList[indexPath.row + 1].isSelect = true
  550. self.selectGood = self.goodList[indexPath.row + 1]
  551. self.mostCell.config(model: self.goodList[0])
  552. }
  553. switch self.selectGood?.level {
  554. case 100 :
  555. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
  556. break
  557. case 700:
  558. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
  559. break;
  560. case 3100:
  561. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
  562. break;
  563. case 9200:
  564. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
  565. break;
  566. case 36600:
  567. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
  568. break;
  569. case 3660000:
  570. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
  571. break;
  572. default:
  573. break;
  574. }
  575. self.goodsCollectionView.reloadData()
  576. }
  577. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  578. var width = (QSLConst.qsl_kScreenW - 42.0.rpx) / 3.0
  579. if self.goodList.count - 1 == 2 {
  580. width = (QSLConst.qsl_kScreenW - 36.0.rpx) / 2.0
  581. }
  582. return CGSize(width: width, height: 134.0.rpx)
  583. }
  584. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  585. return 6.rpx
  586. }
  587. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  588. return 3.rpx
  589. }
  590. }
  591. extension QSLVipController {
  592. func updateUI() {
  593. if QSLBaseManager.shared.isLogin() && QSLBaseManager.shared.isVip() {
  594. let model = QSLBaseManager.shared.userModel.memberModel
  595. if model.permanent {
  596. self.vipTimeLabel.text("您已是尊贵的永久会员")
  597. self.bottomView.isHidden = true
  598. } else {
  599. let level = model.memberLevelString()
  600. let endTime = model.endTimestampString()
  601. self.vipTimeLabel.text("\(level):\(endTime)到期")
  602. }
  603. } else {
  604. self.vipTimeLabel.text("升级VIP会员,解锁全部功能")
  605. }
  606. }
  607. func updateSelectGoodUI() {
  608. var priceText = ""
  609. var originalPriceText = ""
  610. if let selectGood = self.selectGood {
  611. if selectGood.amount.truncatingRemainder(dividingBy: 100) == 0 {
  612. priceText = "\(Int(selectGood.amount / 100))"
  613. } else {
  614. priceText = String(format: "%.2lf", selectGood.amount / 100 )
  615. }
  616. if selectGood.originalAmount.truncatingRemainder(dividingBy: 100) == 0 {
  617. originalPriceText = "\(Int(selectGood.originalAmount / 100))"
  618. } else {
  619. originalPriceText = String(format: "%.2lf", selectGood.originalAmount / 100 )
  620. }
  621. }
  622. self.priceLabel.text(priceText)
  623. // self.goodTypeLabel.text("/ \(self.selectGood?.name ?? "")")
  624. self.goodOriginalPriceLabel.text("原价\(originalPriceText)")
  625. }
  626. func initializeView() {
  627. self.view.addSubview(vipBg)
  628. vipBg.snp.makeConstraints { make in
  629. make.left.top.right.equalTo(0)
  630. }
  631. self.view.addSubview(backButton)
  632. backButton.snp.makeConstraints { make in
  633. make.size.equalTo(100.rpx)
  634. make.height.equalTo(25.rpx)
  635. make.left.equalTo(12.rpx)
  636. make.top.equalTo(QSLConst.qsl_kStatusBarFrameH)
  637. }
  638. self.view.addSubview(peopleCountView)
  639. peopleCountView.snp.makeConstraints { make in
  640. make.size.equalTo(CGSize(width: 212.rpx, height: 24.rpx))
  641. make.right.equalTo(-13.rpx)
  642. make.centerY.equalTo(backButton.snp.centerY)
  643. }
  644. peopleCountView.addSubview(peopleAvatarImageView)
  645. peopleAvatarImageView.snp.makeConstraints { make in
  646. make.size.equalTo(CGSize(width: 72.rpx, height: 16.6.rpx))
  647. make.left.equalTo(3.rpx)
  648. make.centerY.equalTo(peopleCountView.snp.centerY)
  649. }
  650. peopleCountView.addSubview(peopleCountLabel)
  651. peopleCountLabel.snp.makeConstraints { make in
  652. make.left.equalTo(peopleAvatarImageView.snp.right).offset(7.rpx)
  653. make.centerY.equalTo(peopleCountView.snp.centerY)
  654. }
  655. self.view.addSubview(scrollView)
  656. scrollView.snp.makeConstraints { make in
  657. make.left.right.equalTo(0)
  658. make.top.equalTo(QSLConst.qsl_kNavFrameH)
  659. make.bottom.equalTo(0)
  660. }
  661. scrollView.addSubview(cardBannerImageView)
  662. cardBannerImageView.snp.makeConstraints { make in
  663. make.top.equalTo(0)
  664. make.centerX.equalToSuperview()
  665. make.width.equalTo(336.rpx)
  666. make.height.equalTo(108.rpx)
  667. }
  668. cardBannerImageView.addSubview(vipTimeLabel)
  669. vipTimeLabel.snp.makeConstraints { make in
  670. make.left.equalTo(23.rpx)
  671. make.bottom.equalTo(-19.rpx)
  672. }
  673. scrollView.addSubview(funcBannerImageView)
  674. funcBannerImageView.snp.makeConstraints { make in
  675. make.size.equalTo(CGSize(width: 336.rpx, height: 172.rpx))
  676. make.centerX.equalToSuperview()
  677. make.top.equalTo(cardBannerImageView.snp.bottom).offset(14.rpx)
  678. }
  679. scrollView.addSubview(mainView)
  680. mainView.snp.makeConstraints { make in
  681. make.left.right.equalTo(0)
  682. make.top.equalTo(funcBannerImageView.snp.bottom).offset(-24.rpx)
  683. make.width.equalTo(QSLConst.qsl_kScreenW)
  684. // make.height.equalTo(800.rpx)
  685. }
  686. let goodsBgHeight = 54.rpx + UX.mostCellHeight
  687. mainView.addSubview(goodsBgView)
  688. goodsBgView.snp.makeConstraints { make in
  689. make.top.left.right.equalTo(0)
  690. make.width.equalTo(QSLConst.qsl_kScreenW)
  691. make.height.equalTo(goodsBgHeight)
  692. }
  693. goodsBgView.addSubview(vipGoodsTitleIcon)
  694. vipGoodsTitleIcon.snp.makeConstraints { make in
  695. make.size.equalTo(CGSize(width: 117.rpx, height: 26.rpx))
  696. make.left.equalTo(20.rpx)
  697. make.top.equalTo(16.rpx)
  698. }
  699. goodsBgView.addSubview(resumeBtn)
  700. resumeBtn.snp.makeConstraints { make in
  701. make.size.equalTo(CGSize(width: 75.rpx, height: 16.rpx))
  702. make.right.equalTo(-18.rpx)
  703. make.centerY.equalTo(vipGoodsTitleIcon.snp.centerY)
  704. }
  705. goodsBgView.addSubview(mostCell)
  706. mostCell.snp.makeConstraints { make in
  707. make.left.equalTo(12.rpx)
  708. make.right.equalTo(-16.rpx)
  709. make.height.equalTo(113.rpx)
  710. make.top.equalTo(vipGoodsTitleIcon.snp.bottom).offset(10.rpx)
  711. }
  712. goodsBgView.addSubview(goodsCollectionView)
  713. goodsCollectionView.snp.makeConstraints { make in
  714. make.left.equalTo(12.rpx)
  715. make.right.equalTo(-18.rpx)
  716. make.bottom.equalTo(-20.rpx)
  717. make.top.equalTo(mostCell.snp.bottom).offset(3.rpx)
  718. }
  719. // goodsBgView.addSubview(selectBtn)
  720. // selectBtn.snp.makeConstraints { make in
  721. // make.size.equalTo(CGSize(width: 12.rpx, height: 12.rpx))
  722. // make.left.equalTo(23.rpx)
  723. // make.top.equalTo(goodsCollectionView.snp.bottom).offset(16.rpx)
  724. // }
  725. //
  726. // goodsBgView.addSubview(serviceLabel)
  727. // serviceLabel.snp.makeConstraints { make in
  728. // make.left.equalTo(selectBtn.snp.right).offset(2.rpx)
  729. // make.centerY.equalTo(selectBtn.snp.centerY)
  730. // }
  731. mainView.addSubview(commentView)
  732. commentView.snp.makeConstraints { make in
  733. make.left.right.equalTo(0)
  734. make.top.equalTo(goodsBgView.snp.bottom).offset(8.rpx)
  735. make.height.equalTo(525.rpx + QSLConst.qsl_kTabbarBottom)
  736. make.bottom.equalTo(0)
  737. }
  738. commentView.addSubview(commentTitleIcon)
  739. commentTitleIcon.snp.makeConstraints { make in
  740. make.size.equalTo(CGSize(width: 83.rpx, height: 26.rpx))
  741. make.top.equalTo(16.rpx)
  742. make.left.equalTo(12.rpx)
  743. }
  744. let commentHeight1 = "上班没时间,远程遛娃,非常方便很好用。".heightAccording(width: QSLConst.qsl_kScreenW - 52.rpx - 12.rpx, font: .textF(15), lineSpacing: 2) + 35.rpx
  745. commentView.addSubview(comment1)
  746. comment1.snp.makeConstraints { make in
  747. make.left.right.equalTo(0)
  748. make.top.equalTo(commentTitleIcon.snp.bottom).offset(16.rpx)
  749. make.height.equalTo(commentHeight1)
  750. }
  751. let commentHeight2 = "用了之后,才发现真的可以找到他。".heightAccording(width: QSLConst.qsl_kScreenW - 52.rpx - 12.rpx, font: .textF(15), lineSpacing: 2) + 35.rpx
  752. commentView.addSubview(comment2)
  753. comment2.snp.makeConstraints { make in
  754. make.left.right.equalTo(0)
  755. make.top.equalTo(comment1.snp.bottom).offset(30.rpx)
  756. make.height.equalTo(commentHeight2)
  757. }
  758. let commentHeight3 = "轨迹很准,一目了然,奶奶出门遇到危险直接一键报警,我就收到信息了".heightAccording(width: QSLConst.qsl_kScreenW - 52.rpx - 12.rpx, font: .textF(15), lineSpacing: 2) + 35.rpx
  759. commentView.addSubview(comment3)
  760. comment3.snp.makeConstraints { make in
  761. make.left.right.equalTo(0)
  762. make.top.equalTo(comment2.snp.bottom).offset(30.rpx)
  763. make.height.equalTo(commentHeight3)
  764. }
  765. // commentView.addSubview(tipTitleLabel)
  766. // commentView.addSubview(tipContentLabel)
  767. // tipTitleLabel.snp.makeConstraints { make in
  768. // make.left.equalTo(16)
  769. // make.top.equalTo(comment3.snp.bottom).offset(28)
  770. // }
  771. // tipContentLabel.snp.makeConstraints { make in
  772. // make.left.equalTo(16)
  773. // make.right.equalTo(-16)
  774. // make.top.equalTo(tipTitleLabel.snp.bottom).offset(11)
  775. // }
  776. commentView.addSubview(serviceLabel)
  777. serviceLabel.snp.makeConstraints { make in
  778. make.left.equalTo(16)
  779. make.top.equalTo(comment3.snp.bottom).offset(28.rpx)
  780. }
  781. scrollView.snp.makeConstraints { make in
  782. make.bottom.equalTo(mainView)
  783. }
  784. self.view.addSubview(bottomView)
  785. bottomView.snp.makeConstraints { make in
  786. make.left.equalTo(12.rpx)
  787. make.right.equalTo(-12.rpx)
  788. make.bottom.equalTo(-QSLConst.qsl_kTabbarBottom)
  789. make.height.equalTo(50.rpx)
  790. }
  791. bottomView.addSubview(unlockBtn)
  792. unlockBtn.snp.makeConstraints { make in
  793. make.right.top.bottom.equalTo(0)
  794. make.width.equalTo(165.rpx)
  795. }
  796. bottomView.addSubview(priceIconLabel)
  797. priceIconLabel.snp.makeConstraints { make in
  798. make.left.equalTo(20.rpx)
  799. make.bottom.equalTo(-12.rpx)
  800. }
  801. bottomView.addSubview(priceLabel)
  802. priceLabel.snp.makeConstraints { make in
  803. make.left.equalTo(priceIconLabel.snp.right).offset(2.rpx)
  804. make.bottom.equalTo(-10.rpx)
  805. }
  806. bottomView.addSubview(goodTypeLabel)
  807. goodTypeLabel.snp.makeConstraints { make in
  808. make.left.equalTo(priceLabel.snp.right).offset(2.rpx)
  809. make.bottom.equalTo(-14.rpx)
  810. }
  811. bottomView.addSubview(goodOriginalPriceLabel)
  812. goodOriginalPriceLabel.snp.makeConstraints { make in
  813. make.left.equalTo(goodTypeLabel.snp.right).offset(2.rpx)
  814. make.centerY.equalTo(goodTypeLabel.snp.centerY)
  815. }
  816. }
  817. }