修复登录问题
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-12-12 16:45:50 +08:00
parent ff0954a413
commit e17437a5ad
3 changed files with 105 additions and 15 deletions

View File

@@ -108,7 +108,8 @@
"nameRequired": "Please enter your name",
"emailRequired": "Please enter your email",
"passwordRequired": "Please enter your password",
"confirmPasswordRequired": "Please confirm your password"
"confirmPasswordRequired": "Please confirm your password",
"loading": "Loading..."
},
"memorize": {
"folder_selector": {

View File

@@ -1,6 +1,6 @@
"use client";
import { useState, useActionState } from "react";
import { useState, useActionState, startTransition } from "react";
import { useTranslations } from "next-intl";
import { signInAction, signUpAction, SignUpState } from "@/lib/actions/auth";
import Container from "@/components/ui/Container";
@@ -16,13 +16,27 @@ interface AuthFormProps {
export default function AuthForm({ redirectTo }: AuthFormProps) {
const t = useTranslations("auth");
const [mode, setMode] = useState<'signin' | 'signup'>('signin');
const [clearSignIn, setClearSignIn] = useState(false);
const [clearSignUp, setClearSignUp] = useState(false);
const [signInState, signInActionForm, isSignInPending] = useActionState(
async (prevState: SignUpState | undefined, formData: FormData) => signInAction(prevState || {}, formData),
async (prevState: SignUpState | undefined, formData: FormData) => {
if (clearSignIn) {
setClearSignIn(false);
return undefined;
}
return signInAction(prevState || {}, formData);
},
undefined
);
const [signUpState, signUpActionForm, isSignUpPending] = useActionState(
async (prevState: SignUpState | undefined, formData: FormData) => signUpAction(prevState || {}, formData),
async (prevState: SignUpState | undefined, formData: FormData) => {
if (clearSignUp) {
setClearSignUp(false);
return undefined;
}
return signUpAction(prevState || {}, formData);
},
undefined
);
@@ -64,21 +78,29 @@ export default function AuthForm({ redirectTo }: AuthFormProps) {
return Object.keys(newErrors).length === 0;
};
const handleFormSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
if (validateForm(formData)) {
// 基本客户端验证
if (!validateForm(formData)) {
return;
}
// 添加 redirectTo 到 formData
if (redirectTo) {
formData.append("redirectTo", redirectTo);
}
// 使用 startTransition 包装 action 调用
startTransition(() => {
// 根据模式调用相应的 action
if (mode === 'signin') {
await signInActionForm(formData);
signInActionForm(formData);
} else {
await signUpActionForm(formData);
}
signUpActionForm(formData);
}
});
};
const handleGitHubSignIn = async () => {
@@ -115,6 +137,9 @@ export default function AuthForm({ redirectTo }: AuthFormProps) {
{errors.name && (
<p className="text-red-500 text-sm mt-1">{errors.name}</p>
)}
{currentError?.errors?.username && (
<p className="text-red-500 text-sm mt-1">{currentError.errors.username[0]}</p>
)}
</div>
)}
@@ -128,6 +153,9 @@ export default function AuthForm({ redirectTo }: AuthFormProps) {
{errors.email && (
<p className="text-red-500 text-sm mt-1">{errors.email}</p>
)}
{currentError?.errors?.email && (
<p className="text-red-500 text-sm mt-1">{currentError.errors.email[0]}</p>
)}
</div>
<div>
@@ -140,6 +168,9 @@ export default function AuthForm({ redirectTo }: AuthFormProps) {
{errors.password && (
<p className="text-red-500 text-sm mt-1">{errors.password}</p>
)}
{currentError?.errors?.password && (
<p className="text-red-500 text-sm mt-1">{currentError.errors.password[0]}</p>
)}
</div>
{mode === 'signup' && (
@@ -194,6 +225,12 @@ export default function AuthForm({ redirectTo }: AuthFormProps) {
onClick={() => {
setMode(mode === 'signin' ? 'signup' : 'signin');
setErrors({});
// 清除服务器端错误状态
if (mode === 'signin') {
setClearSignIn(true);
} else {
setClearSignUp(true);
}
}}
className="text-[#35786f] hover:underline"
>

View File

@@ -26,6 +26,36 @@ export async function signUpAction(prevState: SignUpState, formData: FormData) {
const password = formData.get("password") as string;
const redirectTo = formData.get("redirectTo") as string;
// 服务器端验证
const errors: SignUpState['errors'] = {};
if (!email) {
errors.email = ["邮箱是必填项"];
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
errors.email = ["请输入有效的邮箱地址"];
}
if (!name) {
errors.username = ["姓名是必填项"];
} else if (name.length < 2) {
errors.username = ["姓名至少需要2个字符"];
}
if (!password) {
errors.password = ["密码是必填项"];
} else if (password.length < 8) {
errors.password = ["密码至少需要8个字符"];
}
// 如果有验证错误,返回错误状态
if (Object.keys(errors).length > 0) {
return {
success: false,
message: "请修正表单中的错误",
errors
};
}
try {
await auth.api.signUpEmail({
body: {
@@ -49,6 +79,28 @@ export async function signInAction(prevState: SignUpState, formData: FormData) {
const password = formData.get("password") as string;
const redirectTo = formData.get("redirectTo") as string;
// 服务器端验证
const errors: SignUpState['errors'] = {};
if (!email) {
errors.email = ["邮箱是必填项"];
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
errors.email = ["请输入有效的邮箱地址"];
}
if (!password) {
errors.password = ["密码是必填项"];
}
// 如果有验证错误,返回错误状态
if (Object.keys(errors).length > 0) {
return {
success: false,
message: "请修正表单中的错误",
errors
};
}
try {
await auth.api.signInEmail({
body: {