| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- import React, { useState } from 'react';
- import {
- Form,
- Input,
- Button,
- Card,
- App,
- } from 'antd';
- import {
- UserOutlined,
- LockOutlined,
- EyeOutlined,
- EyeInvisibleOutlined
- } from '@ant-design/icons';
- import { useNavigate } from 'react-router';
- import {
- useAuth,
- } from '../hooks/AuthProvider';
- // 登录页面
- export const LoginPage = () => {
- const { message } = App.useApp();
- const { login } = useAuth();
- const [form] = Form.useForm();
- const [loading, setLoading] = useState(false);
- const navigate = useNavigate();
-
- const handleSubmit = async (values: { username: string; password: string }) => {
- try {
- setLoading(true);
-
- // 获取地理位置
- let latitude: number | undefined;
- let longitude: number | undefined;
-
- try {
- if (navigator.geolocation) {
- const position = await new Promise<GeolocationPosition>((resolve, reject) => {
- navigator.geolocation.getCurrentPosition(resolve, reject);
- });
- latitude = position.coords.latitude;
- longitude = position.coords.longitude;
- }
- } catch (geoError) {
- console.warn('获取地理位置失败:', geoError);
- }
-
- await login(values.username, values.password, latitude, longitude);
- // 登录成功后跳转到管理后台首页
- navigate('/admin/dashboard');
- } catch (error: any) {
- message.error(error instanceof Error ? error.message : '登录失败');
- } finally {
- setLoading(false);
- }
- };
-
- return (
- <div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100 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="w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center mx-auto mb-4">
- <UserOutlined style={{ fontSize: 32, color: '#1890ff' }} />
- </div>
- <h2 className="mt-2 text-center text-3xl font-extrabold text-gray-900">
- 管理后台登录
- </h2>
- <p className="mt-2 text-gray-500">请输入您的账号和密码</p>
- </div>
-
- <Card className="shadow-lg border-none transition-all duration-300 hover:shadow-xl">
- <Form
- form={form}
- name="login"
- onFinish={handleSubmit}
- autoComplete="off"
- layout="vertical"
- >
- <Form.Item
- name="username"
- rules={[{ required: true, message: '请输入用户名' }]}
- label="用户名"
- >
- <Input
- prefix={<UserOutlined className="text-primary" />}
- placeholder="请输入用户名"
- size="large"
- className="transition-all duration-200 focus:border-primary focus:ring-1 focus:ring-primary"
- />
- </Form.Item>
-
- <Form.Item
- name="password"
- rules={[{ required: true, message: '请输入密码' }]}
- label="密码"
- >
- <Input.Password
- prefix={<LockOutlined className="text-primary" />}
- placeholder="请输入密码"
- size="large"
- iconRender={(visible) => (visible ? <EyeOutlined /> : <EyeInvisibleOutlined />)}
- className="transition-all duration-200 focus:border-primary focus:ring-1 focus:ring-primary"
- />
- </Form.Item>
-
- <Form.Item>
- <Button
- type="primary"
- htmlType="submit"
- size="large"
- block
- loading={loading}
- className="h-12 text-lg transition-all duration-200 hover:shadow-lg"
- >
- 登录
- </Button>
- </Form.Item>
- </Form>
-
- <div className="mt-6 text-center text-gray-500 text-sm">
- <p>测试账号: <span className="font-medium">admin</span> / <span className="font-medium">admin123</span></p>
- <p className="mt-1">© {new Date().getFullYear()} 管理系统. 保留所有权利.</p>
- </div>
- </Card>
- </div>
- </div>
- );
- };
|