|
|
@@ -0,0 +1,470 @@
|
|
|
+//
|
|
|
+// QSLVipTrialVC.swift
|
|
|
+// QuickSearchLocation
|
|
|
+//
|
|
|
+// Created by Destiny on 2025/10/23.
|
|
|
+//
|
|
|
+
|
|
|
+import UIKit
|
|
|
+import YYText
|
|
|
+
|
|
|
+enum QSLTrialVipJumpType: Int {
|
|
|
+
|
|
|
+ case notiPush
|
|
|
+ case shortcut
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+class QSLVipTrialVC: QSLBaseController {
|
|
|
+
|
|
|
+ var type: QSLTrialVipJumpType?
|
|
|
+ var selectGood: QSLGoodModel?
|
|
|
+
|
|
|
+ override func viewDidLoad() {
|
|
|
+ super.viewDidLoad()
|
|
|
+ setUI()
|
|
|
+ requestNetwork()
|
|
|
+ }
|
|
|
+
|
|
|
+ func requestNetwork() {
|
|
|
+ // 网络请求时使用 itemListDict 作为参数(关键修复)
|
|
|
+ QSLNetwork().request(.wakeupTrialList(dict: [String: Any]())) {[weak self] response in
|
|
|
+ // 后续逻辑不变...
|
|
|
+ let list = response.mapArray(QSLGoodModel.self, modelKey: "data>list")
|
|
|
+
|
|
|
+ if list.count > 0 {
|
|
|
+ self?.selectGood = list[0]
|
|
|
+
|
|
|
+ self?.desLabel.text = self?.selectGood?.content ?? ""
|
|
|
+
|
|
|
+ //初始化
|
|
|
+ if(QSLCountdownManager.shared.trialSeconds == -999){
|
|
|
+ QSLCountdownManager.shared.trialSeconds = 900 * 1000
|
|
|
+ }
|
|
|
+ QSLCountdownManager.shared.updateTrialHandler = { [weak self] timeString in
|
|
|
+ self?.countdownLabel.updateCountdownText(timeString)
|
|
|
+ }
|
|
|
+ QSLCountdownManager.shared.startCountdown()
|
|
|
+
|
|
|
+ NotificationCenter.default.post(
|
|
|
+ name: Notification.Name("QSLHomeUpdateCouponViewNoti"),
|
|
|
+ object: nil,
|
|
|
+ userInfo: ["showCoupon": true, "couponType":"1"]
|
|
|
+ )
|
|
|
+ }
|
|
|
+ } fail: { code, error in
|
|
|
+ self.view.toast(text: "加载商品列表失败")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复按钮点击
|
|
|
+ @objc func resumeBtnAction() {
|
|
|
+
|
|
|
+ let memberModel = QSLBaseManager.shared.userModel.memberModel
|
|
|
+ let expired = memberModel.expired
|
|
|
+ if !expired {
|
|
|
+ QSLLoading.success(text: "您已经在订阅中,无需恢复")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ QSLLoading.show()
|
|
|
+ QSLVipManager.shared.restoreAction { isSuccess in
|
|
|
+ QSLVipManager.shared.isPaying = false
|
|
|
+ if isSuccess {
|
|
|
+
|
|
|
+ QSLNetwork().request(.userMember(dict: [:])) { response in
|
|
|
+
|
|
|
+ let model = response.mapObject(QSLMemberModel.self, modelKey: "data")
|
|
|
+ QSLBaseManager.shared.userModel.memberModel = model
|
|
|
+
|
|
|
+ if model.expired {
|
|
|
+ QSLBaseManager.shared.saveVipExpiredTime(time: 0)
|
|
|
+ } else {
|
|
|
+ QSLBaseManager.shared.saveVipExpiredTime(time: model.endTimestamp)
|
|
|
+ }
|
|
|
+
|
|
|
+ QSLBaseManager.shared.saveUserId(id: model.userId)
|
|
|
+
|
|
|
+ if model.endTimestamp > memberModel.endTimestamp {
|
|
|
+ QSLLoading.success(text: "恢复成功")
|
|
|
+ // 支付成功通知
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
|
|
|
+ self.navigationController?.popViewController(animated: true)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ QSLLoading.error(text: "没有可供恢复的订阅")
|
|
|
+ }
|
|
|
+
|
|
|
+ } fail: { code, error in
|
|
|
+ QSLLoading.error(text: "没有可供恢复的订阅")
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ QSLLoading.error(text: "没有可供恢复的订阅")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @objc func payBtnAction(){
|
|
|
+ let memberModel = QSLBaseManager.shared.userModel.memberModel
|
|
|
+
|
|
|
+ if let subscriptionExpired = memberModel.subscriptionExpired, !subscriptionExpired {
|
|
|
+ UIApplication.keyWindow?.toast(text: "你已经订阅了")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ guard let currentGood = selectGood else { return }
|
|
|
+
|
|
|
+ QSLLoading.show()
|
|
|
+ QSLVipManager.shared.startPay(goods: currentGood) { status, outTradeNo in
|
|
|
+ QSLVipManager.shared.isPaying = false
|
|
|
+ if status == .success {
|
|
|
+ QSLLoading.success(text: "支付成功")
|
|
|
+
|
|
|
+ // 引力传递支付事件
|
|
|
+ gravityInstance?.trackPayEvent(withAmount: Int32(currentGood.amount), withPayType: "CNY", withOrderId: outTradeNo, withPayReason: currentGood.name, withPayMethod: "apple")
|
|
|
+
|
|
|
+ QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "success","pay_amount":Int32(currentGood.amount)])
|
|
|
+
|
|
|
+ QSEventHandle.gravityPush(eventName: QSLGravityConst.vip_submit_success, eventProps: ["id": 01001])
|
|
|
+
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
|
+ NotificationCenter.default.post(name: QSLNotification.QSLRefreshMember, object: nil)
|
|
|
+
|
|
|
+ if(!QSLBaseManager.shared.isLogin()){
|
|
|
+ QSLJumpManager.shared.pushToLogin(type: .member)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ } else if status == .cancel {
|
|
|
+ QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "cancel","pay_amount":Int32(currentGood.amount)])
|
|
|
+ QSLLoading.error(text: "支付取消")
|
|
|
+ } else if status == .fail {
|
|
|
+ QSEventHandle.eventPush(eventName: QSLGravityConst.new_vip_result, eventProps: ["is_member":QSLBaseManager.shared.isVip(),"purchase_result": "fail","pay_amount":Int32(currentGood.amount)])
|
|
|
+ QSLLoading.error(text: "支付失败")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @objc func privacyAction() {
|
|
|
+
|
|
|
+ let vc = QSLWebViewController()
|
|
|
+ vc.webUrl = QSLConfig.AppPrivacyAgreementLink
|
|
|
+ vc.title = "隐私政策"
|
|
|
+ self.present(vc, animated: true)
|
|
|
+ }
|
|
|
+
|
|
|
+ @objc func serviceAction() {
|
|
|
+
|
|
|
+ let vc = QSLWebViewController()
|
|
|
+ vc.webUrl = QSLConfig.AppServiceAgreementLink
|
|
|
+ vc.title = "服务协议"
|
|
|
+ self.present(vc, animated: true)
|
|
|
+ }
|
|
|
+
|
|
|
+ func setUI(){
|
|
|
+
|
|
|
+ self.view.addSubview(bottomSpaceView)
|
|
|
+ bottomSpaceView.snp.makeConstraints { make in
|
|
|
+ make.left.right.bottom.equalTo(0)
|
|
|
+ make.height.equalTo(QSLConst.qsl_kTabbarBottom/2+1)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.view.addSubview(bottomBgView)
|
|
|
+ bottomBgView.snp.makeConstraints { make in
|
|
|
+ make.left.right.equalTo(0)
|
|
|
+ make.bottom.equalTo(bottomSpaceView.snp.top).offset(0)
|
|
|
+ make.height.equalTo(QSLConst.qsl_kScreenW/1.4)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.view.addSubview(bgImageView)
|
|
|
+ bgImageView.snp.makeConstraints { make in
|
|
|
+ make.left.top.right.equalTo(0)
|
|
|
+ make.bottom.equalTo(bottomBgView.snp.top).offset(50.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ bgImageView.addSubview(bgTopTit1View)
|
|
|
+ bgTopTit1View.snp.makeConstraints { make in
|
|
|
+ make.centerX.equalTo(bgImageView.snp.centerX)
|
|
|
+ make.top.equalTo(QSLConst.qsl_kNavFrameH+20.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ bgImageView.addSubview(bgTopTit2View)
|
|
|
+ bgTopTit2View.snp.makeConstraints { make in
|
|
|
+ make.centerX.equalTo(bgImageView.snp.centerX)
|
|
|
+ make.top.equalTo(bgTopTit1View.snp.bottom).offset(1)
|
|
|
+ }
|
|
|
+
|
|
|
+ bgImageView.addSubview(desLabel)
|
|
|
+ desLabel.snp.makeConstraints { make in
|
|
|
+ make.right.left.equalTo(0)
|
|
|
+ make.height.equalTo(17.rpx)
|
|
|
+ make.top.equalTo(bgTopTit2View.snp.bottom).offset(6.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ bgImageView.addSubview(bgCenterView)
|
|
|
+ bgCenterView.snp.makeConstraints { make in
|
|
|
+ make.centerX.equalTo(bgImageView.snp.centerX)
|
|
|
+ make.bottom.equalTo(0)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.view.addSubview(vipNaviView)
|
|
|
+ vipNaviView.snp.makeConstraints { make in
|
|
|
+ make.top.left.right.equalTo(0)
|
|
|
+ make.height.equalTo(QSLConst.qsl_kNavFrameH)
|
|
|
+ }
|
|
|
+
|
|
|
+ vipNaviView.addSubview(backButton)
|
|
|
+ backButton.snp.makeConstraints { make in
|
|
|
+ make.width.equalTo(44.rpx)
|
|
|
+ make.height.equalTo(44.rpx)
|
|
|
+ make.left.equalTo(10.rpx)
|
|
|
+ make.top.equalTo(QSLConst.qsl_kStatusBarFrameH)
|
|
|
+ }
|
|
|
+
|
|
|
+ vipNaviView.addSubview(naviTitleIcon)
|
|
|
+ naviTitleIcon.snp.makeConstraints { make in
|
|
|
+ make.centerX.equalToSuperview()
|
|
|
+ make.width.equalTo(100.rpx)
|
|
|
+ make.height.equalTo(20.rpx)
|
|
|
+ make.centerY.equalTo(backButton.snp.centerY)
|
|
|
+ }
|
|
|
+
|
|
|
+ vipNaviView.addSubview(naviResumeBtn)
|
|
|
+ naviResumeBtn.snp.makeConstraints { make in
|
|
|
+ make.size.equalTo(CGSize(width: 70.rpx, height: 18.rpx))
|
|
|
+ make.right.equalTo(-8.rpx)
|
|
|
+ make.centerY.equalTo(backButton.snp.centerY)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.bottomBgView.addSubview(bottomTitleView)
|
|
|
+ bottomTitleView.snp.makeConstraints { make in
|
|
|
+ make.top.equalTo(50.rpx)
|
|
|
+ make.left.equalTo(32.rpx)
|
|
|
+ make.right.equalTo(-32.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ self.bottomBgView.addSubview(bottomBtnView)
|
|
|
+ bottomBtnView.snp.makeConstraints { make in
|
|
|
+ make.top.equalTo(bottomTitleView.snp.bottom).offset(20.rpx)
|
|
|
+ make.left.right.bottom.equalTo(0)
|
|
|
+ }
|
|
|
+
|
|
|
+ bottomBtnView.addSubview(countdownView)
|
|
|
+ countdownView.snp.makeConstraints { make in
|
|
|
+ make.top.equalTo(0)
|
|
|
+ make.left.equalTo(12.rpx)
|
|
|
+ make.right.equalTo(-12.rpx)
|
|
|
+ make.height.equalTo(47.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ countdownView.addSubview(countdownLabel)
|
|
|
+ countdownLabel.snp.makeConstraints { make in
|
|
|
+ make.left.right.equalTo(0)
|
|
|
+ make.top.equalTo(5.rpx)
|
|
|
+ make.height.equalTo(17.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ bottomBtnView.addSubview(unlockBtn)
|
|
|
+ unlockBtn.snp.makeConstraints { make in
|
|
|
+ make.left.equalTo(12.rpx)
|
|
|
+ make.right.equalTo(-12.rpx)
|
|
|
+ make.height.equalTo(50.rpx)
|
|
|
+ make.top.equalTo(25.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ bottomBtnView.addSubview(serviceLabel)
|
|
|
+ serviceLabel.snp.makeConstraints { make in
|
|
|
+ make.right.left.equalTo(0)
|
|
|
+ make.height.equalTo(17.rpx)
|
|
|
+ make.top.equalTo(unlockBtn.snp.bottom).offset(8.rpx)
|
|
|
+ }
|
|
|
+
|
|
|
+ updateServiceLabelText()
|
|
|
+
|
|
|
+ self.view.bringSubviewToFront(bottomBgView)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新服务条款文本内容
|
|
|
+ func updateServiceLabelText() {
|
|
|
+ let attr = NSMutableAttributedString()
|
|
|
+
|
|
|
+ // 固定部分:购买即同意
|
|
|
+ let firstAttr = NSMutableAttributedString(string: "购买前请先阅读")
|
|
|
+ firstAttr.font(11)
|
|
|
+ firstAttr.color(UIColor.init(white: 0, alpha: 0.4))
|
|
|
+ attr.append(firstAttr)
|
|
|
+
|
|
|
+ // 《隐私权政策》
|
|
|
+ let privacyHL = YYTextHighlight()
|
|
|
+ let privacyStr = "隐私政策"
|
|
|
+ let privacyText = NSMutableAttributedString(string: privacyStr)
|
|
|
+ privacyText.font(11)
|
|
|
+ privacyText.color(UIColor.init(white: 0, alpha: 0.7))
|
|
|
+ privacyText.yy_setTextHighlight(privacyHL, range: NSRange(location: 0, length: privacyStr.count))
|
|
|
+ privacyHL.tapAction = { [weak self] containerView, text, range, rect in
|
|
|
+ self?.privacyAction()
|
|
|
+ }
|
|
|
+ let underline1 = YYTextDecoration(style: .single, width: 1, color: UIColor(white: 0, alpha: 0.7))
|
|
|
+ privacyText.yy_textUnderline = underline1
|
|
|
+
|
|
|
+ attr.append(privacyText)
|
|
|
+
|
|
|
+ let blankAttr = NSMutableAttributedString(string: "&")
|
|
|
+ blankAttr.color(UIColor.init(white: 0, alpha: 0.4))
|
|
|
+ blankAttr.font(11)
|
|
|
+ attr.append(blankAttr)
|
|
|
+
|
|
|
+ // 《用户协议》
|
|
|
+ let serviceHL = YYTextHighlight()
|
|
|
+ let serviceStr = "服务条款"
|
|
|
+ let serviceText = NSMutableAttributedString(string: serviceStr)
|
|
|
+ serviceText.font(11)
|
|
|
+ serviceText.color(UIColor.init(white: 0, alpha: 0.7))
|
|
|
+ serviceText.yy_setTextHighlight(serviceHL, range: NSRange(location: 0, length: serviceStr.count))
|
|
|
+ serviceHL.tapAction = { [weak self] containerView, text, range, rect in
|
|
|
+ self?.serviceAction()
|
|
|
+ }
|
|
|
+ let underline = YYTextDecoration(style: .single, width: 1, color: UIColor(white: 0, alpha: 0.7))
|
|
|
+ serviceText.yy_textUnderline = underline
|
|
|
+
|
|
|
+ attr.append(serviceText)
|
|
|
+
|
|
|
+ serviceLabel.attributedText = attr
|
|
|
+ serviceLabel.textAlignment = .center
|
|
|
+ }
|
|
|
+
|
|
|
+ lazy var vipNaviView: UIView = {
|
|
|
+ let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW, QSLConst.qsl_kScreenH))
|
|
|
+ view.addCorner(conrners: [.topLeft,.topRight], radius: 12.rpx)
|
|
|
+ view.backgroundColor = UIColor.clear
|
|
|
+ return view
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var naviTitleIcon: UILabel = {
|
|
|
+ let label = UILabel()
|
|
|
+ label.text("超值福利")
|
|
|
+ label.textColor = .white
|
|
|
+ label.mediumFont(17)
|
|
|
+ label.textAlignment = .center
|
|
|
+ return label
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var naviResumeBtn: UIButton = {
|
|
|
+ let button = UIButton()
|
|
|
+ button.title("恢复订阅")
|
|
|
+ button.setTitleColor(.white, for: .normal)
|
|
|
+ button.titleLabel?.font = UIFont.systemFont(ofSize: 11, weight: .medium)
|
|
|
+ button.image(UIImage(named: "vip_resume_btn")?.withTintColor(UIColor.white))
|
|
|
+ button.setImageTitleLayout(.imgLeft, spacing: 2.rpx)
|
|
|
+ button.addTarget(self, action: #selector(resumeBtnAction), for: .touchUpInside)
|
|
|
+ return button
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var backButton: UIButton = {
|
|
|
+ let button = UIButton()
|
|
|
+ button.image(UIImage(named: "vip_pay_failure_close"))
|
|
|
+ button.addTarget(self, action: #selector(backBtnAction), for: .touchUpInside)
|
|
|
+ return button
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bgImageView: UIImageView = {
|
|
|
+ let item = UIImageView()
|
|
|
+ item.contentMode = .scaleAspectFill
|
|
|
+ item.image = UIImage(named: "vip_trial_top")
|
|
|
+ item.layer.masksToBounds = true
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bgTopTit1View: UIImageView = {
|
|
|
+ let item = UIImageView()
|
|
|
+ item.contentMode = .scaleAspectFit
|
|
|
+ item.image = UIImage(named: "vip_trial_top_title_1")
|
|
|
+ item.layer.masksToBounds = true
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bgTopTit2View: UIImageView = {
|
|
|
+ let item = UIImageView()
|
|
|
+ item.contentMode = .scaleAspectFit
|
|
|
+ item.image = UIImage(named: "vip_trial_top_title_2")
|
|
|
+ item.layer.masksToBounds = true
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bgCenterView: UIImageView = {
|
|
|
+ let item = UIImageView()
|
|
|
+ item.contentMode = .scaleAspectFit
|
|
|
+ item.image = UIImage(named: "vip_trial_center")
|
|
|
+ item.layer.masksToBounds = true
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bottomSpaceView: UIView = {
|
|
|
+ let item = UIView()
|
|
|
+ item.backgroundColor = .white
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bottomBgView: UIImageView = {
|
|
|
+ let item = UIImageView()
|
|
|
+ item.contentMode = .scaleAspectFill
|
|
|
+ item.image = UIImage(named: "vip_trial_bottom_bg")
|
|
|
+ item.layer.masksToBounds = true
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bottomTitleView: UIImageView = {
|
|
|
+ let item = UIImageView()
|
|
|
+ item.image = UIImage(named: "vip_trial_bottom_title")
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bottomBtnView: UIView = {
|
|
|
+ let item = UIView()
|
|
|
+ return item
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var bottomView: UIView = {
|
|
|
+ let view = UIView()
|
|
|
+ view.backgroundColor = UIColor.white
|
|
|
+ return view
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var countdownView: UIView = {
|
|
|
+ let view = UIView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW - 24.rpx, 47.rpx))
|
|
|
+ view.addCorner(conrners: [.topLeft,.topRight], radius: 30.rpx)
|
|
|
+ view.backgroundColor = .hexStringColor(hexString: "#FFFED8")
|
|
|
+ return view
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var countdownLabel: QSLCountdownView = {
|
|
|
+ let label = QSLCountdownView(frame: CGRectMake(0, 0, QSLConst.qsl_kScreenW - 24.rpx, 17.rpx),type: 2)
|
|
|
+ return label
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var unlockBtn: UIButton = {
|
|
|
+ let btn = UIButton()
|
|
|
+ btn.gradientBackgroundColor(color1: .hexStringColor(hexString: "#0E5E61"), color2: .hexStringColor(hexString: "#00434E"), width: QSLConst.qsl_kScreenW - 24.rpx, height: 50.rpx, direction: .horizontal)
|
|
|
+ btn.addRadius(radius: 25.rpx)
|
|
|
+ btn.title("立即领取")
|
|
|
+ btn.textColor(.hexStringColor(hexString: "#FFF8EF"))
|
|
|
+ btn.mediumFont(18)
|
|
|
+ btn.addTarget(self, action: #selector(payBtnAction), for: .touchUpInside)
|
|
|
+ return btn
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var serviceLabel: YYLabel = {
|
|
|
+ let label = YYLabel()
|
|
|
+ label.textAlignment = .center
|
|
|
+ return label
|
|
|
+ }()
|
|
|
+
|
|
|
+ lazy var desLabel: YYLabel = {
|
|
|
+ let label = YYLabel()
|
|
|
+ label.textAlignment = .center
|
|
|
+ label.textColor = UIColor.init(white: 1, alpha: 0.4)
|
|
|
+ label.font = UIFont.systemFont(ofSize: 12)
|
|
|
+ return label
|
|
|
+ }()
|
|
|
+}
|