QSLVipController.swift 47 KB

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