QSLVipController.swift 47 KB

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