153 lines
5.4 KiB
Swift
153 lines
5.4 KiB
Swift
//
|
|
// ScenicQueueSettingChangeLogViewController.swift
|
|
// suixinkan
|
|
//
|
|
|
|
import SnapKit
|
|
import UIKit
|
|
|
|
/// 排队设置配置日志页。
|
|
final class ScenicQueueSettingChangeLogViewController: BaseViewController {
|
|
private let viewModel = ScenicQueueSettingChangeLogViewModel()
|
|
private let api: ScenicQueueAPIProtocol
|
|
private let tableView = UITableView(frame: .zero, style: .plain)
|
|
private let emptyLabel = UILabel()
|
|
|
|
@MainActor
|
|
init(api: ScenicQueueAPIProtocol? = nil) {
|
|
self.api = api ?? NetworkServices.shared.scenicQueueAPI
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
Task { await viewModel.refresh(api: api) }
|
|
}
|
|
|
|
override func setupNavigationBar() {
|
|
title = "配置日志"
|
|
}
|
|
|
|
override func setupUI() {
|
|
view.backgroundColor = ScenicQueueTokens.pageBackground
|
|
tableView.backgroundColor = .clear
|
|
tableView.separatorStyle = .none
|
|
tableView.rowHeight = UITableView.automaticDimension
|
|
tableView.estimatedRowHeight = 120
|
|
tableView.delegate = self
|
|
tableView.dataSource = self
|
|
tableView.register(ScenicQueueLogCell.self, forCellReuseIdentifier: ScenicQueueLogCell.reuseIdentifier)
|
|
tableView.refreshControl = UIRefreshControl()
|
|
tableView.refreshControl?.addTarget(self, action: #selector(refreshPulled), for: .valueChanged)
|
|
emptyLabel.text = "暂无配置变更记录"
|
|
emptyLabel.textColor = AppColor.textTertiary
|
|
emptyLabel.font = ScenicQueueTokens.emptyStateFont
|
|
emptyLabel.textAlignment = .center
|
|
view.addSubview(tableView)
|
|
view.addSubview(emptyLabel)
|
|
}
|
|
|
|
override func setupConstraints() {
|
|
tableView.snp.makeConstraints { make in
|
|
make.edges.equalTo(view.safeAreaLayoutGuide)
|
|
}
|
|
emptyLabel.snp.makeConstraints { make in
|
|
make.center.equalToSuperview()
|
|
}
|
|
}
|
|
|
|
override func bindActions() {
|
|
viewModel.onStateChange = { [weak self] in
|
|
Task { @MainActor in self?.applyState() }
|
|
}
|
|
viewModel.onShowMessage = { [weak self] message in
|
|
Task { @MainActor in self?.showToast(message) }
|
|
}
|
|
}
|
|
|
|
private func applyState() {
|
|
tableView.refreshControl?.endRefreshing()
|
|
tableView.reloadData()
|
|
emptyLabel.isHidden = !viewModel.items.isEmpty
|
|
}
|
|
|
|
@objc private func refreshPulled() {
|
|
Task { await viewModel.refresh(api: api) }
|
|
}
|
|
}
|
|
|
|
extension ScenicQueueSettingChangeLogViewController: UITableViewDataSource, UITableViewDelegate {
|
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
viewModel.items.count
|
|
}
|
|
|
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
let cell = tableView.dequeueReusableCell(withIdentifier: ScenicQueueLogCell.reuseIdentifier, for: indexPath) as! ScenicQueueLogCell
|
|
cell.configure(item: viewModel.items[indexPath.row])
|
|
return cell
|
|
}
|
|
|
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
|
guard scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height - 120 else { return }
|
|
Task { await viewModel.loadMore(api: api) }
|
|
}
|
|
}
|
|
|
|
/// 配置日志 cell。
|
|
final class ScenicQueueLogCell: UITableViewCell {
|
|
static let reuseIdentifier = "ScenicQueueLogCell"
|
|
|
|
private let card = UIView()
|
|
private let titleLabel = UILabel()
|
|
private let detailLabel = UILabel()
|
|
private let timeLabel = UILabel()
|
|
|
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
setupUI()
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
func configure(item: ScenicQueueSettingChangeLogItem) {
|
|
titleLabel.text = item.operatorName.isEmpty ? "配置变更" : item.operatorName
|
|
detailLabel.text = item.displayText.isEmpty ? item.summary : item.displayText
|
|
timeLabel.text = item.createdAt
|
|
}
|
|
|
|
private func setupUI() {
|
|
selectionStyle = .none
|
|
backgroundColor = .clear
|
|
card.backgroundColor = .white
|
|
card.layer.cornerRadius = ScenicQueueTokens.radiusCard
|
|
card.layer.borderWidth = 1
|
|
card.layer.borderColor = ScenicQueueTokens.cardOutline.cgColor
|
|
contentView.addSubview(card)
|
|
titleLabel.font = ScenicQueueTokens.settingsSectionTitleFont
|
|
titleLabel.textColor = AppColor.textPrimary
|
|
detailLabel.font = ScenicQueueTokens.settingsRowTitleFont
|
|
detailLabel.textColor = AppColor.textSecondary
|
|
detailLabel.numberOfLines = 0
|
|
timeLabel.font = ScenicQueueTokens.settingsHintFont
|
|
timeLabel.textColor = AppColor.textTertiary
|
|
let stack = UIStackView(arrangedSubviews: [titleLabel, detailLabel, timeLabel])
|
|
stack.axis = .vertical
|
|
stack.spacing = 8
|
|
card.addSubview(stack)
|
|
card.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 6, left: 16, bottom: 6, right: 16))
|
|
}
|
|
stack.snp.makeConstraints { make in
|
|
make.edges.equalToSuperview().inset(14)
|
|
}
|
|
}
|
|
}
|