'use client'; import { useState, useEffect } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { motion, AnimatePresence } from 'framer-motion'; import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from '@heroicons/react/24/outline'; import { useAuth } from '@/contexts/AuthContext'; import { errorManager } from '@/components/ErrorNotification'; export default function AuthPage() { const [isLoginMode, setIsLoginMode] = useState(true); const [formData, setFormData] = useState({ username: '', email: '', password: '', confirmPassword: '', verificationCode: '', rememberMe: false, agreeToTerms: false }); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); const [errors, setErrors] = useState>({}); const [isLoading, setIsLoading] = useState(false); const [authError, setAuthError] = useState(''); const [isSendingCode, setIsSendingCode] = useState(false); const [codeTimer, setCodeTimer] = useState(0); const { login, register } = useAuth(); const router = useRouter(); useEffect(() => { let interval: NodeJS.Timeout; if (codeTimer > 0) { interval = setInterval(() => { setCodeTimer(prev => prev - 1); }, 1000); } return () => clearInterval(interval); }, [codeTimer]); const handleInputChange = (e: React.ChangeEvent) => { const { name, value, type, checked } = e.target; setFormData(prev => ({ ...prev, [name]: type === 'checkbox' ? checked : value })); if (errors[name]) { setErrors(prev => ({ ...prev, [name]: '' })); } if (authError) { setAuthError(''); } }; const validateLoginForm = () => { const newErrors: Record = {}; if (!formData.username.trim()) { newErrors.username = '请输入用户名或邮箱'; } if (!formData.password) { newErrors.password = '请输入密码'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const validateRegisterForm = () => { const newErrors: Record = {}; if (!formData.username.trim()) { newErrors.username = '用户名不能为空'; } else if (formData.username.length < 3) { newErrors.username = '用户名至少需要3个字符'; } else if (formData.username.length > 50) { newErrors.username = '用户名不能超过50个字符'; } if (!formData.email.trim()) { newErrors.email = '邮箱不能为空'; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { newErrors.email = '请输入有效的邮箱地址'; } if (!formData.password) { newErrors.password = '密码不能为空'; } else if (formData.password.length < 6) { newErrors.password = '密码至少需要6个字符'; } else if (formData.password.length > 128) { newErrors.password = '密码不能超过128个字符'; } if (formData.password !== formData.confirmPassword) { newErrors.confirmPassword = '两次输入的密码不一致'; } if (!formData.verificationCode) { newErrors.verificationCode = '请输入验证码'; } else if (!/^\d{6}$/.test(formData.verificationCode)) { newErrors.verificationCode = '验证码应为6位数字'; } if (!formData.agreeToTerms) { newErrors.agreeToTerms = '请同意服务条款'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const getPasswordStrength = () => { const password = formData.password; if (password.length === 0) return { strength: 0, label: '', color: 'bg-gray-200' }; if (password.length < 6) return { strength: 1, label: '弱', color: 'bg-red-500' }; if (password.length < 10) return { strength: 2, label: '中等', color: 'bg-yellow-500' }; if (password.length >= 15) return { strength: 4, label: '很强', color: 'bg-green-500' }; return { strength: 3, label: '强', color: 'bg-blue-500' }; }; const passwordStrength = getPasswordStrength(); const handleSendCode = async () => { if (!formData.email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { setErrors(prev => ({ ...prev, email: '请输入有效的邮箱地址' })); return; } setIsSendingCode(true); try { const response = await fetch('/api/v1/auth/send-code', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email: formData.email, type: 'register' }), }); const data = await response.json(); if (data.code === 200) { setCodeTimer(60); errorManager.showSuccess('验证码已发送到您的邮箱'); } else { setErrors(prev => ({ ...prev, email: data.message || '发送验证码失败' })); errorManager.showError(data.message || '发送验证码失败'); } } catch (error) { setErrors(prev => ({ ...prev, email: '发送验证码失败,请稍后重试' })); errorManager.showError('发送验证码失败,请稍后重试'); } finally { setIsSendingCode(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (isLoginMode) { if (!validateLoginForm()) return; setIsLoading(true); setAuthError(''); try { await login(formData.username, formData.password); if (formData.rememberMe) { localStorage.setItem('rememberMe', 'true'); } else { localStorage.removeItem('rememberMe'); } errorManager.showSuccess('登录成功!'); router.push('/'); } catch (error) { const errorMessage = error instanceof Error ? error.message : '登录失败,请检查用户名和密码'; setAuthError(errorMessage); errorManager.showError(errorMessage); } finally { setIsLoading(false); } } else { if (!validateRegisterForm()) return; setIsLoading(true); setAuthError(''); try { await register(formData.username, formData.email, formData.password, formData.verificationCode); errorManager.showSuccess('注册成功!欢迎加入CarrotSkin!'); router.push('/'); } catch (error) { const errorMessage = error instanceof Error ? error.message : '注册失败,请稍后重试'; setAuthError(errorMessage); errorManager.showError(errorMessage); } finally { setIsLoading(false); } } }; const switchMode = () => { setIsLoginMode(!isLoginMode); setAuthError(''); setErrors({}); setFormData({ username: '', email: '', password: '', confirmPassword: '', verificationCode: '', rememberMe: false, agreeToTerms: false }); }; return (
{/* Left Side - Orange Section */}
CS {isLoginMode ? '欢迎回来' : '加入我们'} {isLoginMode ? '继续你的创作之旅' : '开始你的创作之旅'}
创建独特的皮肤设计
与社区分享作品
发现精彩创意

已有超过 10,000 位创作者加入我们

{/* Right Side - White Section */}
{/* Back to Home Button */} 返回主页 {/* Header */}

{isLoginMode ? '登录账户' : '创建账户'}

{isLoginMode ? '登录您的CarrotSkin账户' : '加入我们,开始创作'}

{authError && (

{authError}

)}
{/* Username */}
{!isLoginMode && formData.username && !errors.username && ( )} {errors.username && ( )}
{errors.username && (

{errors.username}

)}
{/* Email - Only for registration */} {!isLoginMode && (
{formData.email && !errors.email && ( )} {errors.email && ( )}
{errors.email && (

{errors.email}

)}
)}
{/* Password */}
{!isLoginMode && formData.password && (
密码强度 {passwordStrength.label}
)} {errors.password && (

{errors.password}

)} {/* Confirm Password - Only for registration */} {!isLoginMode && (
{formData.confirmPassword && formData.password === formData.confirmPassword && !errors.confirmPassword && ( )} {errors.confirmPassword && (

{errors.confirmPassword}

)}
)}
{/* Verification Code - Only for registration */} {!isLoginMode && (
{errors.verificationCode && (

{errors.verificationCode}

)}
)}
{/* Remember Me - Only for login */} {isLoginMode && ( 忘记密码? )} {/* Terms Agreement - Only for registration */} {!isLoginMode && ( {errors.agreeToTerms && (

{errors.agreeToTerms}

)}
)}
{/* Submit Button */} {isLoading ? (
{isLoginMode ? '登录中...' : '注册中...'}
) : ( isLoginMode ? '登录' : '创建账户' )} {/* Social Login */}
或者
GitHub Microsoft
{/* Mode Switch */}

{isLoginMode ? '还没有账户?' : '已有账户?'}

); }