完善注册和找回密码逻辑

This commit is contained in:
anlicheng 2026-03-20 22:17:45 +08:00
parent 9727fd1096
commit e86cf5e422
4 changed files with 110 additions and 10 deletions

View File

@ -16,6 +16,7 @@ class ResetPasswordModel {
case requestVerifyCode(username: String?) case requestVerifyCode(username: String?)
case submitVerifyCode(username: String, sessionId: Int) case submitVerifyCode(username: String, sessionId: Int)
case resetPassword(username: String, sessionId: Int) case resetPassword(username: String, sessionId: Int)
case success
} }
var stage: Stage = .requestVerifyCode(username: nil) var stage: Stage = .requestVerifyCode(username: nil)

View File

@ -25,6 +25,8 @@ struct ResetPasswordRootView: View {
SubmitVerifyCodeView(username: username, sessionId: sessionId) SubmitVerifyCodeView(username: username, sessionId: sessionId)
case .resetPassword(let username, let sessionId): case .resetPassword(let username, let sessionId):
ResetPasswordView(username: username, sessionId: sessionId) ResetPasswordView(username: username, sessionId: sessionId)
case .success:
ResetPasswordSuccessView()
} }
} }
.transition(.asymmetric( .transition(.asymmetric(
@ -277,9 +279,10 @@ struct ResetPasswordView: View {
do { do {
let result = try await resetPasswordModel.resetPassword(sessionId: sessionId, newPassword: password) let result = try await resetPasswordModel.resetPassword(sessionId: sessionId, newPassword: password)
print("密码重置成功: \(result)") print("密码重置成功: \(result)")
// withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.showAlert = true self.resetPasswordModel.stage = .success
self.errorMessage = "重置成功,重新登陆" self.resetPasswordModel.transitionEdge = .trailing
}
} catch { } catch {
self.showAlert = true self.showAlert = true
self.errorMessage = "重置失败, 请稍后重试" self.errorMessage = "重置失败, 请稍后重试"
@ -289,3 +292,69 @@ struct ResetPasswordView: View {
} }
} }
struct ResetPasswordSuccessView: View {
@Environment(\.dismiss) private var dismiss
//
@State private var animateIcon = false
@State private var animateText = false
var body: some View {
VStack(spacing: 32) {
Spacer()
// (使绿)
ZStack {
Circle()
.fill(Color.blue.opacity(0.1))
.frame(width: 100, height: 100)
.scaleEffect(animateIcon ? 1.1 : 0.95)
.opacity(animateIcon ? 0.8 : 1.0)
Image(systemName: "lock.circle.fill")
.font(.system(size: 56))
.foregroundStyle(.blue.gradient)
.scaleEffect(animateIcon ? 1.05 : 1.0)
}
.transition(.move(edge: .bottom).combined(with: .opacity))
VStack(spacing: 32) {
VStack(spacing: 12) {
Text("密码重置成功")
.font(.title2.bold())
Text("您的新密码已生效。\n为了安全,建议您立即尝试使用新密码登录。")
.font(.subheadline)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
}
Button(action: {
dismiss() //
}) {
Text("返回登录")
.fontWeight(.bold)
.frame(width: 200)
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
.tint(.blue)
}
.opacity(animateText ? 1.0 : 0.0)
.offset(y: animateText ? 0 : 20)
Spacer()
}
.padding(40)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
withAnimation(.easeInOut(duration: 1.5).repeatForever(autoreverses: true)) {
animateIcon = true
}
withAnimation(.spring(duration: 0.6, bounce: 0.3).delay(0.4)) {
animateText = true
}
}
}
}

View File

@ -8,6 +8,8 @@ import SwiftUI
// MARK: - () // MARK: - ()
struct SettingsUserIssueView: View { struct SettingsUserIssueView: View {
@Environment(UserContext.self) var userContext: UserContext
// //
@State private var account: String = "" @State private var account: String = ""
@State private var text: String = "" @State private var text: String = ""
@ -26,6 +28,7 @@ struct SettingsUserIssueView: View {
HStack(spacing: 12) { HStack(spacing: 12) {
Image(systemName: "envelope.badge.fill") Image(systemName: "envelope.badge.fill")
.foregroundColor(.blue) .foregroundColor(.blue)
Text("用户反馈") Text("用户反馈")
.font(.system(size: 18, weight: .bold)) .font(.system(size: 18, weight: .bold))
} }
@ -48,7 +51,10 @@ struct SettingsUserIssueView: View {
// ( Placeholder ) // ( Placeholder )
VStack(alignment: .leading, spacing: 8) { VStack(alignment: .leading, spacing: 8) {
Text("问题描述").font(.caption.bold()).foregroundColor(.secondary) Text("问题描述")
.font(.caption.bold())
.foregroundColor(.secondary)
ZStack(alignment: .topLeading) { ZStack(alignment: .topLeading) {
if text.isEmpty { if text.isEmpty {
Text("请详细描述您遇到的问题...") Text("请详细描述您遇到的问题...")
@ -73,10 +79,15 @@ struct SettingsUserIssueView: View {
.overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.primary.opacity(0.05), lineWidth: 1)) .overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.primary.opacity(0.05), lineWidth: 1))
// 3. // 3.
Button(action: submitFeedback) { Button {
Task { @MainActor in
await self.submitFeedback()
}
} label: {
HStack { HStack {
if isSubmitting { if isSubmitting {
ProgressView().controlSize(.small).brightness(1) ProgressView()
.controlSize(.small).brightness(1)
} else { } else {
Image(systemName: "paperplane.fill") Image(systemName: "paperplane.fill")
} }
@ -105,8 +116,28 @@ struct SettingsUserIssueView: View {
} }
// MARK: - // MARK: -
private func submitFeedback() { private func submitFeedback() async {
withAnimation { isSubmitting = true } withAnimation {
isSubmitting = true
}
var params: [String: Any] = [
"access_token": self.userContext.networkSession?.accessToken ?? "",
"contact": self.account,
"platform": SystemConfig.systemInfo,
"content": self.text,
"client_id": SystemConfig.getClientId(),
"mac": SystemConfig.macAddressString(mac: SystemConfig.getMacAddress())
]
do {
_ = try await SDLAPIClient.doPost(path: "/app/issue", params: params, as: String.self)
} catch let err as SDLAPIError {
} catch let err {
}
// //
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {

View File

@ -46,8 +46,7 @@ struct punchnetApp: App {
var body: some Scene { var body: some Scene {
WindowGroup(id: "main") { WindowGroup(id: "main") {
//RootView() //RootView()
//RegisterRootView() SettingsUserIssueView()
RegisterSuccessView()
.navigationTitle("") .navigationTitle("")
.environment(self.appContext) .environment(self.appContext)
.environment(self.userContext) .environment(self.userContext)