// // MainTabBarController.swift // suixinkan // import CYLTabBarController import UIKit @MainActor /// 主 Tab 容器,使用 CYLTabBarController 展示四个一级入口及中间扫码按钮。 final class MainTabBarController: CYLTabBarController { 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) MainScanPlusButton.onScanTap = { [weak self] in self?.presentGlobalScanner() } // delegate = self } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } /// 视图加载完成后的 UI 初始化与数据绑定。 override func viewDidLoad() { super.viewDidLoad() configureTabBarAppearance() configureTabs() services.appNavigator.attach(host: self) bindBadgeViewModel() bindAccountContext() Task { await refreshOrderBadge() } #if DEBUG Task { await AppUITestRouteDriver.applyIfNeeded(services: services) } #endif } /// 控制器释放前清理全局扫码按钮回调。 deinit { Task { @MainActor in MainScanPlusButton.onScanTap = nil } } /// 配置 TabBar 外观,对齐参考工程 CustomMainTabBar 样式。 private func configureTabBarAppearance() { tabBar.tintColor = AppDesign.primary tabBar.backgroundColor = .white tabBar.shadowImage = UIImage() let normalAttributes: [NSAttributedString.Key: Any] = [ .foregroundColor: UIColor(hex: 0x7D8DA3), .font: UIFont.systemFont(ofSize: 12, weight: .regular) ] let selectedAttributes: [NSAttributedString.Key: Any] = [ .foregroundColor: AppDesign.primary, .font: UIFont.systemFont(ofSize: 12, weight: .medium) ] let appearance = UITabBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = .white appearance.shadowColor = .clear appearance.stackedLayoutAppearance.normal.titleTextAttributes = normalAttributes appearance.stackedLayoutAppearance.selected.titleTextAttributes = selectedAttributes tabBar.standardAppearance = appearance tabBar.scrollEdgeAppearance = appearance } /// 为每个 Tab 创建独立导航栈,并按 CYLTabBarController 要求先配置 Tab 属性再设置控制器。 private func configureTabs() { let tabs = AppTab.allCases tabBarItemsAttributes = tabs.map { makeTabBarItemAttributes(for: $0) } viewControllers = tabs.map { tab in let navigationController = TabNavigationController(tab: tab, services: services) tabNavigationControllers[tab] = navigationController return navigationController } } /// 构建 CYLTabBarController 识别的 TabBarItem 属性字典。 private func makeTabBarItemAttributes(for tab: AppTab) -> [String: String] { [ CYLTabBarItemTitle: tab.title, CYLTabBarItemImage: tab.unselectedImageName, CYLTabBarItemSelectedImage: tab.selectedImageName ] } /// 绑定角标 ViewModel 回调。 private func bindBadgeViewModel() { badgeViewModel.onChange = { [weak self] in self?.updateOrderBadge() } } /// 绑定账号上下文,景区或门店变化时刷新角标。 private func bindAccountContext() { services.accountContext.onChange = { [weak self] in Task { await self?.refreshOrderBadge() } } } /// 更新订单 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 中间按钮打开全局扫码页,成功后路由至订单核销入口。 private func presentGlobalScanner() { let scanner = OrderCodeScannerViewController() scanner.onScanResult = { [weak self, weak scanner] result in scanner?.dismiss(animated: true) guard let self else { return } switch result { case .success(let code): self.services.appNavigator.openOrdersEntry(.verificationOrders, scannedCode: code) case .failure(let error): self.services.toastCenter.show(error.localizedDescription) } } let navigationController = UINavigationController(rootViewController: scanner) navigationController.modalPresentationStyle = .fullScreen present(navigationController, animated: true) } /// 用户点击 TabBar 时刷新订单角标。 override func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { guard !isSyncingTabSelection, let navigationController = viewController as? TabNavigationController else { return } if navigationController.appTab == .orders { Task { await refreshOrderBadge() } } } } extension MainTabBarController: AppNavigationHost { /// 选中指定主 Tab。 func selectTab(_ tab: AppTab) { guard let index = AppTab.allCases.firstIndex(of: tab) else { return } guard selectedIndex != index else { return } isSyncingTabSelection = true selectedIndex = index isSyncingTabSelection = false if tab == .orders { Task { await refreshOrderBadge() } } } /// 返回指定 Tab 的导航控制器。 func navigationController(for tab: AppTab) -> TabNavigationController? { tabNavigationControllers[tab] } /// 返回当前选中 Tab 的导航控制器。 func selectedNavigationController() -> TabNavigationController? { selectedViewController as? TabNavigationController } /// 重置全部 Tab 的导航栈。 func resetAllStacks() { for navigationController in tabNavigationControllers.values { navigationController.popToRootViewController(animated: false) } selectTab(.home) } /// 将订单入口和可选扫码结果应用到订单根页面。 func applyOrdersEntry(_ entry: OrdersEntry, scannedCode: String?) { guard let ordersController = tabNavigationControllers[.orders]?.viewControllers.first as? OrdersViewController else { return } ordersController.applyOrdersEntry(entry, scannedCode: scannedCode) } }