// // NavigationRouter.swift // suixinkan // // Created by Codex on 2026/6/18. // import Combine import SwiftUI /// 应用内可导航目标,承载各 Tab 内部的路由目的地。 enum AppRoute: Hashable { case placeholder(title: String) case home(HomeRoute) case profile(ProfileRoute) case orders(OrdersRoute) /// 返回该路由通过 NavigationStack push 后是否隐藏底部 TabBar。 var hidesTabBarWhenPushed: Bool { true } /// 构建当前路由对应的目标页面。 @ViewBuilder var destinationView: some View { switch self { case .placeholder(let title): PlaceholderDetailView(title: title) case .home(let route): route.destinationView case .profile(let route): route.destinationView case .orders(let route): route.destinationView } } } extension OrdersRoute { /// 构建订单模块二级路由对应的目标页面。 @ViewBuilder var destinationView: some View { switch self { case .storeDetail(let item): StoreOrderDetailView(item: item) case .writeOffDetail(let item): WriteOffOrderDetailView(item: item) case .depositDetail(let orderNumber): DepositOrderDetailView(orderNumber: orderNumber) case .depositShootingInfo(let orderNumber, let scenicSpotId, let photogUid): DepositOrderShootingInfoView(orderNumber: orderNumber, scenicSpotId: scenicSpotId, photogUid: photogUid) case .historicalShooting(let orderNumber): HistoricalShootingInfoView(orderNumber: orderNumber) case .multiTravelTaskUpload(let orderNumber): MultiTravelTaskUploadView(initialOrderNumber: orderNumber) case .orderTrailer(let orderNumber, let title): OrderTrailerView(orderNumber: orderNumber, title: title) } } } @MainActor /// 单个 NavigationStack 的路径容器,用于保存某个 Tab 的导航历史。 final class RouterPath: ObservableObject { @Published var path: [AppRoute] = [] /// 将指定路由压入当前 Tab 的导航栈。 func navigate(to route: AppRoute) { path.append(route) } /// 清空当前 Tab 的导航栈。 func reset() { path = [] } } @MainActor /// 主导航状态中心,管理当前 Tab 和每个 Tab 独立的 NavigationStack 路径。 final class AppRouter: ObservableObject { @Published var selectedTab: AppTab = .home @Published var selectedOrdersEntry: OrdersEntry = .storeOrders @Published private(set) var pendingOrderScanCode: String? private let routers: [AppTab: RouterPath] init() { routers = Dictionary( uniqueKeysWithValues: AppTab.allCases.map { tab in (tab, RouterPath()) } ) } /// 获取指定 Tab 对应的路由路径容器。 func router(for tab: AppTab) -> RouterPath { guard let router = routers[tab] else { assertionFailure("Missing router path for tab: \(tab)") return RouterPath() } return router } /// 切换到指定主 Tab。 func select(_ tab: AppTab) { selectedTab = tab } /// 切换到订单 Tab,并指定订单内部子入口。 func selectOrders(entry: OrdersEntry) { selectedOrdersEntry = entry selectedTab = .orders } /// 切换到核销订单入口,并暂存全局扫码结果等待订单页消费。 func routeToOrderVerification(scannedCode: String) { pendingOrderScanCode = scannedCode selectOrders(entry: .verificationOrders) } /// 读取并清空待处理的全局扫码结果,确保同一次扫码只被处理一次。 func consumePendingOrderScanCode() -> String? { let code = pendingOrderScanCode pendingOrderScanCode = nil return code } /// 重置主 Tab 选择和所有 Tab 的导航历史。 func reset() { selectedTab = .home selectedOrdersEntry = .storeOrders pendingOrderScanCode = nil routers.values.forEach { $0.reset() } } }