From 2a58fbcbaeb19809f5df904cf5aec1588dc09035 Mon Sep 17 00:00:00 2001 From: Wang Zhuoxuan Date: Wed, 8 Apr 2026 15:46:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=99=BB=E5=BD=95=E9=A1=B5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20Token=20=E5=92=8C=E8=B4=A6=E5=8F=B7=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E4=B8=A4=E7=A7=8D=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 Tab 切换,同时支持 Token 登录和账号密码登录 - Token 登录兼容原有后端 API - 账号密码登录为 Phase 3d 的多管理员功能准备 Co-Authored-By: Claude Opus 4.6 --- src/routes/login.tsx | 178 ++++++++++++++++++++++++++++++------------- 1 file changed, 123 insertions(+), 55 deletions(-) diff --git a/src/routes/login.tsx b/src/routes/login.tsx index 3f976d6..fecf48e 100644 --- a/src/routes/login.tsx +++ b/src/routes/login.tsx @@ -4,40 +4,68 @@ import { useForm } from "react-hook-form" import { z } from "zod/v4" import { zodResolver } from "@hookform/resolvers/zod" import { Eye, EyeOff } from "lucide-react" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { apiClient } from "@/lib/api-client" import { loginAdmin } from "@/lib/api/admin-api" import { useAuth } from "@/hooks/use-auth" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" +import type { LoginResponse } from "@/types/api" import type { AdminSession } from "@/types/admin" -const loginSchema = z.object({ +// Token 登录表单 +const tokenLoginSchema = z.object({ + token: z.string().min(1, "请输入 Admin Token"), +}) + +type TokenLoginForm = z.infer + +// 用户名密码登录表单 +const passwordLoginSchema = z.object({ username: z.string().min(1, "请输入用户名"), password: z.string().min(1, "请输入密码"), }) -type LoginForm = z.infer +type PasswordLoginForm = z.infer export default function LoginPage() { const navigate = useNavigate() const { login } = useAuth() const [error, setError] = useState("") const [showPassword, setShowPassword] = useState(false) + const [loginType, setLoginType] = useState<"token" | "password">("token") - const { - register, - handleSubmit, - formState: { errors, isSubmitting }, - } = useForm({ - resolver: zodResolver(loginSchema), - defaultValues: { - username: "", - password: "", - }, + // Token 登录表单 + const tokenForm = useForm({ + resolver: zodResolver(tokenLoginSchema), + defaultValues: { token: "" }, }) - async function onSubmit(data: LoginForm) { + // 密码登录表单 + const passwordForm = useForm({ + resolver: zodResolver(passwordLoginSchema), + defaultValues: { username: "", password: "" }, + }) + + // Token 登录 + async function handleTokenLogin(data: TokenLoginForm) { + setError("") + try { + const response = await apiClient + .post("auth/login", { json: { token: data.token } }) + .json() + + login(response.jwt, response.admin) + navigate("/") + } catch { + setError("Token 登录失败,请检查是否正确") + } + } + + // 密码登录 + async function handlePasswordLogin(data: PasswordLoginForm) { setError("") try { const response = await loginAdmin(data) @@ -62,56 +90,96 @@ export default function LoginPage() { 多奇管理后台 - 使用管理员账号登录 + 选择登录方式 -
-
- - - {errors.username && ( -

{errors.username.message}

- )} -
+ { setLoginType(val as "token" | "password"); setError("") }}> + + Token 登录 + 账号登录 + + + {/* Token 登录 */} + + +
+ + + {tokenForm.formState.errors.token && ( +

{tokenForm.formState.errors.token.message}

+ )} +
-
- -
- -
- {errors.password && ( -

{errors.password.message}

- )} -
+ +
- {error && ( -

{error}

- )} + {/* 密码登录 */} + +
+
+ + + {passwordForm.formState.errors.username && ( +

{passwordForm.formState.errors.username.message}

+ )} +
- -
+
+ +
+ + +
+ {passwordForm.formState.errors.password && ( +

{passwordForm.formState.errors.password.message}

+ )} +
+ + + +
+
+ + {error && ( +

{error}

+ )}