feat: 更新.gitignore,删除需求文档,优化API调试信息
- 在.gitignore中添加忽略项以排除不必要的文件。 - 删除架构分析需求文档以简化项目文档。 - 在APIEndpoints.swift和LoginModels.swift中移除调试信息的异步调用,提升代码简洁性。 - 在EMailLoginFeature.swift和HomeFeature.swift中新增登录流程状态管理,优化用户体验。 - 在多个视图中调整状态管理和导航逻辑,确保一致性和可维护性。 - 更新Xcode项目配置以增强调试信息的输出格式。
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import SwiftUI
|
||||
import ComposableArchitecture
|
||||
import Perception
|
||||
|
||||
// PreferenceKey 用于传递图片高度
|
||||
struct ImageHeightPreferenceKey: PreferenceKey {
|
||||
@@ -11,8 +12,9 @@ struct ImageHeightPreferenceKey: PreferenceKey {
|
||||
|
||||
struct LoginView: View {
|
||||
let store: StoreOf<LoginFeature>
|
||||
let onLoginSuccess: () -> Void // 新增:登录成功回调
|
||||
@State private var topImageHeight: CGFloat = 120 // 默认值
|
||||
@ObservedObject private var localizationManager = LocalizationManager.shared
|
||||
// @ObservedObject private var localizationManager = LocalizationManager.shared
|
||||
@State private var showLanguageSettings = false
|
||||
@State private var isAgreedToTerms = true
|
||||
@State private var showUserAgreement = false
|
||||
@@ -21,158 +23,169 @@ struct LoginView: View {
|
||||
@State private var showEmailLogin = false // 新增:邮箱登录导航状态
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
GeometryReader { geometry in
|
||||
ZStack {
|
||||
// 使用与 splash 相同的背景图片
|
||||
Image("bg")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.ignoresSafeArea(.all)
|
||||
VStack(spacing: 0) {
|
||||
// 上半部分的"top"图片
|
||||
ZStack {
|
||||
Image("top")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, -100)
|
||||
.background(
|
||||
GeometryReader { topImageGeometry in
|
||||
Color.clear.preference(key: ImageHeightPreferenceKey.self, value: topImageGeometry.size.height)
|
||||
}
|
||||
)
|
||||
// E-PARTI 文本,底部对齐"top"图片底部,间距20
|
||||
HStack {
|
||||
Text(NSLocalizedString("login.app_title", comment: ""))
|
||||
.font(FontManager.adaptedFont(.bayonRegular, designSize: 56, for: geometry.size.width))
|
||||
.foregroundColor(.white)
|
||||
.padding(.leading, 20)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, max(0, topImageHeight - 100)) // top图片高度 - 140
|
||||
|
||||
// 语言切换按钮(右上角)- 仅在 Debug 环境下显示
|
||||
#if DEBUG
|
||||
VStack {
|
||||
WithViewStore(self.store, observe: { $0.isAnyLoginCompleted }) { viewStore in
|
||||
NavigationStack {
|
||||
GeometryReader { geometry in
|
||||
WithPerceptionTracking {
|
||||
ZStack {
|
||||
// 使用与 splash 相同的背景图片
|
||||
Image("bg")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.ignoresSafeArea(.all)
|
||||
VStack(spacing: 0) {
|
||||
// 上半部分的"top"图片
|
||||
ZStack {
|
||||
Image("top")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, -100)
|
||||
.background(
|
||||
GeometryReader { topImageGeometry in
|
||||
Color.clear.preference(key: ImageHeightPreferenceKey.self, value: topImageGeometry.size.height)
|
||||
}
|
||||
)
|
||||
// E-PARTI 文本,底部对齐"top"图片底部,间距20
|
||||
HStack {
|
||||
Text(NSLocalizedString("login.app_title", comment: ""))
|
||||
.font(FontManager.adaptedFont(.bayonRegular, designSize: 56, for: geometry.size.width))
|
||||
.foregroundColor(.white)
|
||||
.padding(.leading, 20)
|
||||
Spacer()
|
||||
Button(action: {
|
||||
showLanguageSettings = true
|
||||
}) {
|
||||
Image(systemName: "globe")
|
||||
.frame(width: 40, height: 40)
|
||||
.font(.system(size: 20))
|
||||
.foregroundColor(.white)
|
||||
.background(Color.black.opacity(0.3))
|
||||
.clipShape(Circle())
|
||||
}
|
||||
.padding(.top, max(0, topImageHeight - 100)) // top图片高度 - 140
|
||||
|
||||
// 语言切换按钮(右上角)- 仅在 Debug 环境下显示
|
||||
#if DEBUG
|
||||
VStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
Button(action: {
|
||||
showLanguageSettings = true
|
||||
}) {
|
||||
Image(systemName: "globe")
|
||||
.frame(width: 40, height: 40)
|
||||
.font(.system(size: 20))
|
||||
.foregroundColor(.white)
|
||||
.background(Color.black.opacity(0.3))
|
||||
.clipShape(Circle())
|
||||
}
|
||||
.padding(.trailing, 16)
|
||||
}
|
||||
.padding(.trailing, 16)
|
||||
Spacer()
|
||||
}
|
||||
Spacer()
|
||||
#endif
|
||||
|
||||
VStack(spacing: 24) {
|
||||
// ID Login 按钮
|
||||
LoginButton(
|
||||
iconName: "person.circle.fill",
|
||||
iconColor: .green,
|
||||
title: NSLocalizedString("login.id_login", comment: "")
|
||||
) {
|
||||
showIDLogin = true // 直接设置SwiftUI状态
|
||||
}
|
||||
// Email Login 按钮
|
||||
LoginButton(
|
||||
iconName: "envelope.fill",
|
||||
iconColor: .blue,
|
||||
title: NSLocalizedString("login.email_login", comment: "")
|
||||
) {
|
||||
showEmailLogin = true // 显示邮箱登录界面
|
||||
}
|
||||
}.padding(.top, max(0, topImageHeight+140))
|
||||
}
|
||||
.onPreferenceChange(ImageHeightPreferenceKey.self) { imageHeight in
|
||||
topImageHeight = imageHeight
|
||||
}
|
||||
#endif
|
||||
|
||||
VStack(spacing: 24) {
|
||||
// ID Login 按钮
|
||||
LoginButton(
|
||||
iconName: "person.circle.fill",
|
||||
iconColor: .green,
|
||||
title: NSLocalizedString("login.id_login", comment: "")
|
||||
) {
|
||||
showIDLogin = true // 直接设置SwiftUI状态
|
||||
}
|
||||
// Email Login 按钮
|
||||
LoginButton(
|
||||
iconName: "envelope.fill",
|
||||
iconColor: .blue,
|
||||
title: NSLocalizedString("login.email_login", comment: "")
|
||||
) {
|
||||
showEmailLogin = true // 显示邮箱登录界面
|
||||
}
|
||||
}.padding(.top, max(0, topImageHeight+140))
|
||||
}
|
||||
.onPreferenceChange(ImageHeightPreferenceKey.self) { imageHeight in
|
||||
topImageHeight = imageHeight
|
||||
}
|
||||
|
||||
// 间距,使登录按钮区域顶部距离"top"图片底部40pt
|
||||
Spacer()
|
||||
.frame(height: 120)
|
||||
// 间距,使登录按钮区域顶部距离"top"图片底部40pt
|
||||
Spacer()
|
||||
.frame(height: 120)
|
||||
|
||||
// 用户协议组件
|
||||
UserAgreementView(
|
||||
isAgreed: $isAgreedToTerms,
|
||||
onUserServiceTapped: {
|
||||
showUserAgreement = true
|
||||
},
|
||||
onPrivacyPolicyTapped: {
|
||||
showPrivacyPolicy = true
|
||||
}
|
||||
)
|
||||
.padding(.horizontal, 28)
|
||||
.padding(.bottom, 140)
|
||||
}
|
||||
|
||||
// 用户协议组件
|
||||
UserAgreementView(
|
||||
isAgreed: $isAgreedToTerms,
|
||||
onUserServiceTapped: {
|
||||
showUserAgreement = true
|
||||
},
|
||||
onPrivacyPolicyTapped: {
|
||||
showPrivacyPolicy = true
|
||||
}
|
||||
)
|
||||
.padding(.horizontal, 28)
|
||||
.padding(.bottom, 140)
|
||||
// 移除旧的 NavigationLink,改用 navigationDestination
|
||||
}
|
||||
|
||||
// 隐藏的NavigationLink - 使用纯SwiftUI方式
|
||||
NavigationLink(
|
||||
destination: IDLoginView(
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
// 新增:适配 iOS 16 的 navigationDestination
|
||||
.navigationDestination(isPresented: $showIDLogin) {
|
||||
WithPerceptionTracking {
|
||||
IDLoginView(
|
||||
store: store.scope(
|
||||
state: \.idLoginState,
|
||||
action: \.idLogin
|
||||
),
|
||||
onBack: {
|
||||
showIDLogin = false // 直接设置SwiftUI状态
|
||||
showIDLogin = false
|
||||
}
|
||||
)
|
||||
.navigationBarHidden(true),
|
||||
isActive: $showIDLogin // 使用SwiftUI的绑定
|
||||
) {
|
||||
EmptyView()
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
.hidden()
|
||||
|
||||
// 新增:邮箱登录的NavigationLink
|
||||
NavigationLink(
|
||||
destination: EMailLoginView(
|
||||
}
|
||||
.navigationDestination(isPresented: $showEmailLogin) {
|
||||
WithPerceptionTracking {
|
||||
EMailLoginView(
|
||||
store: store.scope(
|
||||
state: \.emailLoginState,
|
||||
action: \.emailLogin
|
||||
),
|
||||
onBack: {
|
||||
showEmailLogin = false // 直接设置SwiftUI状态
|
||||
showEmailLogin = false
|
||||
}
|
||||
)
|
||||
.navigationBarHidden(true),
|
||||
isActive: $showEmailLogin // 使用SwiftUI的绑定
|
||||
) {
|
||||
EmptyView()
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
// 移除:HomeView 的 navigationDestination
|
||||
}
|
||||
.sheet(isPresented: $showLanguageSettings) {
|
||||
WithPerceptionTracking {
|
||||
LanguageSettingsView(isPresented: $showLanguageSettings)
|
||||
}
|
||||
}
|
||||
.webView(
|
||||
isPresented: $showUserAgreement,
|
||||
url: APIConfiguration.webURL(for: .userAgreement)
|
||||
)
|
||||
.webView(
|
||||
isPresented: $showPrivacyPolicy,
|
||||
url: APIConfiguration.webURL(for: .privacyPolicy)
|
||||
)
|
||||
// 新增:监听登录成功,调用回调
|
||||
.onChange(of: viewStore.state) { completed in
|
||||
WithPerceptionTracking {
|
||||
if completed {
|
||||
onLoginSuccess()
|
||||
}
|
||||
.hidden()
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
.sheet(isPresented: $showLanguageSettings) {
|
||||
LanguageSettingsView(isPresented: $showLanguageSettings)
|
||||
}
|
||||
.webView(
|
||||
isPresented: $showUserAgreement,
|
||||
url: APIConfiguration.webURL(for: .userAgreement)
|
||||
)
|
||||
.webView(
|
||||
isPresented: $showPrivacyPolicy,
|
||||
url: APIConfiguration.webURL(for: .privacyPolicy)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
LoginView(
|
||||
store: Store(
|
||||
initialState: LoginFeature.State()
|
||||
) {
|
||||
LoginFeature()
|
||||
}
|
||||
)
|
||||
}
|
||||
//#Preview {
|
||||
// LoginView(
|
||||
// store: Store(
|
||||
// initialState: LoginFeature.State()
|
||||
// ) {
|
||||
// LoginFeature()
|
||||
// },
|
||||
// onLoginSuccess: {}
|
||||
// )
|
||||
//}
|
||||
|
Reference in New Issue
Block a user