Initial commit: suixinkan_ios UIKit rewrite project.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -0,0 +1,148 @@
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user