import { useState, useEffect, useMemo } from 'react'; import { useNavigate, useSearchParams, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useForm } from 'react-hook-form'; import userService from '../services/user_service'; import { rsaPsw } from '../utils/encryption'; /** * OAuth回调处理Hook */ export const useOAuthCallback = () => { const [searchParams, setSearchParams] = useSearchParams(); const navigate = useNavigate(); const error = searchParams.get('error'); const newSearchParams: URLSearchParams = useMemo( () => new URLSearchParams(searchParams.toString()), [searchParams], ); useEffect(() => { if (error) { // 显示错误信息(这里可以集成你的消息提示组件) console.error('OAuth Error:', error); setTimeout(() => { navigate('/login'); newSearchParams.delete('error'); setSearchParams(newSearchParams); }, 1000); return; } const auth = searchParams.get('auth'); if (auth) { // 存储认证信息 localStorage.setItem('token', auth); newSearchParams.delete('auth'); setSearchParams(newSearchParams); navigate('/'); } }, [ error, searchParams, newSearchParams, navigate, setSearchParams, ]); return searchParams.get('auth'); }; /** * 认证状态管理Hook */ export const useAuth = () => { const navigate = useNavigate(); const location = useLocation(); const [searchParams] = useSearchParams(); const [isAuthenticated, setIsAuthenticated] = useState(null); const [userInfo, setUserInfo] = useState(null); const [token, setToken] = useState(null); const [isLoading, setIsLoading] = useState(true); // OAuth回调处理 const auth = useOAuthCallback(); // 检查认证状态 const checkAuthStatus = () => { try { const storedToken = localStorage.getItem('token'); const storedUserInfo = localStorage.getItem('userInfo'); if (storedToken) { setToken(storedToken); setIsAuthenticated(true); if (storedUserInfo) { setUserInfo(JSON.parse(storedUserInfo)); } } else { setToken(null); setIsAuthenticated(false); setUserInfo(null); } } catch (error) { console.error('Error checking auth status:', error); setToken(null); setIsAuthenticated(false); setUserInfo(null); } finally { setIsLoading(false); } }; // 登出功能 const logout = () => { localStorage.removeItem('token'); localStorage.removeItem('userInfo'); setToken(null); setIsAuthenticated(false); setUserInfo(null); navigate('/login'); }; // 更新认证状态 const updateAuthStatus = (newToken: string, newUserInfo: any) => { setToken(newToken); setUserInfo(newUserInfo); setIsAuthenticated(true); localStorage.setItem('token', newToken); localStorage.setItem('userInfo', JSON.stringify(newUserInfo)); }; // 带参数重定向到登录页面 const redirectToLogin = (returnUrl?: string) => { const currentPath = returnUrl || location.pathname + location.search; if (currentPath !== '/login') { navigate(`/login?redirect=${encodeURIComponent(currentPath)}`); } else { navigate('/login'); } }; // 重定向到指定页面或首页 const redirectAfterLogin = () => { const redirectUrl = searchParams.get('redirect'); if (redirectUrl) { navigate(decodeURIComponent(redirectUrl)); } else { navigate('/'); } }; useEffect(() => { checkAuthStatus(); }, [auth]); return { isAuthenticated, userInfo, token, isLoading, checkAuthStatus, logout, updateAuthStatus, redirectToLogin, redirectAfterLogin, }; }; export interface LoginFormData { email: string; password: string; rememberEmail?: boolean; } export interface RegisterFormData { email: string; password: string; nickname: string; } /** * 登录Hook */ export const useLogin = () => { const { t } = useTranslation(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const [isLoading, setIsLoading] = useState(false); const login = async (data: LoginFormData) => { setIsLoading(true); try { // RSA加密密码 const encryptedPassword = rsaPsw(data.password); const response = await userService.login({ email: data.email.trim(), password: encryptedPassword }); const { data: res = {} } = response; const { code, message } = res; if (code === 0) { // 登录成功,处理token和用户信息 const { data: userData } = res; const token = userData.access_token; const userInfo = { ...userData, avatar: userData.avatar, name: userData.nickname, email: userData.email, }; // 同步更新localStorage localStorage.setItem('token', token); localStorage.setItem('userInfo', JSON.stringify(userInfo)); // 直接进行重定向,不依赖React状态更新 const redirectUrl = searchParams.get('redirect'); if (redirectUrl) { navigate(decodeURIComponent(redirectUrl), { replace: true }); } else { navigate('/', { replace: true }); } return { success: true }; } else { // 登录失败 return { success: false, error: message || t('login.loginFailed') }; } } catch (error: any) { // 处理网络错误或其他异常 return { success: false, error: error.message || t('login.networkError') }; } finally { setIsLoading(false); } }; return { login, isLoading }; }; /** * 注册Hook */ export const useRegister = () => { const { t } = useTranslation(); const [isLoading, setIsLoading] = useState(false); const register = async (data: RegisterFormData) => { setIsLoading(true); try { // RSA加密密码 const encryptedPassword = rsaPsw(data.password); const response = await userService.register({ nickname: data.nickname, email: data.email.trim(), password: encryptedPassword }); const { data: res = {} } = response; const { code, message } = res; if (code === 0) { // 注册成功 return { success: true, email: data.email }; } else { // 注册失败 return { success: false, error: message || t('login.registerFailed') }; } } catch (error: any) { // 处理网络错误或其他异常 return { success: false, error: error.message || t('login.networkError') }; } finally { setIsLoading(false); } }; return { register, isLoading }; }; /** * 登录表单管理Hook */ export const useLoginForm = () => { const { t } = useTranslation(); const [tabValue, setTabValue] = useState(0); // 0: 登录, 1: 注册 const [error, setError] = useState(''); // 登录表单 const loginForm = useForm({ defaultValues: { email: '', password: '', rememberEmail: false } }); // 注册表单 const registerForm = useForm({ defaultValues: { email: '', password: '', nickname: '' } }); const handleTabChange = (event: React.SyntheticEvent, newValue: number) => { setTabValue(newValue); setError(''); // 清空表单错误 loginForm.clearErrors(); registerForm.clearErrors(); }; const switchToLogin = (email?: string) => { setTabValue(0); setError(''); if (email) { loginForm.setValue('email', email); } }; const setFormError = (errorMessage: string) => { setError(errorMessage); }; const clearError = () => { setError(''); }; return { // 表单状态 tabValue, setTabValue, error, loginForm, registerForm, // 表单操作 handleTabChange, switchToLogin, setFormError, clearError, // 表单验证规则 loginValidation: { email: { required: t('login.emailPlaceholder'), pattern: { value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message: t('login.emailInvalid') } }, password: { required: t('login.passwordPlaceholder'), minLength: { value: 6, message: t('login.passwordMinLength') } } }, registerValidation: { nickname: { required: t('login.nicknamePlaceholder'), minLength: { value: 2, message: t('login.nicknameMinLength') } }, email: { required: t('login.emailPlaceholder'), pattern: { value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message: t('login.emailInvalid') } }, password: { required: t('login.passwordPlaceholder'), minLength: { value: 8, message: t('login.passwordMinLength') } } } }; }; /** * 登录页面主Hook - 整合所有登录相关逻辑 */ export const useLoginPage = () => { const loginHook = useLogin(); const registerHook = useRegister(); const formHook = useLoginForm(); const handleLogin = async (data: LoginFormData) => { formHook.clearError(); const result = await loginHook.login(data); if (!result.success && result.error) { formHook.setFormError(result.error); } return result; }; const handleRegister = async (data: RegisterFormData) => { formHook.clearError(); const result = await registerHook.register(data); if (result.success) { // 注册成功,切换到登录表单并填入邮箱 formHook.registerForm.reset(); formHook.switchToLogin(result.email); } else if (result.error) { formHook.setFormError(result.error); } return result; }; const isSubmitting = loginHook.isLoading || registerHook.isLoading; return { // 表单相关 ...formHook, // 提交处理 handleLogin, handleRegister, isSubmitting, }; };