punchnet-macos/punchnet/Views/ResetPassword/ResetPasswordView.swift
2026-03-09 23:05:30 +08:00

298 lines
9.5 KiB
Swift

//
// ResetPasswordView.swift
// punchnet
//
// Created by on 2026/3/9.
//
import SwiftUI
struct ResetPasswordRootView: View {
@State private var resetPasswordModel = ResetPasswordModel()
var body: some View {
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(ResetPasswordModel.self) var resetPasswordModel: ResetPasswordModel
@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.resetPasswordModel.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.resetPasswordModel.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 SubmitVerifyCodeView: View {
@Environment(ResetPasswordModel.self) var resetPasswordModel: ResetPasswordModel
@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.resetPasswordModel.stage = .resetPassword(username: 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.resetPasswordModel.submitVerifyCode(username: username, verifyCode: verifiyCode)
print("submit verify code result: \(result)")
} catch {
self.showAlert = true
self.errorMessage = error.localizedDescription
}
}
}
//
struct ResetPasswordView: View {
@Environment(ResetPasswordModel.self) var resetPasswordModel: ResetPasswordModel
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.resetPasswordModel.resetPassword(username: username, password: self.password)
print("send verify code result: \(result)")
} catch {
self.showAlert = true
self.errorMessage = error.localizedDescription
}
}
}