// ============================================================ // 登录页面 // ============================================================ import { useState } from 'react' import { useNavigate, useSearchParams } from 'react-router-dom' import { LoginForm, ProFormText } from '@ant-design/pro-components' import { LockOutlined, UserOutlined, SafetyOutlined } from '@ant-design/icons' import { message } from 'antd' import { authService } from '@/services/auth' import { useAuthStore } from '@/stores/authStore' import type { LoginRequest } from '@/types' export default function Login() { const navigate = useNavigate() const [searchParams] = useSearchParams() const loginStore = useAuthStore((s) => s.login) const [needTotp, setNeedTotp] = useState(false) const [loading, setLoading] = useState(false) const handleSubmit = async (values: Record) => { setLoading(true) try { const data: LoginRequest = { username: values.username?.trim() || '', password: values.password || '', totp_code: values.totp_code?.trim() || undefined, } const res = await authService.login(data) loginStore(res.account) message.success('登录成功') const from = searchParams.get('from') || '/' navigate(from, { replace: true }) } catch (err: unknown) { const error = err as { message?: string; status?: number } const msg = error.message || '' if (msg.includes('TOTP') || msg.includes('totp') || msg.includes('2FA') || msg.includes('验证码') || error.status === 403) { setNeedTotp(true) message.warning(msg || '请输入两步验证码') } else { message.error(msg || '登录失败,请检查用户名和密码') } } finally { setLoading(false) } } return (
{/* Left Brand Panel — hidden on mobile */}
{/* Decorative gradient orb */}
{/* Brand content */}
Z

ZCLAW

AI Agent 管理平台

统一管理 AI 服务商、模型配置、API 密钥、用量监控与系统配置

{/* Right Login Form */}
{/* Mobile logo (visible only on mobile) */}
Z
ZCLAW

登录

输入您的账号信息以继续

, autoComplete: 'username', }} placeholder="请输入用户名" rules={[{ required: true, message: '请输入用户名' }]} /> , autoComplete: 'current-password', }} placeholder="请输入密码" rules={[{ required: true, message: '请输入密码' }]} /> {needTotp && ( , maxLength: 6, autoComplete: 'one-time-code', }} placeholder="请输入 6 位验证码" rules={[{ required: true, message: '请输入验证码' }]} /> )}
) }