'use client' import { useCallback, useEffect, useMemo, useState } from 'react' import type { FormEvent } from 'react' type CaptchaResponse = { expiresAt: number prompt: string token: string } function getSafeRedirect() { if (typeof window === 'undefined') return '/admin' const redirectTo = new URLSearchParams(window.location.search).get('redirect') if (!redirectTo || !redirectTo.startsWith('/') || redirectTo.startsWith('//')) return '/admin' return redirectTo } async function readErrorMessage(response: Response) { try { const data = await response.json() if (typeof data?.message === 'string') return data.message if (Array.isArray(data?.errors) && typeof data.errors[0]?.message === 'string') { return data.errors[0].message } } catch { return null } return null } export function AdminLoginForm() { const [captcha, setCaptcha] = useState(null) const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [captchaAnswer, setCaptchaAnswer] = useState('') const [error, setError] = useState('') const [loadingCaptcha, setLoadingCaptcha] = useState(true) const [submitting, setSubmitting] = useState(false) const redirectTo = useMemo(getSafeRedirect, []) const refreshCaptcha = useCallback(async () => { setLoadingCaptcha(true) setCaptchaAnswer('') try { const response = await fetch('/api/admin/captcha', { cache: 'no-store', credentials: 'same-origin', }) if (!response.ok) throw new Error('Failed to load captcha') setCaptcha(await response.json()) } catch { setError('验证码加载失败,请刷新页面后重试。') } finally { setLoadingCaptcha(false) } }, []) useEffect(() => { refreshCaptcha() }, [refreshCaptcha]) useEffect(() => { fetch('/api/users/me', { cache: 'no-store', credentials: 'same-origin', }) .then(async (response) => { if (!response.ok) return const data = await response.json() if (data?.user) window.location.assign(redirectTo) }) .catch(() => undefined) }, [redirectTo]) async function handleSubmit(event: FormEvent) { event.preventDefault() if (!captcha) { setError('验证码还没有加载完成。') return } setError('') setSubmitting(true) const response = await fetch('/api/users/login', { body: JSON.stringify({ captchaAnswer, captchaToken: captcha.token, email, password, }), credentials: 'same-origin', headers: { 'Content-Type': 'application/json', }, method: 'POST', }) if (response.ok) { window.location.assign(redirectTo) return } const message = await readErrorMessage(response) setError(message || '登录失败,请检查账号、密码和验证码。') setSubmitting(false) refreshCaptcha() } return (
{error ? (

{error}

) : null}
) }