62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { redirect } from "next/navigation";
|
|
|
|
import { getAdminSession, getUserSession } from "@/lib/session";
|
|
|
|
import { loginAction } from "./actions";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "鹅梯 FeieProxy",
|
|
};
|
|
|
|
export default async function LoginPage({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<{ error?: string }>;
|
|
}) {
|
|
const [adminSession, userSession] = await Promise.all([
|
|
getAdminSession(),
|
|
getUserSession(),
|
|
]);
|
|
if (adminSession) {
|
|
redirect("/admin/dashboard");
|
|
}
|
|
if (userSession) {
|
|
redirect("/me");
|
|
}
|
|
|
|
const params = await searchParams;
|
|
|
|
return (
|
|
<main className="login-shell login-shell--immersive">
|
|
<section className="login-stage">
|
|
<article className="login-card login-card--form login-card--brand">
|
|
<div className="section-title">
|
|
<div>
|
|
<span className="eyebrow">安全登录</span>
|
|
<h1>鹅梯 FeieProxy</h1>
|
|
</div>
|
|
<span className="status-pill status-pill--neutral">家宽节点</span>
|
|
</div>
|
|
<form action={loginAction} className="stack-lg login-form">
|
|
<label className="field">
|
|
<span>用户名</span>
|
|
<input name="username" type="text" placeholder="admin" required />
|
|
</label>
|
|
<label className="field">
|
|
<span>密码</span>
|
|
<input name="password" type="password" required />
|
|
</label>
|
|
{params.error ? (
|
|
<p className="error-banner">用户名或密码错误。</p>
|
|
) : null}
|
|
<button className="primary-button" type="submit">
|
|
登录
|
|
</button>
|
|
</form>
|
|
</article>
|
|
</section>
|
|
</main>
|
|
);
|
|
}
|