322 lines
10 KiB
Swift
322 lines
10 KiB
Swift
//
|
|
// PromotionalActivitiesView.swift
|
|
// QuickLocation
|
|
//
|
|
// Created by 八条 on 2026/7/3.
|
|
//
|
|
|
|
import UIKit
|
|
import RxSwift
|
|
import RxCocoa
|
|
|
|
class PromotionalActivitiesView: UIView {
|
|
|
|
var disposeBag = DisposeBag()
|
|
|
|
private func setupRx() {
|
|
backBtn.rx.tap.subscribe(onNext: { _ in
|
|
VipWaivePopView.show()
|
|
}).disposed(by: disposeBag)
|
|
|
|
}
|
|
|
|
private func setupUI() {
|
|
addSubview(scrollView)
|
|
|
|
addSubview(navBarView)
|
|
navBarView.addSubview(navTitleLabel)
|
|
addSubview(backBtn)
|
|
|
|
navBarView.layoutChain
|
|
.edges(excludingEdge: .bottom)
|
|
.height(kNaviHeight)
|
|
|
|
navTitleLabel.layoutChain
|
|
.top(kStatusBarHeight + 12)
|
|
.centerY(backBtn)
|
|
.centerX()
|
|
|
|
backBtn.layoutChain
|
|
.top(kStatusBarHeight + 12)
|
|
.left(15)
|
|
.width(24)
|
|
.height(24)
|
|
|
|
addSubview(bottomView)
|
|
bottomView.layoutChain
|
|
.edges(excludingEdge: .top)
|
|
.height(120)
|
|
|
|
scrollView.layoutChain
|
|
.edges(excludingEdge: .bottom)
|
|
.bottomToTopOfView(bottomView)
|
|
}
|
|
|
|
lazy var navBarView: UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = .white
|
|
view.alpha = 0
|
|
return view
|
|
}()
|
|
|
|
lazy var navTitleLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.text = "超值优惠"
|
|
label.font = .systemFont(ofSize: 18, weight: .medium)
|
|
label.textColor = ThemeManager.shared.color.titleAuxColor
|
|
label.textAlignment = .center
|
|
return label
|
|
}()
|
|
|
|
lazy var backBtn: UIButton = {
|
|
let btn = UIButton(type: .custom)
|
|
btn.setImage(UIImage(named: "Common/back"), for: .normal)
|
|
btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 15, right: 100)
|
|
return btn
|
|
}()
|
|
|
|
lazy var scrollView: UIScrollView = {
|
|
let view = UIScrollView()
|
|
view.backgroundColor = UIColor(hexStr: "#F6F9FB")
|
|
view.showsVerticalScrollIndicator = false
|
|
view.delegate = self
|
|
view.bounces = false
|
|
view.contentInsetAdjustmentBehavior = .never
|
|
|
|
view.addSubview(scrollContentView)
|
|
scrollContentView.layoutChain
|
|
.edges().widthToView(view)
|
|
|
|
let headerBgImgView = UIImageView(image: UIImage(named: "PromotionalActivities/header_bg"))
|
|
headerBgImgView.contentMode = .scaleAspectFill
|
|
|
|
scrollContentView.addSubview(headerBgImgView)
|
|
headerBgImgView.layoutChain
|
|
.edges(excludingEdge: .bottom)
|
|
.heightToWidth(285/375)
|
|
|
|
let infoView = UIView()
|
|
infoView.backgroundColor = UIColor(hexStr: "#F6F9FB")
|
|
infoView.layer.cornerRadius = 30
|
|
|
|
scrollContentView.addSubview(infoView)
|
|
infoView.layoutChain
|
|
.topToBottomOfView(headerBgImgView, offset: -65)
|
|
.edges(excludingEdge: .top)
|
|
|
|
let iconView = UIImageView(image: UIImage(named: "PromotionalActivities/vip_icon"))
|
|
infoView.addSubview(iconView)
|
|
iconView.layoutChain
|
|
.top(20)
|
|
.left(15)
|
|
.width(20)
|
|
.heightToWidth(1)
|
|
|
|
let titleLab = UILabel()
|
|
titleLab.text = "即刻加入会员"
|
|
titleLab.font = .systemFont(ofSize: 16, weight: .semibold)
|
|
titleLab.textColor = UIColor(hexStr: "#333333")
|
|
infoView.addSubview(titleLab)
|
|
titleLab.layoutChain
|
|
.leftToRightOfView(iconView, offset: 4)
|
|
.centerY(iconView)
|
|
|
|
let agreementView = UIView()
|
|
infoView.addSubview(agreementView)
|
|
agreementView.layoutChain
|
|
.topToBottomOfView(titleLab, offset: 18)
|
|
.left(15)
|
|
.right(15)
|
|
.height(30)
|
|
|
|
agreementView.addSubview(agreementCheckBtn)
|
|
agreementCheckBtn.layoutChain
|
|
.left(0)
|
|
.centerY()
|
|
.width(16)
|
|
.height(16)
|
|
|
|
agreementView.addSubview(agreementTextView)
|
|
agreementTextView.layoutChain
|
|
.leftToRightOfView(agreementCheckBtn, offset: 6)
|
|
.right(0)
|
|
.centerY()
|
|
.bottom(0)
|
|
|
|
let benefitsImgView = UIImageView(image: UIImage(named: "PromotionalActivities/benefits"))
|
|
benefitsImgView.contentMode = .scaleAspectFill
|
|
infoView.addSubview(benefitsImgView)
|
|
benefitsImgView.layoutChain
|
|
.topToBottomOfView(agreementView, offset: 20)
|
|
.edgesHorzontal(15)
|
|
.bottom(15, relation: .greaterThanOrEqual)
|
|
.heightToWidth(148/375)
|
|
|
|
return view
|
|
}()
|
|
|
|
lazy var scrollContentView: UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = .clear
|
|
return view
|
|
}()
|
|
|
|
lazy var bottomView: UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = .white
|
|
|
|
view.addSubview(countdownLabel)
|
|
countdownLabel.layoutChain
|
|
.top(11)
|
|
.centerX()
|
|
|
|
view.addSubview(confirmBtn)
|
|
confirmBtn.layoutChain
|
|
.edgesHorzontal(30)
|
|
.bottom(35)
|
|
.height(50)
|
|
|
|
return view
|
|
}()
|
|
|
|
lazy var agreementCheckBtn: UIButton = {
|
|
let btn = UIButton(type: .custom)
|
|
btn.setImage(UIImage(named: "Common/checkbox"), for: .normal)
|
|
btn.setImage(UIImage(named: "Common/checkbox_on"), for: .selected)
|
|
btn.rx.tap.subscribe(onNext: { [weak btn] in
|
|
btn?.isSelected.toggle()
|
|
}).disposed(by: disposeBag)
|
|
return btn
|
|
}()
|
|
|
|
lazy var agreementTextView: UITextView = {
|
|
let tv = UITextView()
|
|
tv.isEditable = false
|
|
tv.isScrollEnabled = false
|
|
tv.backgroundColor = .clear
|
|
tv.textContainerInset = .zero
|
|
tv.textContainer.lineFragmentPadding = 0
|
|
tv.delegate = self
|
|
let text = "购买前请先阅读隐私政策和服务条款"
|
|
let attr = NSMutableAttributedString(string: text, attributes: [
|
|
.font: UIFont.systemFont(ofSize: 12),
|
|
.foregroundColor: UIColor(hexStr: "#999999")
|
|
])
|
|
let privacyRange = (text as NSString).range(of: "隐私政策")
|
|
let termsRange = (text as NSString).range(of: "服务条款")
|
|
let linkColor = UIColor(hexStr: "#16B3FF")
|
|
attr.addAttributes([.foregroundColor: linkColor, .link: URLManager.shared.privacyPolicyUrl], range: privacyRange)
|
|
attr.addAttributes([.foregroundColor: linkColor, .link: URLManager.shared.userAgreementUrl], range: termsRange)
|
|
tv.attributedText = attr
|
|
tv.linkTextAttributes = [.foregroundColor: linkColor]
|
|
return tv
|
|
}()
|
|
|
|
lazy var countdownLabel: UILabel = {
|
|
let label = UILabel()
|
|
label.textAlignment = .center
|
|
return label
|
|
}()
|
|
|
|
lazy var confirmBtn: UIButton = {
|
|
let btn = UIButton(type: .custom)
|
|
btn.setTitle("立即开通", for: .normal)
|
|
btn.setTitleColor(.white, for: .normal)
|
|
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
|
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
|
|
btn.cornerRadius = 25
|
|
return btn
|
|
}()
|
|
|
|
private var countdownEndTime: TimeInterval = 0
|
|
private var countdownTimer: Timer?
|
|
|
|
func startCountdown(endTime: TimeInterval) {
|
|
countdownEndTime = endTime
|
|
updateCountdown()
|
|
countdownTimer?.invalidate()
|
|
countdownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
|
|
self?.updateCountdown()
|
|
}
|
|
}
|
|
|
|
private func stopCountdown() {
|
|
countdownTimer?.invalidate()
|
|
countdownTimer = nil
|
|
}
|
|
|
|
private func updateCountdown() {
|
|
let remaining = max(0, countdownEndTime - Date().timeIntervalSince1970)
|
|
let totalSeconds = Int(remaining)
|
|
let days = totalSeconds / 86400
|
|
let hours = (totalSeconds % 86400) / 3600
|
|
let minutes = (totalSeconds % 3600) / 60
|
|
let seconds = totalSeconds % 60
|
|
|
|
let attr = NSMutableAttributedString()
|
|
|
|
let normalStyle: [NSAttributedString.Key: Any] = [
|
|
.foregroundColor: UIColor(hexStr: "#FD501B"),
|
|
.font: UIFont.systemFont(ofSize: 12)
|
|
]
|
|
let timeStyle: [NSAttributedString.Key: Any] = [
|
|
.foregroundColor: UIColor.white,
|
|
.font: UIFont.systemFont(ofSize: 12),
|
|
.backgroundColor: UIColor(hexStr: "#FD501B")
|
|
]
|
|
|
|
attr.append(NSAttributedString(string: "优惠活动倒计时 ", attributes: normalStyle))
|
|
|
|
let timeStr: String
|
|
if days > 0 {
|
|
timeStr = String(format: "%d天%02d:%02d:%02d", days, hours, minutes, seconds)
|
|
} else {
|
|
timeStr = String(format: "%02d:%02d:%02d", hours, minutes, seconds)
|
|
}
|
|
attr.append(NSAttributedString(string: timeStr, attributes: timeStyle))
|
|
|
|
attr.append(NSAttributedString(string: " 限时特惠", attributes: normalStyle))
|
|
|
|
countdownLabel.attributedText = attr
|
|
}
|
|
|
|
override func layoutSubviews() {
|
|
super.layoutSubviews()
|
|
}
|
|
|
|
override func willMove(toSuperview newSuperview: UIView?) {
|
|
super.willMove(toSuperview: newSuperview)
|
|
if newSuperview == nil {
|
|
stopCountdown()
|
|
}
|
|
}
|
|
|
|
override init(frame: CGRect) {
|
|
super.init(frame: .zero)
|
|
backgroundColor = .white
|
|
setupUI()
|
|
setupRx()
|
|
}
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|
|
|
|
// MARK: - UIScrollViewDelegate
|
|
extension PromotionalActivitiesView: UIScrollViewDelegate {
|
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
let maxY = scrollView.contentOffset.y
|
|
let alpha = maxY / kNaviHeight
|
|
navBarView.alpha = alpha < 0.0 ? 0.0 : alpha
|
|
}
|
|
}
|
|
|
|
// MARK: - UITextViewDelegate
|
|
extension PromotionalActivitiesView: UITextViewDelegate {
|
|
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
|
|
AppRouter.push(Route.web, userInfo: ["url": URL.absoluteString])
|
|
return false
|
|
}
|
|
}
|