// // NavigationRouter.swift // suixinkan // // Created by Codex on 2026/6/18. // import Observation 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 @Observable /// 单个 NavigationStack 的路径容器,用于保存某个 Tab 的导航历史。 final class RouterPath { var path: [AppRoute] = [] /// 将指定路由压入当前 Tab 的导航栈。 func navigate(to route: AppRoute) { path.append(route) } /// 清空当前 Tab 的导航栈。 func reset() { path = [] } } @MainActor @Observable /// 主导航状态中心,管理当前 Tab 和每个 Tab 独立的 NavigationStack 路径。 final class AppRouter { var selectedTab: AppTab = .home var selectedOrdersEntry: OrdersEntry = .storeOrders private(set) var pendingOrderScanCode: String? private var routers: [AppTab: RouterPath] = [:] /// 获取指定 Tab 对应的路由路径容器,不存在时自动创建。 func router(for tab: AppTab) -> RouterPath { if let router = routers[tab] { return router } let router = RouterPath() routers[tab] = router return router } /// 生成 SwiftUI NavigationStack 可使用的路径绑定。 func binding(for tab: AppTab) -> Binding<[AppRoute]> { let router = router(for: tab) return Binding( get: { router.path }, set: { router.path = $0 } ) } /// 切换到指定主 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() } } }