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>
130 lines
4.3 KiB
Swift
130 lines
4.3 KiB
Swift
//
|
||
// MainTabBarController.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import UIKit
|
||
|
||
@MainActor
|
||
/// 主 Tab 容器,使用系统 `UITabBarController` 展示四个一级入口。
|
||
final class MainTabBarController: UITabBarController, UITabBarControllerDelegate {
|
||
|
||
private let services: AppServices
|
||
private let badgeViewModel = MainTabBadgeViewModel()
|
||
private var tabNavigationControllers: [AppTab: TabNavigationController] = [:]
|
||
private var isSyncingTabSelection = false
|
||
|
||
/// 初始化实例。
|
||
init(services: AppServices) {
|
||
self.services = services
|
||
super.init(nibName: nil, bundle: nil)
|
||
delegate = self
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) {
|
||
fatalError("init(coder:) has not been implemented")
|
||
}
|
||
|
||
/// 视图加载完成后的 UI 初始化与数据绑定。
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
configureTabBarAppearance()
|
||
configureTabs()
|
||
bindRouter()
|
||
bindBadgeViewModel()
|
||
bindAccountContext()
|
||
syncSelectedTabFromRouter(animated: false)
|
||
Task { await refreshOrderBadge() }
|
||
#if DEBUG
|
||
Task { await AppUITestRouteDriver.applyIfNeeded(services: services) }
|
||
#endif
|
||
}
|
||
|
||
/// 配置系统 TabBar 外观。
|
||
private func configureTabBarAppearance() {
|
||
tabBar.tintColor = AppDesign.primary
|
||
tabBar.backgroundColor = .white
|
||
}
|
||
|
||
/// 为每个 Tab 创建独立导航栈并绑定 TabBarItem。
|
||
private func configureTabs() {
|
||
viewControllers = AppTab.allCases.map { tab in
|
||
let navigationController = TabNavigationController(tab: tab, services: services)
|
||
navigationController.tabBarItem = tab.makeTabBarItem()
|
||
tabNavigationControllers[tab] = navigationController
|
||
return navigationController
|
||
}
|
||
}
|
||
|
||
/// 绑定 Router 回调,同步程序化 Tab 切换。
|
||
private func bindRouter() {
|
||
services.appRouter.onChange = { [weak self] in
|
||
self?.handleRouterChange()
|
||
}
|
||
}
|
||
|
||
/// 绑定角标 ViewModel 回调。
|
||
private func bindBadgeViewModel() {
|
||
badgeViewModel.onChange = { [weak self] in
|
||
self?.updateOrderBadge()
|
||
}
|
||
}
|
||
|
||
/// 绑定账号上下文,景区或门店变化时刷新角标。
|
||
private func bindAccountContext() {
|
||
services.accountContext.onChange = { [weak self] in
|
||
Task { await self?.refreshOrderBadge() }
|
||
}
|
||
}
|
||
|
||
/// 处理 Router 变更,保持选中 Tab 与 `AppRouter` 一致。
|
||
private func handleRouterChange() {
|
||
syncSelectedTabFromRouter(animated: false)
|
||
if services.appRouter.selectedTab == .orders {
|
||
Task { await refreshOrderBadge() }
|
||
}
|
||
}
|
||
|
||
/// 将 `AppRouter.selectedTab` 同步到系统 TabBar 选中项。
|
||
private func syncSelectedTabFromRouter(animated: Bool) {
|
||
guard let index = AppTab.allCases.firstIndex(of: services.appRouter.selectedTab) else { return }
|
||
guard selectedIndex != index else { return }
|
||
|
||
isSyncingTabSelection = true
|
||
selectedIndex = index
|
||
isSyncingTabSelection = false
|
||
}
|
||
|
||
/// 更新订单 Tab 待核销角标。
|
||
private func updateOrderBadge() {
|
||
let badgeValue: String?
|
||
if let count = badgeViewModel.pendingWriteOffCount, count > 0 {
|
||
badgeValue = "\(count)"
|
||
} else {
|
||
badgeValue = nil
|
||
}
|
||
tabNavigationControllers[.orders]?.tabBarItem.badgeValue = badgeValue
|
||
}
|
||
|
||
/// 刷新订单 Tab 待核销角标数据。
|
||
private func refreshOrderBadge() async {
|
||
await badgeViewModel.refreshPendingWriteOffCount(
|
||
api: services.ordersAPI,
|
||
scenicId: services.accountContext.currentScenic?.id,
|
||
storeId: services.accountContext.currentStore?.id
|
||
)
|
||
}
|
||
|
||
/// 用户点击 TabBar 时同步选中状态到 `AppRouter`。
|
||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
||
guard !isSyncingTabSelection,
|
||
let navigationController = viewController as? TabNavigationController else { return }
|
||
|
||
services.appRouter.select(navigationController.appTab)
|
||
if navigationController.appTab == .orders {
|
||
Task { await refreshOrderBadge() }
|
||
}
|
||
}
|
||
}
|