Initial commit
This commit is contained in:
63
suixinkan/App/Navigation/AppTab.swift
Normal file
63
suixinkan/App/Navigation/AppTab.swift
Normal file
@ -0,0 +1,63 @@
|
||||
//
|
||||
// AppTab.swift
|
||||
// suixinkan
|
||||
//
|
||||
// Created by Codex on 2026/6/18.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// 主 Tab 实体,描述底部导航中的每一个一级入口。
|
||||
enum AppTab: String, CaseIterable, Identifiable, Hashable {
|
||||
case home
|
||||
case orders
|
||||
case statistics
|
||||
case profile
|
||||
|
||||
var id: Self { self }
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .home:
|
||||
"首页"
|
||||
case .orders:
|
||||
"订单"
|
||||
case .statistics:
|
||||
"数据"
|
||||
case .profile:
|
||||
"我的"
|
||||
}
|
||||
}
|
||||
|
||||
var systemImage: String {
|
||||
switch self {
|
||||
case .home:
|
||||
"house"
|
||||
case .orders:
|
||||
"doc.text"
|
||||
case .statistics:
|
||||
"chart.bar"
|
||||
case .profile:
|
||||
"person"
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var rootView: some View {
|
||||
switch self {
|
||||
case .home:
|
||||
HomeRootView()
|
||||
case .orders:
|
||||
OrdersRootView()
|
||||
case .statistics:
|
||||
StatisticsRootView()
|
||||
case .profile:
|
||||
ProfileRootView()
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
var label: some View {
|
||||
Label(title, systemImage: systemImage)
|
||||
}
|
||||
}
|
||||
88
suixinkan/App/Navigation/NavigationRouter.swift
Normal file
88
suixinkan/App/Navigation/NavigationRouter.swift
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// 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)
|
||||
|
||||
/// 返回该路由通过 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
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 选择和所有 Tab 的导航历史。
|
||||
func reset() {
|
||||
selectedTab = .home
|
||||
routers.values.forEach { $0.reset() }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user