// // OrderListView.swift // suixinkan // import SnapKit import UIKit /// 订单列表容器,含下拉刷新、空态与分页,对齐 Android LazyColumn。 final class OrderListView: UIView { 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 = 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) 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) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func apply( isRefreshing: Bool, canLoadMore: Bool, isEmpty: Bool, isLoading: Bool = false, isLoadingMore: Bool = false ) { if isRefreshing { if !refreshControl.isRefreshing { refreshControl.beginRefreshing() } } else { refreshControl.endRefreshing() } 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 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 } @objc private func refreshTriggered() { onRefresh?() } func notifyLoadMoreIfNeeded(at index: Int, shouldLoad: Bool) { guard shouldLoad else { return } onLoadMore?(index) } }