Files
Web_BLV_OA_Exam_Prod/src/pages/HomePage.tsx

177 lines
5.5 KiB
TypeScript

import { useState, useEffect } from 'react';
import { Card, Form, Input, Button, message, Typography, AutoComplete } from 'antd';
import { useNavigate } from 'react-router-dom';
import { useUser } from '../contexts';
import { userAPI } from '../services/api';
import { validateUserForm } from '../utils/validation';
const { Title } = Typography;
interface LoginHistory {
name: string;
phone: string;
}
const HomePage = () => {
const navigate = useNavigate();
const { setUser } = useUser();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [historyOptions, setHistoryOptions] = useState<{ value: string; label: string; phone: string }[]>([]);
useEffect(() => {
// 加载历史记录
const history = JSON.parse(localStorage.getItem('loginHistory') || '[]');
setHistoryOptions(history.map((item: LoginHistory) => ({
value: item.name,
label: item.name,
phone: item.phone
})));
}, []);
const saveToHistory = (name: string, phone: string) => {
const history: LoginHistory[] = JSON.parse(localStorage.getItem('loginHistory') || '[]');
// 移除已存在的同名记录(为了更新位置到最前,或者保持最新)
// 简单起见,如果已存在,先移除
const filtered = history.filter(item => item.name !== name);
// 添加到头部
filtered.unshift({ name, phone });
// 保留前5条
const newHistory = filtered.slice(0, 5);
localStorage.setItem('loginHistory', JSON.stringify(newHistory));
};
const handleNameSelect = (value: string, option: any) => {
if (option.phone) {
form.setFieldsValue({ phone: option.phone });
}
};
const handleSubmit = async (values: { name: string; phone: string; password?: string }) => {
try {
setLoading(true);
// 验证表单
const validation = validateUserForm(values.name, values.phone);
if (!validation.valid) {
message.error(validation.nameError || validation.phoneError);
return;
}
// 创建用户或登录
const response = await userAPI.createUser(values) as any;
if (response.success) {
setUser(response.data);
saveToHistory(values.name, values.phone);
message.success('登录成功,请选择考试科目');
setTimeout(() => {
navigate('/subjects');
}, 1000);
}
} catch (error: any) {
message.error(error.message || '登录失败');
} finally {
setLoading(false);
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center p-4">
<div className="w-full max-w-md">
<Card className="shadow-xl">
<div className="text-center mb-6">
<Title level={2} className="text-blue-600">
</Title>
<p className="text-gray-600 mt-2">
</p>
</div>
<Form
form={form}
layout="vertical"
onFinish={handleSubmit}
autoComplete="off"
>
<Form.Item
label="姓名"
name="name"
rules={[
{ required: true, message: '请输入姓名' },
{ min: 2, max: 20, message: '姓名长度必须在2-20个字符之间' },
{ pattern: /^[\u4e00-\u9fa5a-zA-Z\s]+$/, message: '姓名只能包含中文、英文和空格' }
]}
>
<AutoComplete
options={historyOptions}
onSelect={handleNameSelect}
placeholder="请输入您的姓名"
size="large"
filterOption={(inputValue, option) =>
option!.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
/>
</Form.Item>
<Form.Item
label="手机号"
name="phone"
rules={[
{ required: true, message: '请输入手机号' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的中国手机号' }
]}
>
<Input
placeholder="请输入11位手机号"
size="large"
className="rounded-lg"
maxLength={11}
/>
</Form.Item>
<Form.Item
label="登录密码"
name="password"
rules={[
{ required: true, message: '请输入登录密码' }
]}
>
<Input.Password
placeholder="请输入登录密码"
size="large"
className="rounded-lg"
autoComplete="new-password"
visibilityToggle
/>
</Form.Item>
<Form.Item className="mb-0">
<Button
type="primary"
htmlType="submit"
loading={loading}
size="large"
className="w-full rounded-lg bg-blue-600 hover:bg-blue-700 border-none"
>
</Button>
</Form.Item>
</Form>
<div className="mt-6 text-center">
<a
href="/admin/login"
className="text-blue-600 hover:text-blue-800 text-sm"
>
</a>
</div>
</Card>
</div>
</div>
);
};
export default HomePage;