import SwiftUI import Combine // MARK: - Splash ViewModel @MainActor class SplashViewModel: ObservableObject { // MARK: - Published Properties @Published var isLoading = true @Published var shouldShowMainApp = false @Published var authenticationStatus: UserInfoManager.AuthenticationStatus = .notFound @Published var isCheckingAuthentication = false @Published var navigationDestination: NavigationDestination? // MARK: - Private Properties private var cancellables = Set() // MARK: - Navigation Destination enum NavigationDestination: Equatable { case login case main } // MARK: - Initialization init() { setupBindings() } // MARK: - Public Methods func onAppear() { isLoading = true shouldShowMainApp = false authenticationStatus = .notFound isCheckingAuthentication = false navigationDestination = nil // 1秒延迟后显示主应用 Task { try await Task.sleep(nanoseconds: 1_000_000_000) await MainActor.run { self.splashFinished() } } } func splashFinished() { isLoading = false checkAuthentication() } func checkAuthentication() { isCheckingAuthentication = true Task { let authStatus = await UserInfoManager.checkAuthenticationStatus() await MainActor.run { self.authenticationChecked(authStatus) } } } func authenticationChecked(_ status: UserInfoManager.AuthenticationStatus) { isCheckingAuthentication = false authenticationStatus = status if status.canAutoLogin { debugInfoSync("🎉 自动登录成功,开始获取用户信息") fetchUserInfo() } else { debugInfoSync("🔑 需要手动登录") navigateToLogin() } } func fetchUserInfo() { Task { let success = await UserInfoManager.autoFetchUserInfoOnAppLaunch(apiService: LiveAPIService()) await MainActor.run { self.userInfoFetched(success) } } } func userInfoFetched(_ success: Bool) { if success { debugInfoSync("✅ 用户信息获取成功,进入主页") } else { debugInfoSync("⚠️ 用户信息获取失败,但仍进入主页") } navigateToMain() } func navigateToLogin() { navigationDestination = .login } func navigateToMain() { navigationDestination = .main shouldShowMainApp = true } // MARK: - Private Methods private func setupBindings() { // 可以在这里设置 Combine 绑定 } } // MARK: - Splash View struct Splash: View { @StateObject private var viewModel = SplashViewModel() var body: some View { ZStack { Group { // 根据导航目标显示不同页面 if let navigationDestination = viewModel.navigationDestination { switch navigationDestination { case .login: // 显示登录页面 LoginPage( onLoginSuccess: { // 登录成功后导航到主页面 viewModel.navigateToMain() } ) case .main: // 显示主应用页面 MainPage( onLogout: { viewModel.navigateToLogin() } ) } } else { // 显示启动画面 splashContent } } .onAppear { viewModel.onAppear() } // API Loading 效果视图 - 显示在所有内容之上 APILoadingEffectView() } } // 启动画面内容 private var splashContent: some View { ZStack { // 背景图片 - 全屏显示 LoginBackgroundView() VStack(spacing: 32) { Spacer() .frame(height: 200) // 与 storyboard 中的约束对应 // Logo 图片 - 100x100 Image("logo") .resizable() .aspectRatio(contentMode: .fit) .frame(width: 100, height: 100) // 应用标题 - 白色,40pt字体 Text(LocalizedString("splash.title", comment: "E-Parti")) .font(.system(size: 40, weight: .regular)) .foregroundColor(.white) Spacer() } } } } //#Preview { // Splash() //} #Preview { Splash() }