Advance UIKit rewrite with AMap integration and core UI modules.

Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 15:16:12 +08:00
parent 9edf993432
commit d99a5b1bf8
124 changed files with 5195 additions and 1536 deletions

View File

@ -6,9 +6,14 @@
import SnapKit
import UIKit
// MARK: - Diffable
private typealias AccountSelectionSection = Int
private typealias AccountSelectionItem = String
@MainActor
/// /
final class AccountSelectionViewController: UIViewController {
final class AccountSelectionViewController: UIViewController, UITableViewDelegate {
private let payload: AccountSelectionPayload
private var isLoading: Bool
@ -17,9 +22,13 @@ final class AccountSelectionViewController: UIViewController {
private var selectedAccountId: String?
private let tableView = UITableView(frame: .zero, style: .plain)
/// Diffable
private var tableDataSource: UITableViewDiffableDataSource<AccountSelectionSection, AccountSelectionItem>!
private let confirmButton = UIButton(type: .system)
private let bottomBar = UIView()
///
init(
payload: AccountSelectionPayload,
isLoading: Bool,
@ -38,6 +47,7 @@ final class AccountSelectionViewController: UIViewController {
fatalError("init(coder:) has not been implemented")
}
/// UI
override func viewDidLoad() {
super.viewDidLoad()
title = "选择账号"
@ -47,9 +57,47 @@ final class AccountSelectionViewController: UIViewController {
selectedAccountId = payload.accounts.first?.id
configureTableView()
configureTableDataSource()
configureBottomBar()
}
/// Diffable
private func configureTableDataSource() {
tableDataSource = UITableViewDiffableDataSource<AccountSelectionSection, AccountSelectionItem>(
tableView: tableView
) { [weak self] (tableView: UITableView, indexPath: IndexPath, item: AccountSelectionItem) -> UITableViewCell? in
guard let self,
let cell = tableView.dequeueReusableCell(
withIdentifier: AccountSelectionCell.reuseIdentifier,
for: indexPath
) as? AccountSelectionCell,
let account = self.payload.accounts.first(where: { $0.id == item }) else {
return UITableViewCell()
}
cell.configure(account: account, selected: account.id == self.selectedAccountId)
return cell
}
applyTableSnapshot(animated: false)
}
/// Diffable snapshot
private func buildTableSnapshot() -> NSDiffableDataSourceSnapshot<AccountSelectionSection, AccountSelectionItem> {
var snapshot = NSDiffableDataSourceSnapshot<AccountSelectionSection, AccountSelectionItem>()
snapshot.appendSections([0])
snapshot.appendItems(payload.accounts.map(\.id), toSection: 0)
return snapshot
}
/// snapshot
private func applyTableSnapshot(animated: Bool = true, reconfigure: Bool = false) {
var snapshot = buildTableSnapshot()
if reconfigure, !snapshot.itemIdentifiers.isEmpty {
snapshot.reconfigureItems(snapshot.itemIdentifiers)
}
tableDataSource.apply(snapshot, animatingDifferences: animated)
}
/// Loading
func updateLoading(_ loading: Bool) {
isLoading = loading
isModalInPresentation = loading
@ -65,10 +113,10 @@ final class AccountSelectionViewController: UIViewController {
selectedAccount != nil && !isLoading
}
/// TableView
private func configureTableView() {
tableView.backgroundColor = .clear
tableView.separatorStyle = .none
tableView.dataSource = self
tableView.delegate = self
tableView.register(AccountSelectionCell.self, forCellReuseIdentifier: AccountSelectionCell.reuseIdentifier)
view.addSubview(tableView)
@ -78,6 +126,7 @@ final class AccountSelectionViewController: UIViewController {
}
}
/// BottomBar
private func configureBottomBar() {
bottomBar.backgroundColor = .white
@ -112,37 +161,26 @@ final class AccountSelectionViewController: UIViewController {
}
}
/// cancel
@objc private func cancelTapped() {
onCancel()
dismiss(animated: true)
}
/// confirm
@objc private func confirmTapped() {
guard let selectedAccount else { return }
onConfirm(selectedAccount)
}
}
extension AccountSelectionViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
payload.accounts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(
withIdentifier: AccountSelectionCell.reuseIdentifier,
for: indexPath
) as? AccountSelectionCell else {
return UITableViewCell()
}
let account = payload.accounts[indexPath.row]
cell.configure(account: account, selected: account.id == selectedAccountId)
return cell
}
extension AccountSelectionViewController {
/// UITableView
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedAccountId = payload.accounts[indexPath.row].id
tableView.reloadData()
tableView.deselectRow(at: indexPath, animated: true)
guard let item = tableDataSource.itemIdentifier(for: indexPath) else { return }
selectedAccountId = item
applyTableSnapshot(animated: false, reconfigure: true)
confirmButton.isEnabled = canConfirm
confirmButton.backgroundColor = canConfirm ? AppDesign.primary : UIColor(hex: 0xC9CED6)
}
@ -161,6 +199,7 @@ private final class AccountSelectionCell: UITableViewCell {
private let currentTag = UILabel()
private let checkmark = UIImageView()
///
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
@ -257,6 +296,7 @@ private final class AccountSelectionCell: UITableViewCell {
nil
}
///
func configure(account: AccountSwitchAccount, selected: Bool) {
titleLabel.text = account.title.isEmpty ? account.accountTypeLabel : account.title
subtitleLabel.text = account.subtitle