"use client"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; export default function LoginPage() { const router = useRouter(); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); useEffect(() => { // 已登录则跳转 const token = localStorage.getItem("wauth_token"); if (token) { fetch("/api/auth/login", { headers: { "X-Auth-User": token }, }).then(r => { if (r.ok) router.replace("/"); else localStorage.removeItem("wauth_token"); }).catch(() => localStorage.removeItem("wauth_token")); } }, [router]); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); try { const res = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username, password }), }); const data = await res.json(); if (!res.ok) { setError(data.error || "登录失败"); return; } // 存储用户信息 localStorage.setItem("wauth_token", data.user.username); localStorage.setItem("wauth_user", JSON.stringify(data.user)); // 注册 Service Worker if ("serviceWorker" in navigator) { const reg = await navigator.serviceWorker.register("/sw.js"); if (reg.installing) { await new Promise(resolve => { reg.installing!.addEventListener("statechange", function () { if (this.state === "activated") resolve(); }); }); } const sw = reg.active || reg.waiting || reg.installing; if (sw) { sw.postMessage({ type: "SET_TOKEN", token: data.user.username }); } if (navigator.serviceWorker.controller) { navigator.serviceWorker.controller.postMessage({ type: "SET_TOKEN", token: data.user.username }); } } router.replace("/"); } catch { setError("网络错误,请重试"); } finally { setLoading(false); } }; return (

写作后台

优世界 · Blog Admin

{error && (
{error}
)}
setUsername(e.target.value)} className="w-full px-3.5 py-2.5 rounded-lg border border-line bg-bg text-text text-sm outline-none focus:border-accent transition-colors" autoFocus required />
setPassword(e.target.value)} className="w-full px-3.5 py-2.5 rounded-lg border border-line bg-bg text-text text-sm outline-none focus:border-accent transition-colors" required />
); }