feat: 更新Swift助手样式规则和应用结构
- 在swift-assistant-style.mdc中添加项目背景、代码结构、命名规范、Swift最佳实践、UI开发、性能、安全性、测试与质量、核心功能、开发流程、App Store指南等详细规则。 - 在yanaApp.swift中将SplashView替换为Splash,简化应用结构。
This commit is contained in:
182
yana/MVVM/Splash.swift
Normal file
182
yana/MVVM/Splash.swift
Normal file
@@ -0,0 +1,182 @@
|
||||
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<AnyCancellable>()
|
||||
|
||||
// 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()
|
||||
}
|
Reference in New Issue
Block a user