From e4a0728345478fe479e7efc334ea6ec02e057414 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Tue, 24 Mar 2026 18:05:42 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3UI=E7=9A=84=E5=B8=83=E5=B1=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- punchnet/Views/AppContext.swift | 17 ++++---- punchnet/Views/Login/LoginView.swift | 9 ++-- .../{RootView.swift => LoginRootView.swift} | 18 +++----- punchnet/Views/Register/RegisterView.swift | 40 +++++++++--------- .../ResetPassword/ResetPasswordView.swift | 42 +++++++++---------- punchnet/punchnetApp.swift | 12 +++++- 6 files changed, 65 insertions(+), 73 deletions(-) rename punchnet/Views/{RootView.swift => LoginRootView.swift} (85%) diff --git a/punchnet/Views/AppContext.swift b/punchnet/Views/AppContext.swift index fd0ba93..31b8c5b 100644 --- a/punchnet/Views/AppContext.swift +++ b/punchnet/Views/AppContext.swift @@ -16,7 +16,14 @@ class AppContext { var networkContext: SDLAPIClient.NetworkContext = .default() // 当前app所处的场景 - var appScene: AppScene = .login(username: nil) + var loginScene: LoginScene = .login(username: nil) + + // 当前的场景 + enum LoginScene: Equatable { + case login(username: String?) + case register + case resetPassword + } // 登陆凭证 var loginCredit: Credit? @@ -40,14 +47,6 @@ class AppContext { } } - // 当前的场景 - enum AppScene: Equatable { - case login(username: String?) - case logined - case register - case resetPassword - } - init(noticePort: Int) { self.noticePort = noticePort } diff --git a/punchnet/Views/Login/LoginView.swift b/punchnet/Views/Login/LoginView.swift index c46cf5e..8757f4b 100644 --- a/punchnet/Views/Login/LoginView.swift +++ b/punchnet/Views/Login/LoginView.swift @@ -77,7 +77,6 @@ struct LoginView: View { } .padding(.bottom, 20) } - .frame(width: 380, height: 520) } } @@ -106,7 +105,7 @@ struct LoginAccountView: View { HStack { Button("注册") { withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .register + self.appContext.loginScene = .register } } .buttonStyle(.link) @@ -115,7 +114,7 @@ struct LoginAccountView: View { Button("忘记密码?") { withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .resetPassword + self.appContext.loginScene = .resetPassword } } .buttonStyle(.link) @@ -170,7 +169,7 @@ struct LoginAccountView: View { do { _ = try await appContext.loginWith(username: username, password: password) withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .logined + //self.appContext.appScene = .logined } } catch let err as SDLAPIError { self.showAlert = true @@ -231,7 +230,7 @@ struct LoginTokenView: View { do { _ = try await appContext.loginWith(token: token) withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .logined + //self.appContext.appScene = .logined } } catch let err as SDLAPIError { self.showAlert = true diff --git a/punchnet/Views/RootView.swift b/punchnet/Views/LoginRootView.swift similarity index 85% rename from punchnet/Views/RootView.swift rename to punchnet/Views/LoginRootView.swift index a6f309a..d537d50 100644 --- a/punchnet/Views/RootView.swift +++ b/punchnet/Views/LoginRootView.swift @@ -7,7 +7,7 @@ import SwiftUI -struct RootView: View { +struct LoginRootView: View { @Environment(AppContext.self) var appContext: AppContext @State private var updateManager = AppUpdateManager.shared @@ -16,13 +16,10 @@ struct RootView: View { // 1. 主要界面容器 // 使用 ZStack 代替 Group,因为它在处理内容对齐和转场重叠时更稳定 ZStack(alignment: .center) { - switch appContext.appScene { + switch appContext.loginScene { case .login(username: let username): LoginView(username: username) .id("scene_login") // 显式 ID 确保转场触发 - case .logined: - NetworkView() - .id("scene_logined") case .register: RegisterRootView() .id("scene_register") @@ -32,9 +29,7 @@ struct RootView: View { } } // 2. 关键:设置容器尺寸行为 - // 如果是全屏应用,用 maxWidth/Height .infinity - // 如果是固定大小窗口,可以在这里写死 minWidth/minHeight - .frame(maxWidth: .infinity, maxHeight: .infinity) + .frame(width: 380, height: 500) // 3. 限制裁剪,防止位移动画超出 RootView 的边界 .clipped() .transition(.asymmetric( @@ -48,7 +43,7 @@ struct RootView: View { } } // 4. 统一处理 Scene 切换的动画 - .animation(.spring(duration: 0.5), value: appContext.appScene) + .animation(.spring(duration: 0.5), value: appContext.loginScene) .animation(.spring(duration: 0.4), value: updateManager.showUpdateOverlay) // 关键:macOS 标准毛玻璃背景 .background(VisualEffectView(material: .hudWindow, blendingMode: .behindWindow)) @@ -82,8 +77,5 @@ struct RootView: View { )) .zIndex(100) // 确保更新遮罩永远在最上层 } -} - -#Preview { - RootView() + } diff --git a/punchnet/Views/Register/RegisterView.swift b/punchnet/Views/Register/RegisterView.swift index 077ada4..626b8f7 100644 --- a/punchnet/Views/Register/RegisterView.swift +++ b/punchnet/Views/Register/RegisterView.swift @@ -14,21 +14,25 @@ struct RegisterRootView: View { var body: some View { ZStack(alignment: .center) { - switch registerModel.stage { - case .requestVerifyCode: - RegisterRequestVerifyCodeView() - case .submitVerifyCode: - RegisterSubmitVerifyCodeView() - case .setPassword: - RegisterSetPasswordView() - case .success: - RegisterSuccessView() + Color.clear + + ZStack(alignment: .center) { + switch registerModel.stage { + case .requestVerifyCode: + RegisterRequestVerifyCodeView() + case .submitVerifyCode: + RegisterSubmitVerifyCodeView() + case .setPassword: + RegisterSetPasswordView() + case .success: + RegisterSuccessView() + } } + .transition(.asymmetric( + insertion: .move(edge: registerModel.transitionEdge).combined(with: .opacity), + removal: .move(edge: registerModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity) + )) } - .transition(.asymmetric( - insertion: .move(edge: registerModel.transitionEdge).combined(with: .opacity), - removal: .move(edge: registerModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity) - )) .environment(registerModel) // --- 核心改动:使用 overlay --- .overlay(alignment: .topLeading) { @@ -40,7 +44,7 @@ struct RegisterRootView: View { Button(action: { // 执行返回逻辑,例如重置到登录 withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .login(username: nil) + self.appContext.loginScene = .login(username: nil) } }) { HStack { @@ -127,8 +131,6 @@ struct RegisterRequestVerifyCodeView: View { .controlSize(.large) .frame(width: 280) .disabled(!SDLUtil.isValidIdentifyContact(model.username) || isProcessing) - - Spacer() } .padding(40) .alert(isPresented: $showAlert) { @@ -244,8 +246,6 @@ struct RegisterSubmitVerifyCodeView: View { .foregroundColor(.secondary) } .frame(width: 280) - - Spacer() } .padding(40) .alert(isPresented: $showAlert) { @@ -362,8 +362,6 @@ struct RegisterSetPasswordView: View { .controlSize(.large) .frame(width: 280) .disabled(passwordError != nil) - - Spacer() } .padding(40) .alert(isPresented: $showAlert) { @@ -441,7 +439,7 @@ struct RegisterSuccessView: View { Button(action: { // 关闭当前注册窗口 withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .login(username: registerModel.username) + self.appContext.loginScene = .login(username: registerModel.username) } }) { Text("立即开始使用") diff --git a/punchnet/Views/ResetPassword/ResetPasswordView.swift b/punchnet/Views/ResetPassword/ResetPasswordView.swift index b087077..552e15f 100644 --- a/punchnet/Views/ResetPassword/ResetPasswordView.swift +++ b/punchnet/Views/ResetPassword/ResetPasswordView.swift @@ -14,21 +14,25 @@ struct ResetPasswordRootView: View { var body: some View { ZStack(alignment: .center) { - switch resetPasswordModel.stage { - case .requestVerifyCode: - GetVerifyCodeView() - case .submitVerifyCode: - SubmitVerifyCodeView() - case .resetPassword: - ResetPasswordView() - case .success: - ResetPasswordSuccessView() + Color.clear + + ZStack(alignment: .center) { + switch resetPasswordModel.stage { + case .requestVerifyCode: + GetVerifyCodeView() + case .submitVerifyCode: + SubmitVerifyCodeView() + case .resetPassword: + ResetPasswordView() + case .success: + ResetPasswordSuccessView() + } } + .transition(.asymmetric( + insertion: .move(edge: resetPasswordModel.transitionEdge).combined(with: .opacity), + removal: .move(edge: resetPasswordModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity) + )) } - .transition(.asymmetric( - insertion: .move(edge: resetPasswordModel.transitionEdge).combined(with: .opacity), - removal: .move(edge: resetPasswordModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity) - )) .environment(resetPasswordModel) .overlay(alignment: .topLeading) { // 仅在非成功页面显示返回按钮 @@ -36,7 +40,7 @@ struct ResetPasswordRootView: View { Button(action: { // 执行返回逻辑,例如重置到登录 withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .login(username: nil) + self.appContext.loginScene = .login(username: nil) } }) { HStack { @@ -86,8 +90,6 @@ struct GetVerifyCodeView: View { .controlSize(.large) .frame(width: 280) .disabled(!SDLUtil.isValidIdentifyContact(model.username) || isProcessing) - - Spacer() } .padding(40) .alert(isPresented: $showAlert) { @@ -179,8 +181,6 @@ struct SubmitVerifyCodeView: View { .foregroundColor(.secondary) } .frame(width: 280) - - Spacer() } .padding(40) .task { @@ -294,8 +294,6 @@ struct ResetPasswordView: View { .controlSize(.large) .frame(width: 280) .disabled(!isInputValid || isProcessing) - - Spacer() } .padding(40) .alert(isPresented: $showAlert) { @@ -364,7 +362,7 @@ struct ResetPasswordSuccessView: View { Button(action: { withAnimation(.spring(duration: 0.6, bounce: 0.2)) { - self.appContext.appScene = .login(username: self.resetPasswordModel.username) + self.appContext.loginScene = .login(username: self.resetPasswordModel.username) } }) { Text("返回登录") @@ -377,8 +375,6 @@ struct ResetPasswordSuccessView: View { } .opacity(animateText ? 1.0 : 0.0) .offset(y: animateText ? 0 : 20) - - Spacer() } .padding(40) .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/punchnet/punchnetApp.swift b/punchnet/punchnetApp.swift index 2ed4c66..2fb5f1f 100644 --- a/punchnet/punchnetApp.swift +++ b/punchnet/punchnetApp.swift @@ -43,8 +43,8 @@ struct punchnetApp: App { } var body: some Scene { - WindowGroup(id: "main") { - RootView() + Window("登陆", id: "login") { + LoginRootView() .navigationTitle("") .environment(self.appContext) .onAppear { @@ -59,6 +59,14 @@ struct punchnetApp: App { .windowToolbarStyle(.unified) .defaultPosition(.center) + Window("网络", id: "logined") { + SettingsView() + .environment(self.appContext) + .frame(width: 750, height: 500) + } + .windowResizability(.contentSize) + .defaultPosition(.center) + Window("设置", id: "settings") { SettingsView() .environment(self.appContext)