import { useMemo, useState } from "react"; import type { FormEvent } from "react"; import { Button } from "@/components/ui/button"; import { loginWithEmailCode, sendEmailCode, type EmailLoginResult } from "@/services/auth-api"; type EmailLoginPageProps = { onLoginSuccess: (payload: EmailLoginResult) => void; }; export function EmailLoginPage({ onLoginSuccess }: EmailLoginPageProps) { const [email, setEmail] = useState(""); const [code, setCode] = useState(""); const [sendingCode, setSendingCode] = useState(false); const [loggingIn, setLoggingIn] = useState(false); const [codeCooldown, setCodeCooldown] = useState(0); const [message, setMessage] = useState(null); const [error, setError] = useState(null); const canSendCode = useMemo(() => { return email.trim().length > 0 && !sendingCode && codeCooldown <= 0; }, [codeCooldown, email, sendingCode]); const canLogin = useMemo(() => { return email.trim().length > 0 && code.trim().length === 6 && !loggingIn; }, [code, email, loggingIn]); async function handleSendCode(event: FormEvent): Promise { event.preventDefault(); if (!canSendCode) { return; } try { setSendingCode(true); setError(null); setMessage(null); const result = await sendEmailCode(email.trim()); setMessage(`验证码已发送,有效期 ${result.expiresInSeconds} 秒`); let remain = 60; setCodeCooldown(remain); const timer = window.setInterval(() => { remain -= 1; setCodeCooldown(remain); if (remain <= 0) { window.clearInterval(timer); } }, 1000); } catch (err) { setError(err instanceof Error ? err.message : "发送验证码失败"); } finally { setSendingCode(false); } } async function handleLogin(event: FormEvent): Promise { event.preventDefault(); if (!canLogin) { return; } try { setLoggingIn(true); setError(null); setMessage(null); const result = await loginWithEmailCode(email.trim(), code.trim()); onLoginSuccess(result); } catch (err) { setError(err instanceof Error ? err.message : "登录失败"); } finally { setLoggingIn(false); } } return (

邮箱验证码登录

输入邮箱后获取验证码,再完成登录。

setEmail(event.target.value)} />
setCode(event.target.value)} />
{message ?

{message}

: null} {error ?

{error}

: null}
); }