修改这册流程

This commit is contained in:
anlicheng 2026-03-23 23:10:15 +08:00
parent 883f9d7f64
commit c9c507974e
7 changed files with 148 additions and 80 deletions

View File

@ -17,14 +17,14 @@ class AppContext {
//
enum AppScene {
case login
case login(username: String?)
case logined
case register
case resetPassword
}
// app
var appScene: AppScene = .login
var appScene: AppScene = .login(username: nil)
init(noticePort: Int) {
self.noticePort = noticePort

View File

@ -12,6 +12,8 @@ struct LoginView: View {
@Environment(UserContext.self) var userContext: UserContext
@State private var authMethod: AuthMethod = .account
var username: String?
enum AuthMethod: String, CaseIterable {
case account = "账户登录"
case token = "密钥认证"
@ -54,7 +56,7 @@ struct LoginView: View {
LoginTokenView()
.transition(.move(edge: .trailing).combined(with: .opacity))
} else {
LoginAccountView()
LoginAccountView(username: self.username ?? "")
.transition(.move(edge: .leading).combined(with: .opacity))
}
}
@ -88,8 +90,8 @@ struct LoginAccountView: View {
@Environment(UserContext.self) var userContext: UserContext
@Environment(AppContext.self) var appContext: AppContext
@State private var username = ""
@State private var password = ""
@State var username: String = ""
@State private var password: String = ""
@State private var isLoading = false
//

View File

@ -12,10 +12,10 @@ import SwiftUI
@Observable
class RegisterModel {
enum Stage {
case requestVerifyCode(username: String?)
case submitVerifyCode(username: String, sessionId: Int)
case setPassword(sessionId: Int)
enum Stage: Equatable {
case requestVerifyCode
case submitVerifyCode
case setPassword
case success
}
@ -28,7 +28,11 @@ class RegisterModel {
}
}
var stage: Stage = .requestVerifyCode(username: nil)
//
var username: String = ""
var sessionId: Int = 0
var stage: Stage = .requestVerifyCode
var transitionEdge: Edge = .trailing //
private let baseParams: [String: Any] = [

View File

@ -10,6 +10,7 @@ import Observation
// MARK: -
struct RegisterRootView: View {
@State private var registerModel = RegisterModel()
@Environment(AppContext.self) private var appContext: AppContext
var body: some View {
ZStack {
@ -19,12 +20,12 @@ struct RegisterRootView: View {
Group {
switch registerModel.stage {
case .requestVerifyCode(let username):
RegisterRequestVerifyCodeView(username: username ?? "")
case .submitVerifyCode(let username, let sessionId):
RegisterSubmitVerifyCodeView(username: username, sessionId: sessionId)
case .setPassword(let sessionId):
RegisterSetPasswordView(sessionId: sessionId)
case .requestVerifyCode:
RegisterRequestVerifyCodeView()
case .submitVerifyCode:
RegisterSubmitVerifyCodeView()
case .setPassword:
RegisterSetPasswordView()
case .success:
RegisterSuccessView()
}
@ -35,6 +36,34 @@ struct RegisterRootView: View {
))
}
.environment(registerModel)
// --- 使 overlay ---
.overlay(alignment: .topLeading) {
//
switch registerModel.stage {
case .success:
EmptyView()
default:
Button(action: {
//
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.appContext.appScene = .login(username: nil)
}
}) {
HStack {
Image(systemName: "chevron.left")
.font(.system(size: 16, weight: .semibold))
.padding(5)
Text("首页")
.font(.system(size: 16, weight: .regular))
}
.contentShape(Rectangle()) //
}
.buttonStyle(.plain)
.padding([.top, .leading], 16) //
.transition(.opacity) //
}
}
.frame(width: 500, height: 400)
}
}
@ -74,8 +103,7 @@ struct PunchTextField: View {
// MARK: -
struct RegisterRequestVerifyCodeView: View {
@Environment(RegisterModel.self) var registerModel
@State var username: String = ""
@Environment(RegisterModel.self) var registerModel: RegisterModel
@State private var isProcessing = false
//
@ -83,16 +111,18 @@ struct RegisterRequestVerifyCodeView: View {
@State private var errorMessage: String = ""
var body: some View {
@Bindable var model = registerModel
VStack(spacing: 24) {
headerSection(title: "创建个人网络", subtitle: "输入邮箱开始注册")
VStack(spacing: 16) {
PunchTextField(icon: "person.crop.circle", placeholder: "邮箱", text: $username)
PunchTextField(icon: "person.crop.circle", placeholder: "邮箱", text: $model.username)
}
.frame(width: 280)
Button(action: {
self.requestVerifyCode()
self.requestVerifyCode(username: model.username)
}) {
Text("获取验证码")
.fontWeight(.medium)
@ -101,7 +131,7 @@ struct RegisterRequestVerifyCodeView: View {
.buttonStyle(.borderedProminent)
.controlSize(.large)
.frame(width: 280)
.disabled(!SDLUtil.isValidIdentifyContact(username) || isProcessing)
.disabled(!SDLUtil.isValidIdentifyContact(model.username) || isProcessing)
Spacer()
}
@ -111,7 +141,7 @@ struct RegisterRequestVerifyCodeView: View {
}
}
private func requestVerifyCode() {
private func requestVerifyCode(username: String) {
self.isProcessing = true
Task { @MainActor in
if username.isEmpty {
@ -126,7 +156,10 @@ struct RegisterRequestVerifyCodeView: View {
do {
let registerSession = try await self.registerModel.requestVerifyCode(username: username)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .submitVerifyCode(username: username, sessionId: registerSession.sessionId)
self.registerModel.stage = .submitVerifyCode
self.registerModel.username = username
self.registerModel.sessionId = registerSession.sessionId
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
@ -148,10 +181,7 @@ struct RegisterRequestVerifyCodeView: View {
// MARK: -
struct RegisterSubmitVerifyCodeView: View {
@Environment(RegisterModel.self) var registerModel
let username: String
let sessionId: Int
@Environment(RegisterModel.self) var registerModel: RegisterModel
@State private var code: String = ""
@State private var isProcessing = false
@ -172,13 +202,15 @@ struct RegisterSubmitVerifyCodeView: View {
var body: some View {
VStack(spacing: 24) {
headerSection(title: "身份验证", subtitle: "验证码已发送至 \(username)")
headerSection(title: "身份验证", subtitle: "验证码已发送至 \(registerModel.username)")
VStack(alignment: .trailing, spacing: 16) {
PunchTextField(icon: "envelope.badge", placeholder: "输入 6 位验证码", text: $code)
Button {
self.resendVerifyCodeAction()
Task { @MainActor in
await self.resendVerifyCodeAction(username: registerModel.username)
}
} label: {
if isEnabled {
Text("没有收到?重新获取")
@ -194,7 +226,9 @@ struct RegisterSubmitVerifyCodeView: View {
VStack(spacing: 12) {
Button(action: {
self.submitVerifyCode()
Task { @MainActor in
await self.submitVerifyCode(sessionId: registerModel.sessionId)
}
}) {
Text("验证并设置密码")
.fontWeight(.medium)
@ -206,7 +240,8 @@ struct RegisterSubmitVerifyCodeView: View {
Button("返回上一步") {
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .requestVerifyCode(username: self.username)
self.registerModel.stage = .requestVerifyCode
self.registerModel.transitionEdge = .leading
}
}
@ -227,17 +262,15 @@ struct RegisterSubmitVerifyCodeView: View {
}
//
private func resendVerifyCodeAction() {
Task {
do {
let result = try await self.registerModel.requestVerifyCode(username: username)
print("send verify code result: \(result)")
} catch let err {
print("resend verify get error: \(err)")
}
//
await self.startCountdown()
private func resendVerifyCodeAction(username: String) async {
do {
let result = try await self.registerModel.requestVerifyCode(username: username)
print("send verify code result: \(result)")
} catch let err {
print("resend verify get error: \(err)")
}
//
await self.startCountdown()
}
//
@ -252,32 +285,31 @@ struct RegisterSubmitVerifyCodeView: View {
}
//
private func submitVerifyCode() {
private func submitVerifyCode(sessionId: Int) async {
self.isProcessing = true
Task { @MainActor in
do {
_ = try await self.registerModel.submitVerifyCode(sessionId: sessionId, verifyCode: self.code)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .setPassword(sessionId: sessionId)
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
self.showAlert = true
self.errorMessage = err.message
} catch let err {
self.showAlert = true
self.errorMessage = err.localizedDescription
}
defer {
self.isProcessing = false
}
do {
_ = try await self.registerModel.submitVerifyCode(sessionId: sessionId, verifyCode: self.code)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .setPassword
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
self.showAlert = true
self.errorMessage = err.message
} catch let err {
self.showAlert = true
self.errorMessage = err.localizedDescription
}
}
}
// MARK: -
struct RegisterSetPasswordView: View {
@Environment(RegisterModel.self) var registerModel
let sessionId: Int
@Environment(RegisterModel.self) var registerModel: RegisterModel
@State private var password = ""
@State private var confirm = ""
@State private var isProcessing = false
@ -318,7 +350,9 @@ struct RegisterSetPasswordView: View {
.frame(width: 280)
Button(action: {
self.handleRegister()
Task { @MainActor in
await self.handleRegister(sessionId: registerModel.sessionId)
}
}) {
if isProcessing {
ProgressView()
@ -342,32 +376,33 @@ struct RegisterSetPasswordView: View {
}
}
private func handleRegister() {
private func handleRegister(sessionId: Int) async {
self.isProcessing = true
Task { @MainActor in
do {
_ = try await self.registerModel.register(sessionId: sessionId, password: self.password)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .success
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
self.showAlert = true
self.errorMessage = err.message
} catch {
self.showAlert = true
self.errorMessage = "注册失败,重稍后重试"
}
defer {
self.isProcessing = false
}
do {
_ = try await self.registerModel.register(sessionId: sessionId, password: self.password)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .success
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
self.showAlert = true
self.errorMessage = err.message
} catch {
self.showAlert = true
self.errorMessage = "注册失败,重稍后重试"
}
}
}
// MARK:
struct RegisterSuccessView: View {
@Environment(\.dismiss) private var dismiss //
@Environment(AppContext.self) private var appContext: AppContext
@Environment(RegisterModel.self) private var registerModel: RegisterModel
// MARK: -
@State private var animateIcon: Bool = false //
@State private var animateText: Bool = false //
@ -410,7 +445,9 @@ struct RegisterSuccessView: View {
Button(action: {
//
dismiss()
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.appContext.appScene = .login(username: registerModel.username)
}
}) {
Text("立即开始使用")
.fontWeight(.bold)

View File

@ -12,7 +12,7 @@ import SwiftUI
@Observable
class ResetPasswordModel {
enum Stage {
enum Stage: Equatable {
case requestVerifyCode(username: String?)
case submitVerifyCode(username: String, sessionId: Int)
case resetPassword(username: String, sessionId: Int)

View File

@ -10,6 +10,7 @@ import Observation
// MARK: - 1.
struct ResetPasswordRootView: View {
@State private var resetPasswordModel = ResetPasswordModel()
@Environment(AppContext.self) private var appContext: AppContext
var body: some View {
ZStack {
@ -35,6 +36,30 @@ struct ResetPasswordRootView: View {
))
}
.environment(resetPasswordModel)
.overlay(alignment: .topLeading) {
//
if resetPasswordModel.stage != .success {
Button(action: {
//
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.appContext.appScene = .login(username: nil)
}
}) {
HStack {
Image(systemName: "chevron.left")
.font(.system(size: 16, weight: .semibold))
.padding(5)
Text("首页")
.font(.system(size: 16, weight: .regular))
}
.contentShape(Rectangle()) //
}
.buttonStyle(.plain)
.padding([.top, .leading], 16) //
.transition(.opacity) //
}
}
.frame(width: 500, height: 400)
}
}

View File

@ -18,7 +18,7 @@ struct RootView: View {
//
Group {
switch appContext.appScene {
case .login:
case .login(username: let username):
LoginView()
case .logined:
NetworkView()