Rebuild order list UI to strictly match Android OrderView and DepositOrderCard.

Add OrderTokens and shared order components, restore filter bar pills, list loading states, and role-specific card layouts with deposit badge mapping tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 09:12:06 +08:00
parent 87696a4774
commit fe84a7e8f4
17 changed files with 1235 additions and 379 deletions

View File

@ -6,39 +6,53 @@
import SnapKit
import UIKit
///
/// Android LazyColumn
final class OrderListView: UIView {
enum Mode {
case photographer
case store
}
var onRefresh: (() -> Void)?
var onLoadMore: ((Int) -> Void)?
let tableView = UITableView(frame: .zero, style: .plain)
private let refreshControl = UIRefreshControl()
private let loadingIndicator = UIActivityIndicatorView(style: .medium)
private let emptyLabel = UILabel()
private let footerLabel = UILabel()
private let footerSpinner = UIActivityIndicatorView(style: .medium)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor(hex: 0xF5F5F5)
backgroundColor = AppColor.pageBackground
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.keyboardDismissMode = .onDrag
tableView.contentInset = UIEdgeInsets(top: OrderTokens.cardGap, left: 0, bottom: OrderTokens.cardGap, right: 0)
tableView.refreshControl = refreshControl
refreshControl.addTarget(self, action: #selector(refreshTriggered), for: .valueChanged)
footerLabel.font = .systemFont(ofSize: 12)
footerLabel.textColor = UIColor(hex: 0x9CA3AF)
loadingIndicator.hidesWhenStopped = true
loadingIndicator.color = AppColor.primary
emptyLabel.font = .app(.body)
emptyLabel.textColor = OrderTokens.label563
emptyLabel.text = "暂无订单"
emptyLabel.textAlignment = .center
footerLabel.font = .app(.body)
footerLabel.textColor = OrderTokens.label563
footerLabel.textAlignment = .center
footerLabel.text = "没有更多"
footerSpinner.hidesWhenStopped = true
footerSpinner.color = AppColor.primary
addSubview(tableView)
addSubview(loadingIndicator)
tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
loadingIndicator.snp.makeConstraints { make in
make.center.equalToSuperview()
}
}
@available(*, unavailable)
@ -46,18 +60,54 @@ final class OrderListView: UIView {
fatalError("init(coder:) has not been implemented")
}
func apply(isRefreshing: Bool, canLoadMore: Bool, isEmpty: Bool) {
func apply(
isRefreshing: Bool,
canLoadMore: Bool,
isEmpty: Bool,
isLoading: Bool = false,
isLoadingMore: Bool = false
) {
if isRefreshing {
if !refreshControl.isRefreshing { refreshControl.beginRefreshing() }
} else {
refreshControl.endRefreshing()
}
footerLabel.text = isEmpty ? "暂无订单" : (canLoadMore ? "" : "没有更多")
tableView.tableFooterView = footerLabelFrame(isEmpty: isEmpty, canLoadMore: canLoadMore)
if isLoading, isEmpty {
loadingIndicator.startAnimating()
tableView.backgroundView = nil
tableView.tableFooterView = nil
} else {
loadingIndicator.stopAnimating()
if isEmpty {
tableView.backgroundView = emptyBackgroundView()
} else {
tableView.backgroundView = nil
}
tableView.tableFooterView = footerView(canLoadMore: canLoadMore, isLoadingMore: isLoadingMore, isEmpty: isEmpty)
}
}
private func footerLabelFrame(isEmpty: Bool, canLoadMore: Bool) -> UIView? {
guard !canLoadMore || isEmpty else { return nil }
private func emptyBackgroundView() -> UIView {
let container = UIView(frame: tableView.bounds)
emptyLabel.frame = container.bounds
emptyLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight]
container.addSubview(emptyLabel)
return container
}
private func footerView(canLoadMore: Bool, isLoadingMore: Bool, isEmpty: Bool) -> UIView? {
guard !isEmpty else { return nil }
if isLoadingMore {
let container = UIView(frame: CGRect(x: 0, y: 0, width: bounds.width, height: 44))
footerSpinner.center = CGPoint(x: container.bounds.midX, y: container.bounds.midY)
footerSpinner.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin]
container.addSubview(footerSpinner)
footerSpinner.startAnimating()
return container
}
footerSpinner.stopAnimating()
guard !canLoadMore else { return nil }
footerLabel.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 44)
return footerLabel
}