完善流程
This commit is contained in:
parent
d74f58ad0e
commit
702eb1e608
56
punchnet/Views/Register/RegisterModel.swift
Normal file
56
punchnet/Views/Register/RegisterModel.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// LoginState.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/1/16.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@Observable
|
||||
class RegisterModel {
|
||||
|
||||
enum Stage {
|
||||
case requestVerifyCode
|
||||
case submitVerifyCode(username: String)
|
||||
case setPassword(username: String)
|
||||
}
|
||||
|
||||
var stage: Stage = .requestVerifyCode
|
||||
|
||||
private let baseParams: [String: Any] = [
|
||||
"client_id": SystemConfig.getClientId(),
|
||||
"mac": SystemConfig.macAddressString(mac: SystemConfig.getMacAddress())
|
||||
]
|
||||
|
||||
func requestVerifyCode(username: String) async throws -> String {
|
||||
var params: [String: Any] = [
|
||||
"username": username
|
||||
]
|
||||
params.merge(baseParams) {$1}
|
||||
|
||||
return try await SDLAPIClient.doPost(path: "/auth/sendVerifyCode", params: params, as: String.self)
|
||||
}
|
||||
|
||||
func submitVerifyCode(username: String, verifyCode: String) async throws -> String {
|
||||
var params: [String: Any] = [
|
||||
"username": username,
|
||||
"verify_code": verifyCode,
|
||||
]
|
||||
params.merge(baseParams) {$1}
|
||||
|
||||
return try await SDLAPIClient.doPost(path: "/auth/submitVerifyCode", params: params, as: String.self)
|
||||
}
|
||||
|
||||
func register(username: String, password: String) async throws -> String {
|
||||
var params: [String: Any] = [
|
||||
"username": username,
|
||||
"password": password,
|
||||
]
|
||||
params.merge(baseParams) {$1}
|
||||
|
||||
return try await SDLAPIClient.doPost(path: "/auth/resetPassword", params: params, as: String.self)
|
||||
}
|
||||
|
||||
}
|
||||
296
punchnet/Views/Register/RegisterView.swift
Normal file
296
punchnet/Views/Register/RegisterView.swift
Normal file
@ -0,0 +1,296 @@
|
||||
//
|
||||
// ResetPasswordView.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/3/9.
|
||||
//
|
||||
import SwiftUI
|
||||
|
||||
struct RegisterRootView: View {
|
||||
@State private var registerModel: RegisterModel = RegisterModel()
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
switch registerModel.stage {
|
||||
case .requestVerifyCode:
|
||||
RegisterRequestVerifyCodeView()
|
||||
case .submitVerifyCode(let username):
|
||||
RegisterSubmitVerifyCodeView(username: username)
|
||||
case .setPassword(username: let username):
|
||||
RegisterSetPasswordView(username: username)
|
||||
}
|
||||
}
|
||||
.environment(registerModel)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
struct RegisterRequestVerifyCodeView: View {
|
||||
@Environment(RegisterModel.self) var registerModel: RegisterModel
|
||||
|
||||
@State private var username: String = ""
|
||||
@State private var showAlert = false
|
||||
@State private var errorMessage = ""
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 30) {
|
||||
|
||||
// 标题
|
||||
Text("注册 创建个人网络")
|
||||
.font(.system(size: 18, weight: .medium))
|
||||
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
TextField("手机号/邮箱", text: $username)
|
||||
.textFieldStyle(.plain)
|
||||
.frame(width: 260, height: 28)
|
||||
.overlay(
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(.blue),
|
||||
alignment: .bottom
|
||||
)
|
||||
}
|
||||
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
//await self.sendVerifyCode()
|
||||
withAnimation {
|
||||
self.registerModel.stage = .submitVerifyCode(username: self.username)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Text("获取验证码")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.black)
|
||||
.frame(width: 160, height: 36)
|
||||
.background(Color(red: 74/255, green: 207/255, blue: 154/255))
|
||||
}
|
||||
.frame(width: 160, height: 36)
|
||||
.cornerRadius(6)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, 40)
|
||||
.frame(width: 400, height: 400)
|
||||
.alert(isPresented: $showAlert) {
|
||||
Alert(title: Text("提示"), message: Text(self.errorMessage))
|
||||
}
|
||||
}
|
||||
|
||||
private func sendVerifyCode() async {
|
||||
if username.isEmpty {
|
||||
self.showAlert = true
|
||||
self.errorMessage = "手机号/邮箱为空"
|
||||
return
|
||||
}
|
||||
|
||||
switch SDLUtil.identifyContact(username) {
|
||||
case .email, .phone:
|
||||
do {
|
||||
let result = try await self.registerModel.requestVerifyCode(username: username)
|
||||
print("send verify code result: \(result)")
|
||||
} catch {
|
||||
self.showAlert = true
|
||||
self.errorMessage = error.localizedDescription
|
||||
}
|
||||
|
||||
case .invalid:
|
||||
self.showAlert = true
|
||||
self.errorMessage = "手机号/邮箱格式错误"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 输入验证码
|
||||
struct RegisterSubmitVerifyCodeView: View {
|
||||
@Environment(RegisterModel.self) var registerModel: RegisterModel
|
||||
|
||||
@State var username: String
|
||||
@State private var verifiyCode: String = ""
|
||||
|
||||
@State private var showAlert = false
|
||||
@State private var errorMessage = ""
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 30) {
|
||||
|
||||
// 标题
|
||||
Text("注册 创建个人网络")
|
||||
.font(.system(size: 18, weight: .medium))
|
||||
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
TextField("手机号/邮箱", text: $username)
|
||||
.textFieldStyle(.plain)
|
||||
.frame(width: 260, height: 28)
|
||||
.disabled(true)
|
||||
.overlay(
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(.blue),
|
||||
alignment: .bottom
|
||||
)
|
||||
|
||||
HStack {
|
||||
TextField("验证码", text: $verifiyCode)
|
||||
.textFieldStyle(.plain)
|
||||
.frame(width: 260, height: 28)
|
||||
.overlay(
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(.blue),
|
||||
alignment: .bottom
|
||||
)
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
//await self.sendVerifyCode()
|
||||
}
|
||||
} label: {
|
||||
Text("再次获取")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.black)
|
||||
.frame(width: 160, height: 36)
|
||||
.background(Color(red: 74/255, green: 207/255, blue: 154/255))
|
||||
}
|
||||
.frame(width: 160, height: 36)
|
||||
.cornerRadius(6)
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
await self.submitVerifyCode()
|
||||
withAnimation {
|
||||
self.registerModel.stage = .setPassword(username: self.username)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Text("设置密码")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.black)
|
||||
.frame(width: 160, height: 36)
|
||||
.background(Color(red: 74/255, green: 207/255, blue: 154/255))
|
||||
}
|
||||
.frame(width: 160, height: 36)
|
||||
.cornerRadius(6)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, 40)
|
||||
.frame(width: 400, height: 400)
|
||||
.alert(isPresented: $showAlert) {
|
||||
Alert(title: Text("提示"), message: Text(self.errorMessage))
|
||||
}
|
||||
}
|
||||
|
||||
private func submitVerifyCode() async {
|
||||
if verifiyCode.isEmpty {
|
||||
self.showAlert = true
|
||||
self.errorMessage = "请输入验证码"
|
||||
return
|
||||
}
|
||||
|
||||
if verifiyCode.count != 4 {
|
||||
self.showAlert = true
|
||||
self.errorMessage = "验证码错误"
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let result = try await self.registerModel.submitVerifyCode(username: username, verifyCode: verifiyCode)
|
||||
print("submit verify code result: \(result)")
|
||||
} catch {
|
||||
self.showAlert = true
|
||||
self.errorMessage = error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 设置密码
|
||||
struct RegisterSetPasswordView: View {
|
||||
@Environment(RegisterModel.self) var registerModel: RegisterModel
|
||||
var username: String
|
||||
|
||||
@State private var password: String = ""
|
||||
@State private var confirmPassword: String = ""
|
||||
|
||||
@State private var showAlert = false
|
||||
@State private var errorMessage = ""
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 30) {
|
||||
|
||||
// 标题
|
||||
Text("注册 创建个人网络")
|
||||
.font(.system(size: 18, weight: .medium))
|
||||
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
SecureField("新密码", text: $password)
|
||||
.textFieldStyle(.plain)
|
||||
.frame(width: 260, height: 28)
|
||||
.overlay(
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(.blue),
|
||||
alignment: .bottom
|
||||
)
|
||||
|
||||
SecureField("再次输入密码", text: $confirmPassword)
|
||||
.textFieldStyle(.plain)
|
||||
.frame(width: 260, height: 28)
|
||||
.overlay(
|
||||
Rectangle()
|
||||
.frame(height: 1)
|
||||
.foregroundColor(.blue),
|
||||
alignment: .bottom
|
||||
)
|
||||
}
|
||||
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
await self.resetPassword()
|
||||
}
|
||||
} label: {
|
||||
Text("注册")
|
||||
.font(.system(size: 14))
|
||||
.foregroundColor(.black)
|
||||
.frame(width: 160, height: 36)
|
||||
.background(Color(red: 74/255, green: 207/255, blue: 154/255))
|
||||
}
|
||||
.frame(width: 160, height: 36)
|
||||
.cornerRadius(6)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, 40)
|
||||
.frame(width: 400, height: 400)
|
||||
.alert(isPresented: $showAlert) {
|
||||
Alert(title: Text("提示"), message: Text(self.errorMessage))
|
||||
}
|
||||
}
|
||||
|
||||
private func resetPassword() async {
|
||||
if password.isEmpty {
|
||||
self.showAlert = true
|
||||
self.errorMessage = "请输入新密码"
|
||||
return
|
||||
}
|
||||
|
||||
if confirmPassword.isEmpty || confirmPassword != password {
|
||||
self.showAlert = true
|
||||
self.errorMessage = "两次输入的密码不一致"
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let result = try await self.registerModel.register(username: username, password: self.password)
|
||||
print("send verify code result: \(result)")
|
||||
} catch {
|
||||
self.showAlert = true
|
||||
self.errorMessage = error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
56
punchnet/Views/ResetPassword/ResetPasswordModel.swift
Normal file
56
punchnet/Views/ResetPassword/ResetPasswordModel.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// LoginState.swift
|
||||
// punchnet
|
||||
//
|
||||
// Created by 安礼成 on 2026/1/16.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Observation
|
||||
|
||||
@Observable
|
||||
class ResetPasswordModel {
|
||||
|
||||
enum Stage {
|
||||
case requestVerifyCode
|
||||
case submitVerifyCode(username: String)
|
||||
case resetPassword(username: String)
|
||||
}
|
||||
|
||||
var stage: Stage = .requestVerifyCode
|
||||
|
||||
private let baseParams: [String: Any] = [
|
||||
"client_id": SystemConfig.getClientId(),
|
||||
"mac": SystemConfig.macAddressString(mac: SystemConfig.getMacAddress())
|
||||
]
|
||||
|
||||
func requestVerifyCode(username: String) async throws -> String {
|
||||
var params: [String: Any] = [
|
||||
"username": username
|
||||
]
|
||||
params.merge(baseParams) {$1}
|
||||
|
||||
return try await SDLAPIClient.doPost(path: "/auth/sendVerifyCode", params: params, as: String.self)
|
||||
}
|
||||
|
||||
func submitVerifyCode(username: String, verifyCode: String) async throws -> String {
|
||||
var params: [String: Any] = [
|
||||
"username": username,
|
||||
"verify_code": verifyCode,
|
||||
]
|
||||
params.merge(baseParams) {$1}
|
||||
|
||||
return try await SDLAPIClient.doPost(path: "/auth/submitVerifyCode", params: params, as: String.self)
|
||||
}
|
||||
|
||||
func resetPassword(username: String, password: String) async throws -> String {
|
||||
var params: [String: Any] = [
|
||||
"username": username,
|
||||
"password": password,
|
||||
]
|
||||
params.merge(baseParams) {$1}
|
||||
|
||||
return try await SDLAPIClient.doPost(path: "/auth/resetPassword", params: params, as: String.self)
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,31 +6,27 @@
|
||||
//
|
||||
import SwiftUI
|
||||
|
||||
enum ResetPasswordStage {
|
||||
case getVerifyCode
|
||||
case submitVerifyCode(username: String)
|
||||
case resetPassword(username: String)
|
||||
}
|
||||
|
||||
struct ResetPasswordRootView: View {
|
||||
@State private var stage: ResetPasswordStage = .getVerifyCode
|
||||
@State private var resetPasswordModel = ResetPasswordModel()
|
||||
|
||||
var body: some View {
|
||||
switch stage {
|
||||
case .getVerifyCode:
|
||||
GetVerifyCodeView(stage: $stage)
|
||||
case .submitVerifyCode(let username):
|
||||
SubmitVerifyCodeView(username: username, stage: $stage)
|
||||
case .resetPassword(let username):
|
||||
ResetPasswordView(stage: $stage, username: username)
|
||||
Group {
|
||||
switch resetPasswordModel.stage {
|
||||
case .requestVerifyCode:
|
||||
GetVerifyCodeView()
|
||||
case .submitVerifyCode(let username):
|
||||
SubmitVerifyCodeView(username: username)
|
||||
case .resetPassword(let username):
|
||||
ResetPasswordView(username: username)
|
||||
}
|
||||
}
|
||||
.environment(resetPasswordModel)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
struct GetVerifyCodeView: View {
|
||||
@Environment(UserContext.self) var userContext: UserContext
|
||||
@Binding var stage: ResetPasswordStage
|
||||
@Environment(ResetPasswordModel.self) var resetPasswordModel: ResetPasswordModel
|
||||
|
||||
@State private var username: String = ""
|
||||
@State private var showAlert = false
|
||||
@ -59,7 +55,7 @@ struct GetVerifyCodeView: View {
|
||||
Task { @MainActor in
|
||||
//await self.sendVerifyCode()
|
||||
withAnimation {
|
||||
self.stage = .submitVerifyCode(username: self.username)
|
||||
self.resetPasswordModel.stage = .submitVerifyCode(username: self.username)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
@ -91,7 +87,7 @@ struct GetVerifyCodeView: View {
|
||||
switch SDLUtil.identifyContact(username) {
|
||||
case .email, .phone:
|
||||
do {
|
||||
let result = try await self.userContext.sendVerifyCode(username: username)
|
||||
let result = try await self.resetPasswordModel.requestVerifyCode(username: username)
|
||||
print("send verify code result: \(result)")
|
||||
} catch {
|
||||
self.showAlert = true
|
||||
@ -107,11 +103,9 @@ struct GetVerifyCodeView: View {
|
||||
|
||||
// 输入验证码
|
||||
struct SubmitVerifyCodeView: View {
|
||||
@Environment(UserContext.self) var userContext: UserContext
|
||||
@Environment(ResetPasswordModel.self) var resetPasswordModel: ResetPasswordModel
|
||||
|
||||
@State var username: String
|
||||
@Binding var stage: ResetPasswordStage
|
||||
|
||||
@State private var verifiyCode: String = ""
|
||||
|
||||
@State private var showAlert = false
|
||||
@ -168,7 +162,7 @@ struct SubmitVerifyCodeView: View {
|
||||
Task { @MainActor in
|
||||
await self.submitVerifyCode()
|
||||
withAnimation {
|
||||
self.stage = .resetPassword(username: username)
|
||||
self.resetPasswordModel.stage = .resetPassword(username: username)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
@ -204,7 +198,7 @@ struct SubmitVerifyCodeView: View {
|
||||
}
|
||||
|
||||
do {
|
||||
let result = try await self.userContext.submitVerifyCode(username: username, verifyCode: verifiyCode)
|
||||
let result = try await self.resetPasswordModel.submitVerifyCode(username: username, verifyCode: verifiyCode)
|
||||
print("submit verify code result: \(result)")
|
||||
} catch {
|
||||
self.showAlert = true
|
||||
@ -216,8 +210,8 @@ struct SubmitVerifyCodeView: View {
|
||||
|
||||
// 重置密码
|
||||
struct ResetPasswordView: View {
|
||||
@Environment(UserContext.self) var userContext: UserContext
|
||||
@Binding var stage: ResetPasswordStage
|
||||
@Environment(ResetPasswordModel.self) var resetPasswordModel: ResetPasswordModel
|
||||
|
||||
var username: String
|
||||
|
||||
@State private var password: String = ""
|
||||
@ -258,7 +252,6 @@ struct ResetPasswordView: View {
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
await self.resetPassword()
|
||||
self.stage = .resetPassword(username: username)
|
||||
}
|
||||
} label: {
|
||||
Text("保存")
|
||||
@ -293,7 +286,7 @@ struct ResetPasswordView: View {
|
||||
}
|
||||
|
||||
do {
|
||||
let result = try await self.userContext.resetPassword(username: username, password: self.password)
|
||||
let result = try await self.resetPasswordModel.resetPassword(username: username, password: self.password)
|
||||
print("send verify code result: \(result)")
|
||||
} catch {
|
||||
self.showAlert = true
|
||||
@ -96,6 +96,12 @@ struct punchnetApp: App {
|
||||
}
|
||||
.defaultSize(width: 800, height: 500)
|
||||
|
||||
Window("注册", id: "register") {
|
||||
ResetPasswordRootView()
|
||||
.environment(self.userContext)
|
||||
}
|
||||
.defaultSize(width: 800, height: 500)
|
||||
|
||||
MenuBarExtra("punchnet", image: "logo_32") {
|
||||
VStack {
|
||||
Button(action: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user