149 lines
5.3 KiB
Swift
149 lines
5.3 KiB
Swift
//
|
|
// InviteViewControllers.swift
|
|
// suixinkan
|
|
//
|
|
// Created by Codex on 2026/6/26.
|
|
//
|
|
|
|
import SnapKit
|
|
import UIKit
|
|
|
|
/// 摄影师邀请页。
|
|
final class PhotographerInviteViewController: UIViewController {
|
|
private let services = AppServices.shared
|
|
private let viewModel = PhotographerInviteViewModel()
|
|
private let scrollView = UIScrollView()
|
|
private let contentStack = UIStackView()
|
|
private let codeLabel = UILabel()
|
|
private let urlLabel = UILabel()
|
|
private let qrImageView = UIImageView()
|
|
private let rulesLabel = UILabel()
|
|
private let activityIndicator = UIActivityIndicatorView(style: .medium)
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
title = "邀请摄影师"
|
|
view.backgroundColor = UIColor(hex: 0xF5F7FA)
|
|
setupUI()
|
|
viewModel.onChange = { [weak self] in self?.render() }
|
|
Task { await viewModel.reload(api: services.inviteAPI) }
|
|
}
|
|
|
|
private func setupUI() {
|
|
navigationItem.rightBarButtonItems = [
|
|
UIBarButtonItem(title: "复制码", style: .plain, target: self, action: #selector(copyCode)),
|
|
UIBarButtonItem(title: "复制链接", style: .plain, target: self, action: #selector(copyURL))
|
|
]
|
|
|
|
contentStack.axis = .vertical
|
|
contentStack.spacing = 12
|
|
scrollView.addSubview(contentStack)
|
|
view.addSubview(scrollView)
|
|
view.addSubview(activityIndicator)
|
|
|
|
scrollView.snp.makeConstraints { $0.edges.equalToSuperview() }
|
|
contentStack.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview().inset(16)
|
|
make.width.equalTo(scrollView.snp.width).offset(-32)
|
|
}
|
|
activityIndicator.snp.makeConstraints { $0.center.equalToSuperview() }
|
|
|
|
codeLabel.font = .systemFont(ofSize: 22, weight: .bold)
|
|
urlLabel.font = .systemFont(ofSize: 14)
|
|
urlLabel.numberOfLines = 0
|
|
urlLabel.textColor = AppDesign.textSecondary
|
|
qrImageView.contentMode = .scaleAspectFit
|
|
qrImageView.snp.makeConstraints { $0.height.equalTo(220) }
|
|
rulesLabel.numberOfLines = 0
|
|
rulesLabel.font = .systemFont(ofSize: 14)
|
|
rulesLabel.textColor = AppDesign.textSecondary
|
|
|
|
contentStack.addArrangedSubview(codeLabel)
|
|
contentStack.addArrangedSubview(urlLabel)
|
|
contentStack.addArrangedSubview(qrImageView)
|
|
contentStack.addArrangedSubview(rulesLabel)
|
|
}
|
|
|
|
private func render() {
|
|
activityIndicator.isHidden = !viewModel.loading
|
|
if viewModel.loading { activityIndicator.startAnimating() } else { activityIndicator.stopAnimating() }
|
|
codeLabel.text = viewModel.inviteCode.isEmpty ? "邀请码加载中..." : "邀请码:\(viewModel.inviteCode)"
|
|
urlLabel.text = viewModel.inviteUrl
|
|
qrImageView.image = viewModel.qrImage
|
|
rulesLabel.text = viewModel.rules.joined(separator: "\n")
|
|
if let error = viewModel.errorMessage {
|
|
rulesLabel.text = (rulesLabel.text ?? "") + "\n\n" + error
|
|
}
|
|
}
|
|
|
|
@objc private func copyCode() { viewModel.copyInviteCode() }
|
|
@objc private func copyURL() { viewModel.copyInviteUrl() }
|
|
}
|
|
|
|
extension PhotographerInviteViewModel: ViewModelBindable {}
|
|
|
|
/// 邀请记录页。
|
|
final class InviteRecordViewController: ModuleTableViewController {
|
|
private let viewModel = InviteRecordViewModel()
|
|
private let summaryLabel = UILabel()
|
|
|
|
override func viewDidLoad() {
|
|
title = "邀请记录"
|
|
navigationItem.rightBarButtonItem = UIBarButtonItem(
|
|
title: "奖励明细",
|
|
style: .plain,
|
|
target: self,
|
|
action: #selector(toggleTab)
|
|
)
|
|
super.viewDidLoad()
|
|
setupHeader()
|
|
viewModel.onChange = { [weak self] in
|
|
self?.updateSummary()
|
|
self?.reloadTable()
|
|
}
|
|
}
|
|
|
|
private func setupHeader() {
|
|
summaryLabel.font = .systemFont(ofSize: 14)
|
|
summaryLabel.textColor = AppDesign.textSecondary
|
|
summaryLabel.numberOfLines = 0
|
|
summaryLabel.textAlignment = .center
|
|
summaryLabel.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 56)
|
|
tableView.tableHeaderView = summaryLabel
|
|
}
|
|
|
|
override func tableRowCount() -> Int {
|
|
viewModel.displayRows.count
|
|
}
|
|
|
|
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
|
|
let row = viewModel.displayRows[indexPath.row]
|
|
cell.configure(
|
|
title: row.title,
|
|
subtitle: row.subtitle,
|
|
detail: row.amount.isEmpty ? row.time : "\(row.amount) · \(row.time)"
|
|
)
|
|
}
|
|
|
|
override func reloadContent() async {
|
|
await viewModel.reload(
|
|
inviteAPI: services.inviteAPI,
|
|
walletAPI: services.walletAPI,
|
|
refresh: true
|
|
)
|
|
updateSummary()
|
|
}
|
|
|
|
private func updateSummary() {
|
|
summaryLabel.text = "累计奖励 \(viewModel.totalRewardText) · 可提现 \(viewModel.withdrawableText)"
|
|
navigationItem.rightBarButtonItem?.title = viewModel.tab == .invite ? "奖励明细" : "邀请用户"
|
|
}
|
|
|
|
@objc private func toggleTab() {
|
|
Task {
|
|
let next: InviteRecordTab = viewModel.tab == .invite ? .reward : .invite
|
|
await viewModel.selectTab(next, inviteAPI: services.inviteAPI, walletAPI: services.walletAPI)
|
|
}
|
|
}
|
|
}
|