QSLVipController.swift 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213
  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. case guideComments // 引导评论
  16. }
  17. class QSLVipController: QSLBaseController {
  18. // 购买人数
  19. static let record_non_member_clicks_to_claim = "RECORD_NON_MEMBER_CLIKS_CLAIM"
  20. struct UX {
  21. static let mostCellHeight = 113.0.rpx
  22. static let collectionRowHeight = 137.0.rpx
  23. static let goodsBgHeight = 54.rpx + UX.mostCellHeight + 20.rpx
  24. }
  25. var type: QSLVipJumpType?
  26. var isCancel = false
  27. var finishHandler: ((Bool) -> Void)?
  28. var goodList: [QSLGoodModel] = [QSLGoodModel]()
  29. ///是否是订阅的产品
  30. //var is
  31. var selectGood: QSLGoodModel? {
  32. didSet {
  33. updateSelectGoodUI()
  34. }
  35. }
  36. lazy var vipBg: UIImageView = {
  37. let imageView = UIImageView()
  38. imageView.image = UIImage(named: "vip_bg")
  39. return imageView
  40. }()
  41. lazy var backButton: UIButton = {
  42. let button = UIButton()
  43. button.image(UIImage(named: "public_back_btn_white"))
  44. button.title("会员中心")
  45. button.mediumFont(17)
  46. button.textColor(.white)
  47. button.setImageTitleLayout(.imgLeft, spacing: 4.rpx)
  48. button.addTarget(self, action: #selector(backBtnAction), for: .touchUpInside)
  49. return button
  50. }()
  51. lazy var peopleCountView: UIView = {
  52. let view = UIView()
  53. view.layer.cornerRadius = 12.rpx
  54. view.layer.borderColor = UIColor.white.withAlphaComponent(0.16).cgColor
  55. view.layer.borderWidth = 1.rpx
  56. return view
  57. }()
  58. lazy var peopleAvatarImageView: UIImageView = {
  59. let imageView = UIImageView()
  60. imageView.image = UIImage(named: "vip_avatars_icon")
  61. return imageView
  62. }()
  63. lazy var peopleCountLabel: UILabel = {
  64. let label = UILabel()
  65. label.text("1456488人 已开通VIP")
  66. label.color("#FFE6C0")
  67. label.font(12)
  68. return label
  69. }()
  70. lazy var scrollView: UIScrollView = {
  71. let scrollView = UIScrollView()
  72. // scrollView.delegate = self
  73. scrollView.bounces = false
  74. scrollView.showsVerticalScrollIndicator = false
  75. scrollView.contentInsetAdjustmentBehavior = .never
  76. return scrollView
  77. }()
  78. lazy var cardBannerImageView: UIImageView = {
  79. let imageView = UIImageView()
  80. imageView.image = UIImage(named: "vip_banner_card")
  81. return imageView
  82. }()
  83. lazy var vipTimeLabel: UILabel = {
  84. let label = UILabel()
  85. label.text("升级VIP会员,解锁全部功能")
  86. label.font(13)
  87. label.textColor = .hexStringColor(hexString: "#AF7655")
  88. return label
  89. }()
  90. lazy var funcBannerImageView: UIImageView = {
  91. let imageView = UIImageView()
  92. imageView.image = UIImage(named: "vip_banner_func")
  93. return imageView
  94. }()
  95. lazy var mainView: UIView = {
  96. let view = UIView()
  97. view.backgroundColor = QSLColor.backGroundColor
  98. view.addRadius(radius: 12.rpx)
  99. return view
  100. }()
  101. lazy var goodsBgView: UIView = {
  102. let view = UIView()
  103. view.gradientBackgroundColor(color1: .hexStringColor(hexString: "#FFF8F2"), color2: .hexStringColor(hexString: "#FFFFFF"), width: QSLConst.qsl_kScreenW, height: UX.goodsBgHeight, direction: .vertical)
  104. return view
  105. }()
  106. lazy var vipGoodsTitleIcon: UIImageView = {
  107. let imageView = UIImageView()
  108. imageView.image = UIImage(named: "vip_title_icon")
  109. return imageView
  110. }()
  111. lazy var resumeBtn: UIButton = {
  112. let button = UIButton()
  113. button.title("恢复购买")
  114. button.setTitleColor(.hexStringColor(hexString: "#000000").withAlphaComponent(0.5), for: .normal)
  115. button.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .medium)
  116. button.image(UIImage(named: "vip_resume_btn"))
  117. button.setImageTitleLayout(.imgLeft, spacing: 2.rpx)
  118. button.addTarget(self, action: #selector(resumeBtnAction), for: .touchUpInside)
  119. return button
  120. }()
  121. lazy var mostCell: QSLVipMostGoodCell = {
  122. let cell = QSLVipMostGoodCell()
  123. cell.isUserInteractionEnabled = true
  124. let tap = UITapGestureRecognizer(target: self, action: #selector(firstCellClickAction))
  125. cell.addGestureRecognizer(tap)
  126. return cell
  127. }()
  128. lazy var goodsCollectionView: UICollectionView = {
  129. let layout = UICollectionViewFlowLayout()
  130. layout.minimumLineSpacing = 0
  131. layout.scrollDirection = .vertical
  132. let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
  133. collectionView.backgroundColor = .clear
  134. collectionView.dataSource = self
  135. collectionView.delegate = self
  136. collectionView.showsHorizontalScrollIndicator = false
  137. collectionView.bounces = false
  138. collectionView.register(cellClass: QSLVipGoodCollectionViewCell.self)
  139. return collectionView
  140. }()
  141. lazy var selectBtn: UIButton = {
  142. let btn = UIButton()
  143. btn.image(UIImage(named: "public_select_btn_false"), .normal)
  144. btn.image(UIImage(named: "public_select_btn_true"), .selected)
  145. btn.addTarget(self, action: #selector(selectBtnAction), for: .touchUpInside)
  146. return btn
  147. }()
  148. lazy var serviceLabel: YYLabel = {
  149. let label = YYLabel()
  150. //updateServiceLabelText(showSubscribe: true) // 默认显示所有内容
  151. return label
  152. }()
  153. // 更新服务条款文本内容
  154. func updateServiceLabelText(showSubscribe: Bool) {
  155. let attr = NSMutableAttributedString()
  156. // 固定部分:购买即同意
  157. let firstAttr = NSMutableAttributedString(string: "购买即同意")
  158. firstAttr.font(10)
  159. firstAttr.color(.hexStringColor(hexString: "#A7A7A7"))
  160. attr.append(firstAttr)
  161. let blankAttr = NSMutableAttributedString(string: " ")
  162. blankAttr.font(10)
  163. attr.append(blankAttr)
  164. // 《隐私权政策》
  165. let privacyHL = YYTextHighlight()
  166. let privacyStr = "《隐私权政策》"
  167. let privacyText = NSMutableAttributedString(string: privacyStr)
  168. privacyText.font(10)
  169. privacyText.color(.hexStringColor(hexString: "#E7B983"))
  170. privacyText.yy_setTextHighlight(privacyHL, range: NSRange(location: 0, length: privacyStr.count))
  171. privacyHL.tapAction = { [weak self] containerView, text, range, rect in
  172. self?.privacyAction()
  173. }
  174. attr.append(privacyText)
  175. attr.append(blankAttr)
  176. // 《用户协议》
  177. let serviceHL = YYTextHighlight()
  178. let serviceStr = "《用户协议》"
  179. let serviceText = NSMutableAttributedString(string: serviceStr)
  180. serviceText.font(10)
  181. serviceText.color(.hexStringColor(hexString: "#E7B983"))
  182. serviceText.yy_setTextHighlight(serviceHL, range: NSRange(location: 0, length: serviceStr.count))
  183. serviceHL.tapAction = { [weak self] containerView, text, range, rect in
  184. self?.serviceAction()
  185. }
  186. attr.append(serviceText)
  187. // 根据条件决定是否添加《续订说明》相关内容
  188. if showSubscribe {
  189. attr.append(blankAttr)
  190. let andAttr = NSMutableAttributedString(string: "和")
  191. andAttr.font(10)
  192. andAttr.color(.hexStringColor(hexString: "#A7A7A7"))
  193. attr.append(andAttr)
  194. attr.append(blankAttr)
  195. let subcribeHL = YYTextHighlight()
  196. let subcribeStr = "《续订说明》"
  197. let subcribeText = NSMutableAttributedString(string: subcribeStr)
  198. subcribeText.font(10)
  199. subcribeText.color(.hexStringColor(hexString: "#E7B983"))
  200. subcribeText.yy_setTextHighlight(subcribeHL, range: NSRange(location: 0, length: subcribeStr.count))
  201. subcribeHL.tapAction = { [weak self] containerView, text, range, rect in
  202. self?.subscibeAction()
  203. }
  204. attr.append(subcribeText)
  205. }
  206. serviceLabel.attributedText = attr
  207. }
  208. // 在需要隐藏《续订说明》时调用此方法
  209. func hideSubscribeDescription() {
  210. updateServiceLabelText(showSubscribe: false)
  211. }
  212. // 在需要显示《续订说明》时调用此方法
  213. func showSubscribeDescription() {
  214. updateServiceLabelText(showSubscribe: true)
  215. }
  216. lazy var commentView: UIView = {
  217. let view = UIView()
  218. view.backgroundColor = .white
  219. return view
  220. }()
  221. lazy var commentTitleIcon: UIImageView = {
  222. let imageView = UIImageView()
  223. imageView.image = UIImage(named: "vip_comment_title_icon")
  224. return imageView
  225. }()
  226. lazy var comment1: QSLVipCommentCellView = {
  227. let view = QSLVipCommentCellView()
  228. view.config(name: "用户189****7913", comment: "上班没时间,远程遛娃,非常方便很好用。")
  229. return view
  230. }()
  231. lazy var comment2: QSLVipCommentCellView = {
  232. let view = QSLVipCommentCellView()
  233. view.config(name: "用户189****7913", comment: "用了之后,才发现真的可以找到他。")
  234. return view
  235. }()
  236. lazy var comment3: QSLVipCommentCellView = {
  237. let view = QSLVipCommentCellView()
  238. view.config(name: "用户189****7913", comment: "轨迹很准,一目了然,奶奶出门遇到危险直接一键报警,我就收到信息了")
  239. return view
  240. }()
  241. lazy var tipTitleLabel: UILabel = {
  242. let label = UILabel()
  243. label.text("温馨提示")
  244. label.font(12)
  245. label.textColor = .hexStringColor(hexString: "#000000").withAlphaComponent(0.8)
  246. return label
  247. }()
  248. lazy var tipContentLabel: UILabel = {
  249. let label = UILabel()
  250. label.numberOfLines = 0
  251. label.text("1 订阅后会从您的iTunes账户中扣除相关费用。如需取消续订,请在当前订阅周期结束前,至少24小时内通过手机“账户设置”的订阅管理关闭自动续费功能。\n2 未成年人请在监护者的陪同下进行购买\n3 购买后不支持退款,请仔细审阅《隐私权政策》《用户协议》和《续订说明》")
  252. label.font(10)
  253. label.textColor = .hexStringColor(hexString: "#000000").withAlphaComponent(0.6)
  254. label.changeLineSpace(space: 5)
  255. return label
  256. }()
  257. lazy var bottomContentView: UIView = {
  258. let view = UIView()
  259. return view
  260. }()
  261. lazy var bottomTopView: UIView = {
  262. let view = UIView()
  263. view.isHidden = true
  264. view.backgroundColor = .hexStringColor(hexString: "#FFFED8")
  265. view.addRadius(radius: 30.rpx)
  266. return view
  267. }()
  268. lazy var bottomTopLabel: UILabel = {
  269. let label = UILabel()
  270. label.text = ""
  271. return label
  272. }()
  273. func bottomTopLabelInfo(_ goodInfo : QSLGoodModel) {
  274. let darkGrayAttributes: [NSAttributedString.Key: Any] = [
  275. .foregroundColor: UIColor.hexStringColor(hexString: "#404040"),
  276. .font: UIFont.systemFont(ofSize: 11),
  277. .paragraphStyle: {
  278. let paragraphStyle = NSMutableParagraphStyle()
  279. paragraphStyle.alignment = .center
  280. return paragraphStyle
  281. }(),
  282. .kern: -1
  283. ]
  284. // 创建绿色文本样式
  285. let greenAttributes: [NSAttributedString.Key: Any] = [
  286. .foregroundColor: UIColor.hexStringColor(hexString: "#EE6C1C"),
  287. .font: UIFont.systemFont(ofSize: 15, weight: .black),
  288. .paragraphStyle: {
  289. let paragraphStyle = NSMutableParagraphStyle()
  290. paragraphStyle.alignment = .center
  291. return paragraphStyle
  292. }(),
  293. .kern: -1
  294. ]
  295. let textArray = goodInfo.text.components(separatedBy: goodInfo.keys.key)
  296. if textArray.count > 0 && goodInfo.text.count > 0{
  297. bottomTopView.isHidden = false
  298. let inputtr = NSMutableAttributedString()
  299. let titleOneAttr = NSAttributedString(string: textArray.first ?? "", attributes: darkGrayAttributes)
  300. let titleTwoAttr = NSAttributedString(string: " \(goodInfo.keys.value) ", attributes: greenAttributes)
  301. inputtr.append(titleOneAttr)
  302. inputtr.append(titleTwoAttr)
  303. if textArray.count > 1 {
  304. let titleThreeAttr = NSAttributedString(string: textArray[1], attributes: darkGrayAttributes)
  305. inputtr.append(titleThreeAttr)
  306. }
  307. bottomTopLabel.attributedText = inputtr
  308. } else {
  309. bottomTopView.isHidden = true
  310. }
  311. }
  312. lazy var bottomView: UIView = {
  313. let view = UIView()
  314. view.gradientBackgroundColor(color1: .hexStringColor(hexString: "#00434E"), color2: .hexStringColor(hexString: "#0E5E61"), width: QSLConst.qsl_kScreenW - 24.rpx, height: 50.rpx, direction: .horizontal)
  315. view.addRadius(radius: 25.rpx)
  316. return view
  317. }()
  318. lazy var unlockBtn: UIButton = {
  319. let btn = UIButton()
  320. btn.setBackgroundImage(UIImage(named: "vip_unlock_btn_bg"), for: .normal)
  321. btn.title("立即解锁")
  322. btn.textColor(.hexStringColor(hexString: "#9B3800"))
  323. btn.mediumFont(18)
  324. btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 30.rpx, bottom: 0, right: 0)
  325. btn.addTarget(self, action: #selector(unlockBtnAction), for: .touchUpInside)
  326. return btn
  327. }()
  328. lazy var priceIconLabel: UILabel = {
  329. let label = UILabel()
  330. label.text("¥")
  331. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  332. label.font(14)
  333. return label
  334. }()
  335. lazy var priceLabel: UILabel = {
  336. let label = UILabel()
  337. label.text("168")
  338. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  339. label.font(24)
  340. return label
  341. }()
  342. lazy var goodTypeLabel: UILabel = {
  343. let label = UILabel()
  344. label.text("/")
  345. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  346. label.font(12)
  347. return label
  348. }()
  349. lazy var goodOriginalPriceLabel: UILabel = {
  350. let label = UILabel()
  351. label.text("原价228")
  352. label.textColor = .hexStringColor(hexString: "#FFF8EF")
  353. label.font(12)
  354. label.centerLineText(lineValue: 1, underlineColor: .hexStringColor(hexString: "#FFF8EF"))
  355. return label
  356. }()
  357. deinit {
  358. self.finishHandler?(self.isCancel)
  359. }
  360. override func viewDidLoad() {
  361. super.viewDidLoad()
  362. initializeView()
  363. updateUI()
  364. requestItemList()
  365. calculateBuyCount()
  366. if(QSLBaseManager.shared.isLogin()){
  367. self.resumeBtn.isHidden = true
  368. }else{
  369. self.resumeBtn.isHidden = true
  370. }
  371. if let type = self.type {
  372. switch type {
  373. case .homeRoad:
  374. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1001])
  375. gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"track"])
  376. case .add:
  377. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1002])
  378. gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"find_friend"])
  379. case .friendRoad:
  380. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1003])
  381. gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"find_track"])
  382. case .contact:
  383. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1004])
  384. gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"contact"])
  385. case .mine:
  386. gravityInstance?.track(QSLGravityConst.vip_show, properties: ["id": 1006])
  387. gravityInstance?.track(QSLGravityConst.new_vip_show, properties: ["is_member":QSLBaseManager.shared.isVip(),"entry_point":"open_now"])
  388. case .guideComments:
  389. print("")
  390. }
  391. }
  392. }
  393. }
  394. extension QSLVipController {
  395. @objc func privacyAction() {
  396. let vc = QSLWebViewController()
  397. vc.webUrl = QSLConfig.AppPrivacyAgreementLink
  398. vc.title = "隐私政策"
  399. self.navigationController?.pushViewController(vc, animated: true)
  400. }
  401. @objc func serviceAction() {
  402. let vc = QSLWebViewController()
  403. vc.webUrl = QSLConfig.AppServiceAgreementLink
  404. vc.title = "服务协议"
  405. self.navigationController?.pushViewController(vc, animated: true)
  406. }
  407. @objc func subscibeAction() {
  408. let vc = QSLWebViewController()
  409. vc.webUrl = QSLConfig.AppSubscibeAgreementLink
  410. vc.title = "续订说明"
  411. self.navigationController?.pushViewController(vc, animated: true)
  412. }
  413. @objc func selectBtnAction() {
  414. selectBtn.isSelected = !selectBtn.isSelected
  415. }
  416. // 恢复按钮点击
  417. @objc func resumeBtnAction() {
  418. let memberModel = QSLBaseManager.shared.userModel.memberModel
  419. let expired = memberModel.expired
  420. if !expired {
  421. QSLLoading.success(text: "您已经在订阅中,无需恢复")
  422. return
  423. }
  424. QSLLoading.show()
  425. QSLVipManager.shared.restoreAction { isSuccess in
  426. QSLVipManager.shared.isPaying = false
  427. if isSuccess {
  428. QSLNetwork().request(.userMember(dict: [:])) { response in
  429. let model = response.mapObject(QSLMemberModel.self, modelKey: "data")
  430. QSLBaseManager.shared.userModel.memberModel = model
  431. if model.expired {
  432. QSLBaseManager.shared.saveVipExpiredTime(time: 0)
  433. } else {
  434. QSLBaseManager.shared.saveVipExpiredTime(time: model.endTimestamp)
  435. }
  436. QSLBaseManager.shared.saveUserId(id: model.userId)
  437. if model.endTimestamp > memberModel.endTimestamp {
  438. QSLLoading.success(text: "恢复成功")
  439. // 支付成功通知
  440. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
  441. self.navigationController?.popViewController(animated: true)
  442. }
  443. } else {
  444. QSLLoading.error(text: "没有可供恢复的订阅")
  445. }
  446. } fail: { code, error in
  447. QSLLoading.error(text: "没有可供恢复的订阅")
  448. }
  449. } else {
  450. QSLLoading.error(text: "没有可供恢复的订阅")
  451. }
  452. }
  453. }
  454. // 支付按钮点击
  455. @objc func unlockBtnAction() {
  456. switch self.selectGood?.level {
  457. case 100 :
  458. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1006])
  459. gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "day"])
  460. break
  461. case 700:
  462. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1005])
  463. gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "weekly"])
  464. break;
  465. case 3100:
  466. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1004])
  467. gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "monthly"])
  468. break;
  469. case 9200:
  470. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1003])
  471. gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "quarterly"])
  472. break;
  473. case 36600:
  474. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1002])
  475. gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "yearly"])
  476. break;
  477. case 3660000:
  478. gravityInstance?.track(QSLGravityConst.vip_buy_click, properties: ["id": 1001])
  479. gravityInstance?.track(QSLGravityConst.new_vip_click, properties: ["is_member":QSLBaseManager.shared.isVip(),"package_type": "lifetime"])
  480. break;
  481. default:
  482. break;
  483. }
  484. // if !selectBtn.isSelected {
  485. // self.view.toast(text: "请先同意《隐私权政策》和《用户协议》")
  486. // return
  487. // }
  488. let memberModel = QSLBaseManager.shared.userModel.memberModel
  489. if let subscriptionExpired = memberModel.subscriptionExpired, !subscriptionExpired {
  490. self.view.toast(text: "你已经订阅了")
  491. return
  492. }
  493. if goodList.count > 0, let selectGood = self.selectGood {
  494. QSLLoading.show()
  495. QSLVipManager.shared.startPay(goods: selectGood) { [self] status, outTradeNo in
  496. QSLVipManager.shared.isPaying = false
  497. if status == .success {
  498. QSLLoading.success(text: "支付成功")
  499. gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(selectGood.amount)])
  500. //支付成功埋点
  501. gravityInstance?.track(QSLGravityConst.vip_submit_success, properties: ["id": 01001])
  502. //弹出是否好评的弹窗
  503. QSLGuideusersToCommentManager.commentShare.manageWhetherTriggerPopUpWindow(QSLGuideusersToCommentType.member)
  504. // 引力传递支付事件
  505. if let selectGood = self.selectGood {
  506. gravityInstance?.trackPayEvent(withAmount: Int32(selectGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: selectGood.name, withPayMethod: "apple")
  507. }
  508. #if DEBUG
  509. #else
  510. //苹果广告奇异果传递支付事件
  511. QSWikiHandle.shared.addEventResultAttribution(eventDict: ["event_name": "pay", "event_val": selectGood.amount])
  512. #endif
  513. if let type = self.type {
  514. switch type {
  515. case .homeRoad:
  516. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1001])
  517. case .add:
  518. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1002])
  519. case .friendRoad:
  520. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1003])
  521. case .contact:
  522. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1004])
  523. case .mine:
  524. gravityInstance?.track(QSLGravityConst.vip_success_page, properties: ["id": 1006])
  525. case .guideComments:
  526. print("")
  527. }
  528. }
  529. switch self.selectGood?.level {
  530. case 100 :
  531. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 1])
  532. break
  533. case 700:
  534. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 5])
  535. break;
  536. case 3100:
  537. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 9])
  538. break;
  539. case 9200:
  540. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 13])
  541. break;
  542. case 36600:
  543. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 17])
  544. break;
  545. case 3660000:
  546. gravityInstance?.track(QSLGravityConst.vip_success_good, properties: ["id": 21])
  547. break;
  548. default:
  549. break;
  550. }
  551. DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
  552. self.navigationController?.popViewController(animated: true)
  553. NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
  554. }
  555. } else if status == .cancel {
  556. gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(selectGood.amount)])
  557. QSLLoading.error(text: "支付取消")
  558. payFailAlertTip()
  559. gravityInstance?.track(QSLGravityConst.new_vip_retention_show, properties: ["trigger_type":"cancel_payment"])
  560. } else if status == .fail {
  561. gravityInstance?.track(QSLGravityConst.new_vip_result, properties: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(selectGood.amount)])
  562. gravityInstance?.track(QSLGravityConst.vip_fail)
  563. QSLLoading.error(text: "支付失败")
  564. payFailAlertTip()
  565. gravityInstance?.track(QSLGravityConst.new_vip_retention_show, properties: ["trigger_type":"fail"])
  566. } else if status == .searchFail {
  567. QSLLoading.error(text: "查询订单失败,请稍后重试")
  568. }
  569. }
  570. }
  571. }
  572. func payFailAlertTip() {
  573. if let currentWindow = UIApplication.keyWindow {
  574. self.isCancel = true
  575. QSLRetainPopUpAlertView.alert(view: currentWindow, isOneBtn: true, oneBtnText: "继续支付", oneBtnClosure: { [weak self] in
  576. self?.unlockBtnAction()
  577. gravityInstance?.track(QSLGravityConst.new_vip_retention_click, properties: ["button":"continue_payment"])
  578. },closeBtnClosure: {
  579. gravityInstance?.track(QSLGravityConst.new_vip_retention_click, properties: ["button":"close"])
  580. })
  581. }
  582. }
  583. @objc func firstCellClickAction() {
  584. for i in 0..<self.goodList.count {
  585. self.goodList[i].isSelect = false
  586. }
  587. if self.goodList.count > 0 {
  588. self.goodList[0].isSelect = true
  589. self.selectGood = self.goodList[0]
  590. self.mostCell.config(model: self.goodList[0])
  591. //选中立即支付
  592. unlockBtnAction()
  593. }
  594. switch self.selectGood?.level {
  595. case 100 :
  596. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
  597. break
  598. case 700:
  599. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
  600. break;
  601. case 3100:
  602. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
  603. break;
  604. case 9200:
  605. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
  606. break;
  607. case 36600:
  608. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
  609. break;
  610. case 3660000:
  611. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
  612. break;
  613. default:
  614. break;
  615. }
  616. self.goodsCollectionView.reloadData()
  617. }
  618. }
  619. extension QSLVipController {
  620. // 请求商品列表
  621. func requestItemList() {
  622. // 定义并赋值 itemListDict(根据条件变化)
  623. var itemListDict: [String: Any] = ["itemListType": 2]
  624. if UserDefaults.standard.string(forKey: QSLVipController.record_non_member_clicks_to_claim) == nil && self.type == .guideComments {
  625. itemListDict = ["itemListType": 2, "showExtraText": true]
  626. // 记录非会员点击领取
  627. UserDefaults.standard.set("YES", forKey: QSLVipController.record_non_member_clicks_to_claim)
  628. UserDefaults.standard.synchronize()
  629. }
  630. // 网络请求时使用 itemListDict 作为参数(关键修复)
  631. QSLNetwork().request(.vipItemList(dict: itemListDict)) { response in
  632. // 后续逻辑不变...
  633. let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
  634. self.goodList = list
  635. if self.goodList.count > 0 {
  636. self.goodList[0].isSelect = true
  637. self.selectGood = self.goodList[0]
  638. QSLCountdownManager.shared.selectGood = self.goodList[0]
  639. self.mostCell.config(model: self.goodList[0])
  640. let row = ceil(Double(self.goodList.count - 1) / 3.0)
  641. let height = UX.goodsBgHeight + (row * UX.collectionRowHeight)
  642. self.goodsBgView.gradientBackgroundColor(color1: .hexStringColor(hexString: "#FFF8F2"), color2: .hexStringColor(hexString: "#FFFFFF"), width: QSLConst.qsl_kScreenW, height: height, direction: .vertical)
  643. self.goodsBgView.snp.updateConstraints { make in
  644. make.height.equalTo(height)
  645. }
  646. self.scrollView.snp.makeConstraints { make in
  647. make.bottom.equalTo(self.mainView)
  648. }
  649. self.checkRenewalOfProducts()
  650. }
  651. self.goodsCollectionView.reloadData()
  652. } fail: { code, error in
  653. self.view.toast(text: "加载商品列表失败")
  654. }
  655. }
  656. ///检查有没有续订的产品
  657. func checkRenewalOfProducts() {
  658. let hasSubscribable = self.goodList.contains(where: { model in
  659. return model.subscribable == 1
  660. })
  661. if hasSubscribable == false {
  662. tipContentLabel.isHidden = true
  663. hideSubscribeDescription()
  664. serviceLabel.snp.removeConstraints()
  665. serviceLabel.snp.makeConstraints { make in
  666. make.left.equalTo(16)
  667. make.top.equalTo(comment3.snp.bottom).offset(28.rpx)
  668. }
  669. } else {
  670. tipContentLabel.isHidden = false
  671. showSubscribeDescription()
  672. }
  673. }
  674. // 计算购买人数
  675. func calculateBuyCount() {
  676. var num = 145883
  677. if let localNum = UserDefaults.standard.value(forKey: QSLConfig.user_default_local_buy_count) as? Int {
  678. num = localNum
  679. }
  680. let randomAddCount = Int.random(in: 1...10)
  681. num = num + randomAddCount
  682. UserDefaults.standard.setValue(num, forKey: QSLConfig.user_default_local_buy_count)
  683. self.peopleCountLabel.text("\(num)人 已开通VIP")
  684. }
  685. }
  686. // MARK: - 设置 CollectionView
  687. extension QSLVipController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  688. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  689. return goodList.count - 1
  690. }
  691. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  692. let cell = collectionView.dequeueReusableCell(cellType: QSLVipGoodCollectionViewCell.self, cellForRowAt: indexPath)
  693. let model = self.goodList[indexPath.row + 1]
  694. if self.goodList.count - 1 == 2 {
  695. cell.config(model: model, type: .big)
  696. } else {
  697. cell.config(model: model, type: .small)
  698. }
  699. return cell
  700. }
  701. func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  702. for i in 0..<self.goodList.count {
  703. self.goodList[i].isSelect = false
  704. }
  705. if self.goodList.count > 0 {
  706. self.goodList[indexPath.row + 1].isSelect = true
  707. self.selectGood = self.goodList[indexPath.row + 1]
  708. self.mostCell.config(model: self.goodList[0])
  709. //选中立即支付
  710. unlockBtnAction()
  711. }
  712. switch self.selectGood?.level {
  713. case 100 :
  714. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1006])
  715. break
  716. case 700:
  717. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1005])
  718. break;
  719. case 3100:
  720. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1004])
  721. break;
  722. case 9200:
  723. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1003])
  724. break;
  725. case 36600:
  726. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1002])
  727. break;
  728. case 3660000:
  729. gravityInstance?.track(QSLGravityConst.vip_good_select, properties: ["id": 1001])
  730. break;
  731. default:
  732. break;
  733. }
  734. self.goodsCollectionView.reloadData()
  735. }
  736. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  737. var width = (QSLConst.qsl_kScreenW - 42.0.rpx) / 3.0
  738. if self.goodList.count - 1 == 2 {
  739. width = (QSLConst.qsl_kScreenW - 36.0.rpx) / 2.0
  740. }
  741. return CGSize(width: width, height: 134.0.rpx)
  742. }
  743. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  744. return 6.rpx
  745. }
  746. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  747. return 3.rpx
  748. }
  749. }
  750. extension QSLVipController {
  751. func updateUI() {
  752. if QSLBaseManager.shared.isLogin() && QSLBaseManager.shared.isVip() {
  753. let model = QSLBaseManager.shared.userModel.memberModel
  754. if model.permanent {
  755. self.vipTimeLabel.text("您已是尊贵的永久会员")
  756. self.bottomContentView.isHidden = true
  757. } else {
  758. let level = model.memberLevelString()
  759. let endTime = model.endTimestampString()
  760. self.vipTimeLabel.text("\(level):\(endTime)到期")
  761. }
  762. } else {
  763. self.vipTimeLabel.text("升级VIP会员,解锁全部功能")
  764. }
  765. }
  766. func updateSelectGoodUI() {
  767. var priceText = ""
  768. var originalPriceText = ""
  769. if let selectGood = self.selectGood {
  770. if selectGood.amount.truncatingRemainder(dividingBy: 100) == 0 {
  771. priceText = "\(Int(selectGood.amount / 100))"
  772. } else {
  773. priceText = String(format: "%.2lf", selectGood.amount / 100 )
  774. }
  775. if selectGood.originalAmount.truncatingRemainder(dividingBy: 100) == 0 {
  776. originalPriceText = "\(Int(selectGood.originalAmount / 100))"
  777. } else {
  778. originalPriceText = String(format: "%.2lf", selectGood.originalAmount / 100 )
  779. }
  780. }
  781. self.priceLabel.text(priceText)
  782. // self.goodTypeLabel.text("/ \(self.selectGood?.name ?? "")")
  783. self.goodOriginalPriceLabel.text("原价\(originalPriceText)")
  784. ///底部内容
  785. bottomTopLabelInfo(self.selectGood ?? QSLGoodModel())
  786. }
  787. func initializeView() {
  788. self.view.addSubview(vipBg)
  789. vipBg.snp.makeConstraints { make in
  790. make.left.top.right.equalTo(0)
  791. }
  792. self.view.addSubview(backButton)
  793. backButton.snp.makeConstraints { make in
  794. make.size.equalTo(100.rpx)
  795. make.height.equalTo(25.rpx)
  796. make.left.equalTo(12.rpx)
  797. make.top.equalTo(QSLConst.qsl_kStatusBarFrameH)
  798. }
  799. self.view.addSubview(peopleCountView)
  800. peopleCountView.snp.makeConstraints { make in
  801. make.size.equalTo(CGSize(width: 212.rpx, height: 24.rpx))
  802. make.right.equalTo(-13.rpx)
  803. make.centerY.equalTo(backButton.snp.centerY)
  804. }
  805. peopleCountView.addSubview(peopleAvatarImageView)
  806. peopleAvatarImageView.snp.makeConstraints { make in
  807. make.size.equalTo(CGSize(width: 72.rpx, height: 16.6.rpx))
  808. make.left.equalTo(3.rpx)
  809. make.centerY.equalTo(peopleCountView.snp.centerY)
  810. }
  811. peopleCountView.addSubview(peopleCountLabel)
  812. peopleCountLabel.snp.makeConstraints { make in
  813. make.left.equalTo(peopleAvatarImageView.snp.right).offset(7.rpx)
  814. make.centerY.equalTo(peopleCountView.snp.centerY)
  815. }
  816. self.view.addSubview(scrollView)
  817. scrollView.snp.makeConstraints { make in
  818. make.left.right.equalTo(0)
  819. make.top.equalTo(QSLConst.qsl_kNavFrameH)
  820. make.bottom.equalTo(0)
  821. }
  822. scrollView.addSubview(cardBannerImageView)
  823. cardBannerImageView.snp.makeConstraints { make in
  824. make.top.equalTo(0)
  825. make.centerX.equalToSuperview()
  826. make.width.equalTo(336.rpx)
  827. make.height.equalTo(108.rpx)
  828. }
  829. cardBannerImageView.addSubview(vipTimeLabel)
  830. vipTimeLabel.snp.makeConstraints { make in
  831. make.left.equalTo(23.rpx)
  832. make.bottom.equalTo(-19.rpx)
  833. }
  834. scrollView.addSubview(funcBannerImageView)
  835. funcBannerImageView.snp.makeConstraints { make in
  836. make.size.equalTo(CGSize(width: 336.rpx, height: 172.rpx))
  837. make.centerX.equalToSuperview()
  838. make.top.equalTo(cardBannerImageView.snp.bottom).offset(14.rpx)
  839. }
  840. scrollView.addSubview(mainView)
  841. mainView.snp.makeConstraints { make in
  842. make.left.right.equalTo(0)
  843. make.top.equalTo(funcBannerImageView.snp.bottom).offset(-24.rpx)
  844. make.width.equalTo(QSLConst.qsl_kScreenW)
  845. // make.height.equalTo(800.rpx)
  846. }
  847. let goodsBgHeight = 54.rpx + UX.mostCellHeight
  848. mainView.addSubview(goodsBgView)
  849. goodsBgView.snp.makeConstraints { make in
  850. make.top.left.right.equalTo(0)
  851. make.width.equalTo(QSLConst.qsl_kScreenW)
  852. make.height.equalTo(goodsBgHeight)
  853. }
  854. goodsBgView.addSubview(vipGoodsTitleIcon)
  855. vipGoodsTitleIcon.snp.makeConstraints { make in
  856. make.size.equalTo(CGSize(width: 117.rpx, height: 26.rpx))
  857. make.left.equalTo(20.rpx)
  858. make.top.equalTo(16.rpx)
  859. }
  860. goodsBgView.addSubview(resumeBtn)
  861. resumeBtn.snp.makeConstraints { make in
  862. make.size.equalTo(CGSize(width: 75.rpx, height: 16.rpx))
  863. make.right.equalTo(-18.rpx)
  864. make.centerY.equalTo(vipGoodsTitleIcon.snp.centerY)
  865. }
  866. goodsBgView.addSubview(mostCell)
  867. mostCell.snp.makeConstraints { make in
  868. make.left.equalTo(12.rpx)
  869. make.right.equalTo(-16.rpx)
  870. make.height.equalTo(113.rpx)
  871. make.top.equalTo(vipGoodsTitleIcon.snp.bottom).offset(10.rpx)
  872. }
  873. goodsBgView.addSubview(goodsCollectionView)
  874. goodsCollectionView.snp.makeConstraints { make in
  875. make.left.equalTo(12.rpx)
  876. make.right.equalTo(-18.rpx)
  877. make.bottom.equalTo(-20.rpx)
  878. make.top.equalTo(mostCell.snp.bottom).offset(3.rpx)
  879. }
  880. // goodsBgView.addSubview(selectBtn)
  881. // selectBtn.snp.makeConstraints { make in
  882. // make.size.equalTo(CGSize(width: 12.rpx, height: 12.rpx))
  883. // make.left.equalTo(23.rpx)
  884. // make.top.equalTo(goodsCollectionView.snp.bottom).offset(16.rpx)
  885. // }
  886. //
  887. // goodsBgView.addSubview(serviceLabel)
  888. // serviceLabel.snp.makeConstraints { make in
  889. // make.left.equalTo(selectBtn.snp.right).offset(2.rpx)
  890. // make.centerY.equalTo(selectBtn.snp.centerY)
  891. // }
  892. mainView.addSubview(commentView)
  893. commentView.snp.makeConstraints { make in
  894. make.left.right.equalTo(0)
  895. make.top.equalTo(goodsBgView.snp.bottom).offset(8.rpx)
  896. make.height.equalTo(525.rpx + QSLConst.qsl_kTabbarBottom)
  897. make.bottom.equalTo(0)
  898. }
  899. commentView.addSubview(commentTitleIcon)
  900. commentTitleIcon.snp.makeConstraints { make in
  901. make.size.equalTo(CGSize(width: 83.rpx, height: 26.rpx))
  902. make.top.equalTo(16.rpx)
  903. make.left.equalTo(12.rpx)
  904. }
  905. let commentHeight1 = "上班没时间,远程遛娃,非常方便很好用。".heightAccording(width: QSLConst.qsl_kScreenW - 52.rpx - 12.rpx, font: .textF(15), lineSpacing: 2) + 35.rpx
  906. commentView.addSubview(comment1)
  907. comment1.snp.makeConstraints { make in
  908. make.left.right.equalTo(0)
  909. make.top.equalTo(commentTitleIcon.snp.bottom).offset(16.rpx)
  910. make.height.equalTo(commentHeight1)
  911. }
  912. let commentHeight2 = "用了之后,才发现真的可以找到他。".heightAccording(width: QSLConst.qsl_kScreenW - 52.rpx - 12.rpx, font: .textF(15), lineSpacing: 2) + 35.rpx
  913. commentView.addSubview(comment2)
  914. comment2.snp.makeConstraints { make in
  915. make.left.right.equalTo(0)
  916. make.top.equalTo(comment1.snp.bottom).offset(30.rpx)
  917. make.height.equalTo(commentHeight2)
  918. }
  919. let commentHeight3 = "轨迹很准,一目了然,奶奶出门遇到危险直接一键报警,我就收到信息了".heightAccording(width: QSLConst.qsl_kScreenW - 52.rpx - 12.rpx, font: .textF(15), lineSpacing: 2) + 35.rpx
  920. commentView.addSubview(comment3)
  921. comment3.snp.makeConstraints { make in
  922. make.left.right.equalTo(0)
  923. make.top.equalTo(comment2.snp.bottom).offset(30.rpx)
  924. make.height.equalTo(commentHeight3)
  925. }
  926. // commentView.addSubview(tipTitleLabel)
  927. // tipTitleLabel.snp.makeConstraints { make in
  928. // make.left.equalTo(16)
  929. // make.top.equalTo(comment3.snp.bottom).offset(28)
  930. // }
  931. commentView.addSubview(tipContentLabel)
  932. tipContentLabel.snp.makeConstraints { make in
  933. make.left.equalTo(16)
  934. make.right.equalTo(-16)
  935. make.top.equalTo(comment3.snp.bottom).offset(11)
  936. }
  937. commentView.addSubview(serviceLabel)
  938. serviceLabel.snp.makeConstraints { make in
  939. make.left.equalTo(16)
  940. make.top.equalTo(tipContentLabel.snp.bottom).offset(28.rpx)
  941. }
  942. scrollView.snp.makeConstraints { make in
  943. make.bottom.equalTo(mainView)
  944. }
  945. self.view.addSubview(bottomContentView)
  946. bottomContentView.snp.makeConstraints { make in
  947. make.left.equalTo(12.rpx)
  948. make.right.equalTo(-12.rpx)
  949. make.bottom.equalTo(-QSLConst.qsl_kTabbarBottom)
  950. make.height.equalTo(72.rpx)
  951. }
  952. bottomContentView.addSubview(bottomTopView)
  953. bottomTopView.snp.makeConstraints { make in
  954. make.left.equalToSuperview()
  955. make.right.equalToSuperview()
  956. make.top.equalToSuperview()
  957. make.height.equalTo(60.rpx)
  958. }
  959. bottomTopView.addSubview(bottomTopLabel)
  960. bottomTopLabel.snp.makeConstraints { make in
  961. make.left.equalToSuperview().offset(22)
  962. make.top.equalToSuperview()
  963. make.height.equalTo(21.rpx)
  964. }
  965. bottomContentView.addSubview(bottomView)
  966. bottomView.snp.makeConstraints { make in
  967. make.left.equalToSuperview()
  968. make.right.equalToSuperview()
  969. make.bottom.equalToSuperview()
  970. make.height.equalTo(50.rpx)
  971. }
  972. bottomView.addSubview(unlockBtn)
  973. unlockBtn.snp.makeConstraints { make in
  974. make.right.top.bottom.equalTo(0)
  975. make.width.equalTo(165.rpx)
  976. }
  977. bottomView.addSubview(priceIconLabel)
  978. priceIconLabel.snp.makeConstraints { make in
  979. make.left.equalTo(20.rpx)
  980. make.bottom.equalTo(-12.rpx)
  981. }
  982. bottomView.addSubview(priceLabel)
  983. priceLabel.snp.makeConstraints { make in
  984. make.left.equalTo(priceIconLabel.snp.right).offset(2.rpx)
  985. make.bottom.equalTo(-10.rpx)
  986. }
  987. bottomView.addSubview(goodTypeLabel)
  988. goodTypeLabel.snp.makeConstraints { make in
  989. make.left.equalTo(priceLabel.snp.right).offset(2.rpx)
  990. make.bottom.equalTo(-14.rpx)
  991. }
  992. bottomView.addSubview(goodOriginalPriceLabel)
  993. goodOriginalPriceLabel.snp.makeConstraints { make in
  994. make.left.equalTo(goodTypeLabel.snp.right).offset(2.rpx)
  995. make.centerY.equalTo(goodTypeLabel.snp.centerY)
  996. }
  997. }
  998. }