import { useState } from "react"; import { useNavigate } from "react-router-dom"; import toast from "react-hot-toast"; import { Turnstile } from "@marsidev/react-turnstile"; import { motion } from "framer-motion"; import { Card, CardBody, CardHeader } from "@/shadcn-bridge/heroui/card"; import { Input } from "@/shadcn-bridge/heroui/input"; import { Button } from "@/shadcn-bridge/heroui/button"; import { siteConfig } from "@/config/site"; import { VersionFooter } from "@/components/version-footer"; import { BrandLogo } from "@/components/brand-logo"; import { login, LoginData, checkCaptcha, getPublicConfigByName } from "@/api"; import { writeLoginSession } from "@/utils/session"; import { useWebViewMode } from "@/hooks/useWebViewMode"; interface LoginForm { username: string; password: string; captchaId: string; } export default function IndexPage() { const [form, setForm] = useState({ username: "", password: "", captchaId: "", }); const [loading, setLoading] = useState(false); const [errors, setErrors] = useState>({}); const [showCaptcha, setShowCaptcha] = useState(false); const [siteKey, setSiteKey] = useState(""); const navigate = useNavigate(); const isWebView = useWebViewMode(); // 验证表单 const validateForm = (): boolean => { const newErrors: Partial = {}; if (!form.username.trim()) { newErrors.username = "请输入用户名"; } if (!form.password.trim()) { newErrors.password = "请输入密码"; } else if (form.password.length < 6) { newErrors.password = "密码长度至少6位"; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; // 处理输入变化 const handleInputChange = (field: keyof LoginForm, value: string) => { setForm((prev) => ({ ...prev, [field]: value })); // 清除该字段的错误 if (errors[field]) { setErrors((prev) => ({ ...prev, [field]: undefined })); } }; // 执行登录请求 const performLogin = async (captchaToken?: string) => { try { const finalCaptchaId = typeof captchaToken === "string" && captchaToken.trim() ? captchaToken : form.captchaId; const loginData: LoginData = { username: form.username.trim(), password: form.password, captchaId: finalCaptchaId, }; const response = await login(loginData); if (response.code !== 0) { toast.error(response.msg || "登录失败"); if (showCaptcha) { setForm((prev) => ({ ...prev, captchaId: "" })); } return; } // 检查是否需要强制修改密码 if (response.data.requirePasswordChange) { writeLoginSession(response.data); toast.success("检测到默认密码,即将跳转到修改密码页面"); navigate("/change-password"); return; } // 保存登录信息 writeLoginSession(response.data); // 登录成功 toast.success("登录成功"); navigate("/dashboard"); } catch { toast.error("网络错误,请稍后重试"); } finally { setLoading(false); } }; const handleLogin = async () => { if (!validateForm()) return; setLoading(true); try { // 先检查是否需要验证码 const checkResponse = await checkCaptcha(); if (checkResponse.code !== 0) { toast.error("检查验证码状态失败,请重试" + checkResponse.msg); setLoading(false); return; } // 根据返回值决定是否显示验证码 if (checkResponse.data === 0) { await performLogin(); } else { const configResp = await getPublicConfigByName("cloudflare_site_key"); if (configResp.code === 0 && configResp.data && configResp.data.value) { setSiteKey(configResp.data.value); setShowCaptcha(true); } else { toast.error("未配置Cloudflare Site Key,请联系管理员"); setLoading(false); } } } catch (error) { toast.error("网络错误,请稍后重试" + error); setLoading(false); } }; const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !loading) { handleLogin(); } }; return (

{siteConfig.name}

Sign in to manage your networks

handleInputChange("username", e.target.value) } onKeyDown={handleKeyPress} /> handleInputChange("password", e.target.value) } onKeyDown={handleKeyPress} />
{/* 版权信息 - 固定在底部,不占据布局空间 */} {/* 验证码弹层 */} {showCaptcha && siteKey && (
{/* 背景遮罩层 - 模糊效果,暗黑模式下更深 */}
)}
); }