feat: 组合根装配会话与导航(Tab + 登录 + 提交页)
This commit is contained in:
@@ -38,12 +38,26 @@ let package = Package(
|
|||||||
dependencies: ["CoreDomain", "CoreUI", "CoreModel", "CoreCommon"]
|
dependencies: ["CoreDomain", "CoreUI", "CoreModel", "CoreCommon"]
|
||||||
),
|
),
|
||||||
.target(name: "FeatureAuth", dependencies: ["CoreDomain", "CoreUI", "CoreModel"]),
|
.target(name: "FeatureAuth", dependencies: ["CoreDomain", "CoreUI", "CoreModel"]),
|
||||||
|
.target(
|
||||||
|
name: "FeaturePlan",
|
||||||
|
dependencies: ["CoreDomain", "CoreUI", "CoreModel", "CoreCommon"]
|
||||||
|
),
|
||||||
|
.target(
|
||||||
|
name: "FeatureCheckin",
|
||||||
|
dependencies: ["CoreDomain", "CoreUI", "CoreModel", "CoreCommon"]
|
||||||
|
),
|
||||||
|
.target(
|
||||||
|
name: "FeatureProfile",
|
||||||
|
dependencies: ["CoreDomain", "CoreUI", "CoreModel", "CoreCommon"]
|
||||||
|
),
|
||||||
|
|
||||||
// 组合根(依赖一切,用于 DI 装配)
|
// 组合根(依赖一切,用于 DI 装配)
|
||||||
.target(
|
.target(
|
||||||
name: "App",
|
name: "App",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"FeatureHome", "FeatureAuth", "CoreRepository",
|
"FeatureHome", "FeatureAuth",
|
||||||
|
"FeaturePlan", "FeatureCheckin", "FeatureProfile",
|
||||||
|
"CoreRepository",
|
||||||
"CoreUI", "DesignSystem", "CoreDomain", "CoreModel",
|
"CoreUI", "DesignSystem", "CoreDomain", "CoreModel",
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,14 +1,49 @@
|
|||||||
import CoreDomain
|
import CoreDomain
|
||||||
|
import CoreModel
|
||||||
import CoreRepository
|
import CoreRepository
|
||||||
|
import FeatureAuth
|
||||||
|
import FeatureCheckin
|
||||||
import FeatureHome
|
import FeatureHome
|
||||||
|
import FeaturePlan
|
||||||
|
import FeatureProfile
|
||||||
|
|
||||||
/// 手写组合根 / DI 容器(对应 Android Hilt 的 AppContainer)。
|
/// 手写组合根 / DI 容器(对应 Android Hilt 的 AppContainer)。
|
||||||
@MainActor
|
@MainActor
|
||||||
public enum AppContainer {
|
public enum AppContainer {
|
||||||
/// 装配 FeatureHome 依赖并返回 ViewModel。
|
// 共享的有状态仓库(登录态、打卡、计划可提交,需跨页面共享单例)。
|
||||||
|
private static let sessionRepository: SessionRepository = FakeSessionRepository()
|
||||||
|
private static let checkinRepository: CheckinRepository = FakeCheckinRepository()
|
||||||
|
private static let planRepository: PlanRepository = FakePlanRepository()
|
||||||
|
|
||||||
|
private static let sessionUseCase = SessionUseCase(repository: sessionRepository)
|
||||||
|
private static let checkinUseCase = CheckinUseCase(repository: checkinRepository)
|
||||||
|
private static let planUseCase = PlanUseCase(repository: planRepository)
|
||||||
|
|
||||||
public static func makeHomeViewModel() -> HomeViewModel {
|
public static func makeHomeViewModel() -> HomeViewModel {
|
||||||
let repository: HomeRepository = FakeHomeRepository()
|
let repository: HomeRepository = FakeHomeRepository()
|
||||||
let useCase = HomeUseCase(repository: repository)
|
let useCase = HomeUseCase(repository: repository)
|
||||||
return HomeViewModel(homeUseCase: useCase)
|
return HomeViewModel(homeUseCase: useCase, sessionUseCase: sessionUseCase)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makeCheckinViewModel() -> CheckinViewModel {
|
||||||
|
CheckinViewModel(checkinUseCase: checkinUseCase, sessionUseCase: sessionUseCase)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makePlanViewModel() -> PlanViewModel {
|
||||||
|
PlanViewModel(planUseCase: planUseCase, sessionUseCase: sessionUseCase)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makeProfileViewModel() -> ProfileViewModel {
|
||||||
|
let repository: ProfileRepository = FakeProfileRepository()
|
||||||
|
let useCase = ProfileUseCase(repository: repository)
|
||||||
|
return ProfileViewModel(profileUseCase: useCase, sessionUseCase: sessionUseCase)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makeAuthViewModel() -> AuthViewModel {
|
||||||
|
AuthViewModel(sessionUseCase: sessionUseCase)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makePlanSubmitViewModel(type: PlanType, periodKey: String) -> PlanSubmitViewModel {
|
||||||
|
PlanSubmitViewModel(planUseCase: planUseCase, type: type, periodKey: periodKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,73 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import CoreUI
|
|
||||||
import FeatureAuth
|
import FeatureAuth
|
||||||
|
import FeatureCheckin
|
||||||
import FeatureHome
|
import FeatureHome
|
||||||
|
import FeaturePlan
|
||||||
|
import FeatureProfile
|
||||||
|
|
||||||
public struct AppRootView: View {
|
public struct AppRootView: View {
|
||||||
@State private var homeViewModel: HomeViewModel
|
@State private var homeViewModel: HomeViewModel
|
||||||
|
@State private var checkinViewModel: CheckinViewModel
|
||||||
|
@State private var planViewModel: PlanViewModel
|
||||||
|
@State private var profileViewModel: ProfileViewModel
|
||||||
|
@State private var authViewModel: AuthViewModel
|
||||||
|
@State private var selectedTab: AppTab = .home
|
||||||
|
@State private var isAuthPresented = false
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
_homeViewModel = State(initialValue: AppContainer.makeHomeViewModel())
|
_homeViewModel = State(initialValue: AppContainer.makeHomeViewModel())
|
||||||
|
_checkinViewModel = State(initialValue: AppContainer.makeCheckinViewModel())
|
||||||
|
_planViewModel = State(initialValue: AppContainer.makePlanViewModel())
|
||||||
|
_profileViewModel = State(initialValue: AppContainer.makeProfileViewModel())
|
||||||
|
_authViewModel = State(initialValue: AppContainer.makeAuthViewModel())
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
TabView {
|
TabView(selection: $selectedTab) {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
HomeScreen(viewModel: homeViewModel)
|
HomeScreen(
|
||||||
|
viewModel: homeViewModel,
|
||||||
|
onNavigateToCheckin: { selectedTab = .checkin },
|
||||||
|
onNavigateToPlan: { selectedTab = .plan },
|
||||||
|
onNavigateToAuth: { isAuthPresented = true }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.tabItem { Label("首页", systemImage: "house.fill") }
|
.tabItem { Label("首页", systemImage: "house.fill") }
|
||||||
|
.tag(AppTab.home)
|
||||||
|
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
PlaceholderView("计划", systemImage: "calendar")
|
CheckinScreen(viewModel: checkinViewModel, onNavigateToAuth: { isAuthPresented = true })
|
||||||
}
|
|
||||||
.tabItem { Label("计划", systemImage: "calendar") }
|
|
||||||
|
|
||||||
NavigationStack {
|
|
||||||
PlaceholderView("打卡", systemImage: "checkmark.seal.fill")
|
|
||||||
}
|
}
|
||||||
.tabItem { Label("打卡", systemImage: "checkmark.seal.fill") }
|
.tabItem { Label("打卡", systemImage: "checkmark.seal.fill") }
|
||||||
|
.tag(AppTab.checkin)
|
||||||
|
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
AuthScreen()
|
PlanScreen(
|
||||||
|
viewModel: planViewModel,
|
||||||
|
onNavigateToAuth: { isAuthPresented = true },
|
||||||
|
makePlanSubmitViewModel: { type, periodKey in
|
||||||
|
AppContainer.makePlanSubmitViewModel(type: type, periodKey: periodKey)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.tabItem { Label("计划", systemImage: "calendar") }
|
||||||
|
.tag(AppTab.plan)
|
||||||
|
|
||||||
|
NavigationStack {
|
||||||
|
ProfileScreen(viewModel: profileViewModel, onNavigateToAuth: { isAuthPresented = true })
|
||||||
}
|
}
|
||||||
.tabItem { Label("我的", systemImage: "person.crop.circle") }
|
.tabItem { Label("我的", systemImage: "person.crop.circle") }
|
||||||
|
.tag(AppTab.profile)
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $isAuthPresented) {
|
||||||
|
AuthScreen(viewModel: authViewModel, onLoggedIn: { isAuthPresented = false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum AppTab: Hashable {
|
||||||
|
case home
|
||||||
|
case checkin
|
||||||
|
case plan
|
||||||
|
case profile
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user