Integrate CYLTabBar center scan button and unify UIKit navigation.

Add CYLTabBarController with a global scan entry, promote MainTabBarController to the window root after login, replace RouterPath-based navigation with AppNavigator, and fix Profile diffable cell reconfiguration crashes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 16:36:18 +08:00
parent 24a7339b68
commit a1c031c9b7
31 changed files with 838 additions and 517 deletions

View File

@ -96,7 +96,7 @@ final class DepositOrderListViewController: UIViewController, UITableViewDelegat
let cell = tableView.dequeueReusableCell(withIdentifier: DepositOrderCell.reuseID, for: indexPath) as! DepositOrderCell
cell.configure(item: orderItem, isOperating: self.viewModel.operatingOrderNumber == orderItem.orderNumber)
cell.onDetail = { [weak self] in
self.flatMap { HomeMenuRouting.pushOrders(.depositDetail(orderNumber: orderItem.orderNumber), from: $0) }
self.flatMap { $0.appServices.appNavigator.push(.orders(.depositDetail(orderNumber: orderItem.orderNumber)), from: $0) }
}
cell.onWriteOff = { [weak self] in self?.writeOff(orderItem) }
cell.onRefund = { [weak self] in self?.refund(orderItem) }
@ -154,7 +154,7 @@ final class DepositOrderListViewController: UIViewController, UITableViewDelegat
@objc private func openDetail() {
let text = orderNumberField.text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
guard !text.isEmpty else { return }
HomeMenuRouting.pushOrders(.depositDetail(orderNumber: text), from: self)
appServices.appNavigator.push(.orders(.depositDetail(orderNumber: text)), from: self)
}
///

View File

@ -289,13 +289,13 @@ final class StoreOrderDetailViewController: UIViewController, UITableViewDelegat
let orderNumber = viewModel.display.orderNumber
switch index {
case 0:
HomeMenuRouting.pushOrders(.historicalShooting(orderNumber: orderNumber), from: self)
appServices.appNavigator.push(.orders(.historicalShooting(orderNumber: orderNumber)), from: self)
case 1 where item.orderType == 19:
HomeMenuRouting.pushOrders(.multiTravelTaskUpload(orderNumber: orderNumber), from: self)
appServices.appNavigator.push(.orders(.multiTravelTaskUpload(orderNumber: orderNumber)), from: self)
case 2:
HomeMenuRouting.pushOrders(.orderTrailer(orderNumber: orderNumber, title: "视频预告"), from: self)
appServices.appNavigator.push(.orders(.orderTrailer(orderNumber: orderNumber, title: "视频预告")), from: self)
case 3:
HomeMenuRouting.pushOrders(.orderTrailer(orderNumber: orderNumber, title: "尾片上传"), from: self)
appServices.appNavigator.push(.orders(.orderTrailer(orderNumber: orderNumber, title: "尾片上传")), from: self)
case 4:
presentRefund()
default:

View File

@ -37,6 +37,7 @@ final class OrdersViewController: UIViewController {
private let viewModel = OrdersViewModel()
private var manualOrderNumber = ""
private var scanHintMessage: String?
private var pendingScanCode: String?
private lazy var collectionView: UICollectionView = {
let layout = makeCollectionLayout()
@ -77,25 +78,34 @@ final class OrdersViewController: UIViewController {
self?.applySnapshot()
}
appServices.appRouter.onChange = { [weak self] in
guard let self else { return }
if self.viewModel.selectedEntry != self.appServices.appRouter.selectedOrdersEntry {
self.viewModel.selectedEntry = self.appServices.appRouter.selectedOrdersEntry
Task { await self.reload(showLoading: true) }
}
Task { await self.consumePendingScanCodeIfNeeded() }
}
appServices.accountContext.onChange = { [weak self] in
Task { await self?.reload(showLoading: true) }
}
viewModel.selectedEntry = appServices.appRouter.selectedOrdersEntry
Task {
await reload(showLoading: true)
await consumePendingScanCodeIfNeeded()
}
}
///
func applyOrdersEntry(_ entry: OrdersEntry, scannedCode: String?) {
let didChangeEntry = viewModel.selectedEntry != entry
viewModel.selectedEntry = entry
if let scannedCode {
pendingScanCode = scannedCode
}
guard isViewLoaded else { return }
Task {
if didChangeEntry {
await reload(showLoading: true)
}
await consumePendingScanCodeIfNeeded()
}
}
/// Compositional Layout section
private func makeCollectionLayout() -> UICollectionViewCompositionalLayout {
UICollectionViewCompositionalLayout { [weak self] sectionIndex, _ in
@ -345,7 +355,6 @@ final class OrdersViewController: UIViewController {
private func switchEntry(_ entry: OrdersEntry) {
guard viewModel.selectedEntry != entry else { return }
viewModel.selectedEntry = entry
appServices.appRouter.selectedOrdersEntry = entry
Task { await reload(showLoading: true) }
}
@ -370,7 +379,8 @@ final class OrdersViewController: UIViewController {
///
private func consumePendingScanCodeIfNeeded() async {
guard viewModel.selectedEntry == .verificationOrders,
let code = appServices.appRouter.consumePendingOrderScanCode() else { return }
let code = pendingScanCode else { return }
pendingScanCode = nil
handleScanResult(code)
}
@ -459,11 +469,11 @@ extension OrdersViewController: UICollectionViewDelegate {
if item.hasPrefix("orders:store:") {
let orderNumber = String(item.dropFirst("orders:store:".count))
guard let order = viewModel.storeOrders.first(where: { $0.orderNumber == orderNumber }) else { return }
HomeMenuRouting.pushOrders(.storeDetail(order), from: self)
appServices.appNavigator.push(.orders(.storeDetail(order)), from: self)
} else if item.hasPrefix("orders:writeoff:") {
let orderNumber = String(item.dropFirst("orders:writeoff:".count))
guard let order = viewModel.writeOffOrders.first(where: { $0.orderNumber == orderNumber }) else { return }
HomeMenuRouting.pushOrders(.writeOffDetail(order), from: self)
appServices.appNavigator.push(.orders(.writeOffDetail(order)), from: self)
}
}