Files
Mutual_Fund/frontend/app/login/page.tsx
T
2026-09-14 11:54:20 +08:00

28 lines
3.4 KiB
TypeScript

"use client";
import Link from "next/link";
import { ArrowLeft, ArrowRight, LockKeyhole } from "lucide-react";
import { FormEvent, useState } from "react";
import { apiFetch } from "@/lib/api";
import { getPostLoginPath, setToken } from "@/lib/auth";
interface LoginResult { token: string; user: { user_type: string; employee_role?: string | null } }
export default function LoginPage() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [message, setMessage] = useState("");
const [loading, setLoading] = useState(false);
async function handleSubmit(event: FormEvent) {
event.preventDefault(); setMessage(""); setLoading(true);
try {
const result = await apiFetch<LoginResult>("/auth/login", { method: "POST", body: JSON.stringify({ username, password }) });
setToken(result.token);
window.location.href = getPostLoginPath(result.user);
} catch (error) { setMessage(error instanceof Error ? error.message : "登录失败,请稍后重试"); } finally { setLoading(false); }
}
return <main className="flex min-h-screen items-center justify-center bg-[var(--brand-navy)] p-8"><div className="grid w-full max-w-5xl overflow-hidden rounded-2xl bg-white shadow-2xl lg:grid-cols-[.9fr_1.1fr]"><div className="hidden bg-[linear-gradient(145deg,#071a49,#263a8a)] p-10 text-white lg:block"><Link href="/" className="inline-flex items-center gap-2 text-sm text-blue-100 hover:text-white"><ArrowLeft className="h-4 w-4" />返回首页</Link><div className="mt-36"><p className="text-sm uppercase tracking-[0.24em] text-blue-200">Huaxia Fund</p><h1 className="mt-5 text-4xl font-semibold leading-tight">专业研究,<br />陪伴长期价值。</h1><p className="mt-5 max-w-sm text-sm leading-7 text-blue-100">登录后查看您的账户、持仓和专属服务。</p></div></div><div className="p-8 sm:p-12"><div className="flex h-10 w-10 items-center justify-center rounded-xl bg-indigo-50 text-[var(--brand-primary)]"><LockKeyhole className="h-5 w-5" /></div><h2 className="mt-7 text-2xl font-semibold text-[var(--brand-navy)]">欢迎回来</h2><p className="mt-2 text-sm text-slate-500">登录华夏基金账户</p><form onSubmit={handleSubmit} className="mt-8 space-y-5"><label className="block text-sm font-medium text-slate-700">用户名<input value={username} onChange={(event) => setUsername(event.target.value)} required className="mt-2 w-full rounded-lg border border-slate-200 px-3 py-3 outline-none focus:border-[var(--brand-primary)]" /></label><label className="block text-sm font-medium text-slate-700">密码<input type="password" value={password} onChange={(event) => setPassword(event.target.value)} required className="mt-2 w-full rounded-lg border border-slate-200 px-3 py-3 outline-none focus:border-[var(--brand-primary)]" /></label>{message && <p className="rounded-lg bg-rose-50 px-3 py-2 text-sm text-rose-600">{message}</p>}<button disabled={loading} className="flex w-full items-center justify-center gap-2 rounded-lg bg-[var(--brand-primary)] px-4 py-3.5 text-sm font-semibold text-white hover:bg-[var(--brand-primary-dark)] disabled:opacity-50">{loading ? "登录中..." : "登录"}<ArrowRight className="h-4 w-4" /></button></form><p className="mt-7 text-center text-sm text-slate-500">还没有账号? <Link href="/register" className="font-semibold text-[var(--brand-primary)]">立即注册</Link></p></div></div></main>;
}