| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import { useState } from 'react';
- import { useNavigate } from 'react-router';
- import { useAuth } from '../hooks/AuthProvider';
- import { useForm } from 'react-hook-form';
- import { zodResolver } from '@hookform/resolvers/zod';
- import { z } from 'zod';
- import { toast } from 'sonner';
- import { Eye, EyeOff, User, Lock } from 'lucide-react';
- import { Button } from '@/client/components/ui/button';
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/client/components/ui/card';
- import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/client/components/ui/form';
- import { Input } from '@/client/components/ui/input';
- // 表单验证Schema
- const loginSchema = z.object({
- username: z.string().min(1, '请输入用户名'),
- password: z.string().min(1, '请输入密码'),
- });
- type LoginFormData = z.infer<typeof loginSchema>;
- // 登录页面
- export const LoginPage = () => {
- const { login } = useAuth();
- const [isLoading, setIsLoading] = useState(false);
- const [showPassword, setShowPassword] = useState(false);
- const navigate = useNavigate();
-
- const form = useForm<LoginFormData>({
- resolver: zodResolver(loginSchema),
- defaultValues: {
- username: '',
- password: '',
- },
- });
- const handleSubmit = async (data: LoginFormData) => {
- try {
- setIsLoading(true);
-
- await login(data.username, data.password);
- // 登录成功后跳转到管理后台首页
- navigate('/admin/dashboard');
- toast.success('登录成功!欢迎回来');
- } catch (error: any) {
- toast.error(error instanceof Error ? error.message : '登录失败');
- } finally {
- setIsLoading(false);
- }
- };
-
- return (
- <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 py-12 px-4 sm:px-6 lg:px-8">
- <div className="max-w-md w-full space-y-8">
- <div className="text-center">
- <div className="mx-auto w-16 h-16 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-full flex items-center justify-center shadow-lg">
- <User className="h-8 w-8 text-white" />
- </div>
- <h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900">
- 管理后台登录
- </h2>
- <p className="mt-2 text-center text-sm text-gray-600">
- 请输入您的账号和密码继续操作
- </p>
- </div>
-
- <Card className="shadow-xl border-0">
- <CardHeader className="text-center">
- <CardTitle className="text-2xl">欢迎登录</CardTitle>
- <CardDescription>
- 使用您的账户信息登录系统
- </CardDescription>
- </CardHeader>
- <CardContent>
- <Form {...form}>
- <form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-4">
- <FormField
- control={form.control}
- name="username"
- render={({ field }) => (
- <FormItem>
- <FormLabel>用户名</FormLabel>
- <FormControl>
- <div className="relative">
- <User className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
- <Input
- placeholder="请输入用户名"
- className="pl-10"
- {...field}
- />
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <FormField
- control={form.control}
- name="password"
- render={({ field }) => (
- <FormItem>
- <FormLabel>密码</FormLabel>
- <FormControl>
- <div className="relative">
- <Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
- <Input
- type={showPassword ? 'text' : 'password'}
- placeholder="请输入密码"
- className="pl-10 pr-10"
- {...field}
- />
- <button
- type="button"
- className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
- onClick={() => setShowPassword(!showPassword)}
- >
- {showPassword ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
- </button>
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <Button
- type="submit"
- className="w-full"
- disabled={isLoading}
- >
- {isLoading ? (
- <>
- <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
- 登录中...
- </>
- ) : (
- '登录'
- )}
- </Button>
- </form>
- </Form>
- </CardContent>
- <CardFooter className="flex flex-col items-center space-y-2">
- <div className="text-sm text-gray-500">
- 测试账号: <span className="font-medium text-gray-700">admin</span> / <span className="font-medium text-gray-700">admin123</span>
- </div>
- <div className="text-xs text-gray-400">
- © {new Date().getFullYear()} 管理系统. 保留所有权利.
- </div>
- </CardFooter>
- </Card>
-
- <div className="text-center">
- <p className="text-sm text-gray-500">
- 遇到问题?<a href="#" className="font-medium text-indigo-600 hover:text-indigo-500">联系管理员</a>
- </p>
- </div>
- </div>
- </div>
- );
- };
|