/** * Admin 后台 - 登录页(报刊风) * * 密码验证通过后由服务端写入 HttpOnly 会话 Cookie。 */ import { useState } from 'react' import { ApiError, login } from '../api/api' import { Button, Input } from '../components/ui' export default function Login({ onSuccess }: { onSuccess: () => void }) { const [password, setPassword] = useState('') const [submitting, setSubmitting] = useState(false) const [error, setError] = useState('') async function handleSubmit(e: React.FormEvent) { e.preventDefault() if (!password || submitting) return setSubmitting(true) setError('') try { await login(password) onSuccess() } catch (err) { setError( err instanceof ApiError ? err.message.split('\n')[0] : '登录失败,请检查网络连接', ) } finally { setSubmitting(false) } } return (

先知 Profeto

管理后台 · 管理员登录

setPassword(e.target.value)} placeholder="输入服务器 .env 中的 ADMIN_PASSWORD" autoFocus autoComplete="current-password" /* 错误时把输入框标记为无效并关联错误文本, 屏幕阅读器才能知道「密码错了」以及错在哪 */ aria-invalid={error ? true : undefined} aria-describedby={error ? 'admin-password-error' : undefined} className="mt-2 w-full" /> {error && ( )}

密码初始来自服务器 .env,可登录后在「系统配置」页修改;连续输错 5 次将锁定 10 分钟。

) }