jsdw_ios/QuickLocation/Section/PopupWindow/PromotionalActivitiesView.s...

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
}
}