"use client" import type { CSSProperties, FormEvent } from "react" import { useEffect, useMemo, useState } from "react" import { AlertCircle, ArrowRight, CheckCircle2, Eye, EyeOff, LockKeyhole, ShieldCheck, Sparkles, UserRound, } from "lucide-react" type LoginStatus = "idle" | "loading" | "success" type LoginMood = "idle" | "typing" | "peek" | "error" | "success" const CHARACTER_IDS = ["pilot", "lens", "spark", "keeper"] as const export default function LoginPage() { const [username, setUsername] = useState("") const [password, setPassword] = useState("") const [remember, setRemember] = useState(true) const [showPassword, setShowPassword] = useState(false) const [activeField, setActiveField] = useState<"username" | "password" | null>(null) const [error, setError] = useState("") const [status, setStatus] = useState("idle") const [eyeOffset, setEyeOffset] = useState({ x: 0, y: 0 }) useEffect(() => { const onPointerMove = (event: PointerEvent) => { const centerX = window.innerWidth / 2 const centerY = window.innerHeight / 2 const nextX = Math.max(-1, Math.min(1, (event.clientX - centerX) / centerX)) const nextY = Math.max(-1, Math.min(1, (event.clientY - centerY) / centerY)) setEyeOffset({ x: nextX * 5, y: nextY * 3 }) } window.addEventListener("pointermove", onPointerMove) return () => window.removeEventListener("pointermove", onPointerMove) }, []) const mood: LoginMood = useMemo(() => { if (status === "success") return "success" if (error) return "error" if (showPassword && activeField === "password") return "peek" if (activeField || username || password) return "typing" return "idle" }, [activeField, error, password, showPassword, status, username]) const disabled = status === "loading" || status === "success" async function onSubmit(event: FormEvent) { event.preventDefault() setError("") if (!username.trim() || !password) { setError("请输入账号和密码") return } setStatus("loading") try { const res = await fetch("/api/auth/login", { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username, password, remember }), }) if (!res.ok) { let message = "账号或密码不正确" try { const data = await res.json() message = data?.detail || data?.error || message } catch { // keep default message } throw new Error(message) } setStatus("success") window.setTimeout(() => { window.location.href = "/" }, 420) } catch (err) { setStatus("idle") setError(err instanceof Error ? err.message : "登录失败,请稍后再试") } } return (

SKG Marketing Studio

营销内容工作台

生产入口已保护

登录

进入 SKG 营销内容工作台

marketing.skg.com
{error ? (
{error}
) : status === "success" ? (
登录成功,正在进入工作台
) : null}
) }