'use client'; /** * 登录 / 注册页。 * * 支持两种模式切换:登录与注册。注册时可选择角色(学生/导师/管理员),便于演示三端。 * 成功后依据角色跳转到对应工作台。错误信息取自后端统一错误体。 */ import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; import { homeForRole } from '@/components/app-shell'; import { ErrorBanner } from '@/components/ui'; import { ApiError } from '@/lib/api'; import { useAuth } from '@/lib/auth-context'; import { ROLE_LABELS, Role } from '@/lib/types'; /** 内置测试账户(与后端 SEED_TEST_ACCOUNTS 一致),用于一键登录。 */ const TEST_ACCOUNTS: { username: string; password: string; role: Role; }[] = [ { username: 'student', password: 'student123', role: Role.Student }, { username: 'mentor', password: 'mentor123', role: Role.Mentor }, { username: 'admin', password: 'admin123', role: Role.Administrator }, ]; export default function LoginPage() { const { user, loading, login, register } = useAuth(); const router = useRouter(); const [mode, setMode] = useState<'login' | 'register'>('login'); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [displayName, setDisplayName] = useState(''); const [role, setRole] = useState(Role.Student); const [error, setError] = useState(null); const [submitting, setSubmitting] = useState(false); const [quickRole, setQuickRole] = useState(null); // 已登录则直接跳转。 useEffect(() => { if (!loading && user) { router.replace(homeForRole(user.role)); } }, [loading, user, router]); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setError(null); setSubmitting(true); try { const u = mode === 'login' ? await login(username, password) : await register({ username, password, role, displayName }); router.replace(homeForRole(u.role)); } catch (err) { if (err instanceof ApiError) { setError(err.body.message ?? '操作失败'); } else { setError('网络错误,请确认后端服务已启动'); } } finally { setSubmitting(false); } } /** 一键登录某测试账户。 */ async function quickLogin(acct: (typeof TEST_ACCOUNTS)[number]) { setError(null); setQuickRole(acct.role); try { const u = await login(acct.username, acct.password); router.replace(homeForRole(u.role)); } catch (err) { if (err instanceof ApiError) { setError( `${ROLE_LABELS[acct.role]}测试账户登录失败:${err.body.message ?? ''}`, ); } else { setError('网络错误,请确认后端服务已启动'); } setQuickRole(null); } } return (

医科高校 AI 学习中心

学习 · 对练 · 画像 · 科研 · 协同

{(['login', 'register'] as const).map((m) => ( ))}
setUsername(e.target.value)} placeholder="至少 3 个字符" autoComplete="username" required />
setPassword(e.target.value)} placeholder="至少 8 个字符" autoComplete={ mode === 'login' ? 'current-password' : 'new-password' } required />
{mode === 'register' && ( <>
setDisplayName(e.target.value)} placeholder="如:张三" required />
{Object.values(Role).map((r) => ( ))}
)} {error && }

测试账户 · 一键登录

{TEST_ACCOUNTS.map((acct) => ( ))}

口令:student123 / mentor123 / admin123

后端服务默认运行于 http://localhost:3000

); }