KnowledgeBase_frontend/src/pages/auth/Signup.jsx

274 lines
10 KiB
React
Raw Normal View History

2025-03-04 03:38:50 +08:00
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useNavigate } from 'react-router-dom';
import { checkAuthThunk, signupThunk } from '../../store/auth/auth.thunk';
// 部门和组别映射关系
const departmentGroups = {
2025-04-13 01:37:23 +08:00
达人部门: ['达人部门'],
商务部门: ['商务部门'],
样本中心: ['样本中心'],
产品部门: ['产品部门'],
AI自媒体: ['AI自媒体'],
HR: ['HR'],
技术部门: ['技术部门'],
};
2025-03-04 03:38:50 +08:00
export default function Signup() {
const dispatch = useDispatch();
const navigate = useNavigate();
const [formData, setFormData] = useState({
username: '',
email: '',
password: '',
name: '',
role: 'member',
department: '',
group: '',
});
2025-03-04 03:38:50 +08:00
const [errors, setErrors] = useState({});
const [submitted, setSubmitted] = useState(false);
const [availableGroups, setAvailableGroups] = useState([]);
2025-03-04 03:38:50 +08:00
const { user, loading } = useSelector((state) => state.auth);
2025-03-04 03:38:50 +08:00
useEffect(() => {
handleCheckAuth();
}, [dispatch]);
// 当部门变化时,更新可选的组别
useEffect(() => {
if (formData.department && departmentGroups[formData.department]) {
setAvailableGroups(departmentGroups[formData.department]);
// 如果已选择的组别不在新部门的选项中,则重置组别
if (!departmentGroups[formData.department].includes(formData.group)) {
setFormData(prev => ({
...prev,
group: ''
}));
}
} else {
setAvailableGroups([]);
setFormData(prev => ({
...prev,
group: ''
}));
}
}, [formData.department]);
2025-03-04 03:38:50 +08:00
const handleCheckAuth = async () => {
console.log('signup page handleCheckAuth');
2025-03-04 07:22:05 +08:00
try {
await dispatch(checkAuthThunk()).unwrap();
if (user) navigate('/');
} catch (error) {}
2025-03-04 03:38:50 +08:00
};
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
// 清除对应的错误信息
if (errors[name]) {
setErrors({
...errors,
[name]: '',
});
}
};
2025-03-04 03:38:50 +08:00
const validateForm = () => {
const newErrors = {};
if (!formData.username) {
2025-03-04 03:38:50 +08:00
newErrors.username = 'Username is required';
}
if (!formData.email) {
2025-03-04 03:38:50 +08:00
newErrors.email = 'Email is required';
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(formData.email)) {
2025-03-04 03:38:50 +08:00
newErrors.email = 'Invalid email address';
}
2025-03-04 07:22:05 +08:00
if (!formData.password) {
2025-03-04 03:38:50 +08:00
newErrors.password = 'Password is required';
} else if (formData.password.length < 6) {
2025-03-04 03:38:50 +08:00
newErrors.password = 'Password must be at least 6 characters';
}
if (!formData.name) {
newErrors.name = 'Name is required';
}
if (!formData.department) {
newErrors.department = '请选择部门';
}
if (!formData.group) {
newErrors.group = '请选择组别';
}
2025-03-04 03:38:50 +08:00
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
2025-03-04 07:22:05 +08:00
const handleSubmit = async (e) => {
2025-03-04 03:38:50 +08:00
e.preventDefault();
setSubmitted(true);
if (validateForm()) {
console.log('Form submitted successfully!');
console.log('Registration data:', formData);
2025-03-04 07:22:05 +08:00
try {
await dispatch(signupThunk(formData)).unwrap();
navigate('/login');
2025-03-04 07:22:05 +08:00
} catch (error) {
console.error('Signup failed:', error);
}
2025-03-04 03:38:50 +08:00
}
};
return (
<div className='position-absolute top-50 start-50 translate-middle d-flex flex-column gap-4 align-items-center'>
<div className='title text-center h1'>OOIN 智能知识库</div>
<form
className='auth-form login-form d-flex flex-column gap-3 align-items-center'
onSubmit={handleSubmit}
noValidate
>
<div className='input-group has-validation'>
<input
type='text'
className={`form-control form-control-lg${submitted && errors.username ? ' is-invalid' : ''}`}
id='username'
name='username'
placeholder='用户名'
value={formData.username}
2025-03-04 03:38:50 +08:00
required
onChange={handleInputChange}
disabled={loading}
2025-03-04 03:38:50 +08:00
></input>
{submitted && errors.username && <div className='invalid-feedback'>{errors.username}</div>}
</div>
<div className='input-group has-validation'>
<input
type='email'
className={`form-control form-control-lg${submitted && errors.email ? ' is-invalid' : ''}`}
id='email'
name='email'
placeholder='邮箱'
value={formData.email}
2025-03-04 03:38:50 +08:00
required
onChange={handleInputChange}
disabled={loading}
2025-03-04 03:38:50 +08:00
></input>
{submitted && errors.email && <div className='invalid-feedback'>{errors.email}</div>}
</div>
<div className='input-group has-validation'>
<input
type='password'
id='password'
name='password'
placeholder='密码'
value={formData.password}
2025-03-04 03:38:50 +08:00
required
className={`form-control form-control-lg${submitted && errors.password ? ' is-invalid' : ''}`}
aria-describedby='passwordHelpBlock'
onChange={handleInputChange}
disabled={loading}
2025-03-04 03:38:50 +08:00
></input>
{submitted && errors.password && <div className='invalid-feedback'>{errors.password}</div>}
</div>
<div className='input-group has-validation'>
<input
type='text'
className={`form-control form-control-lg${submitted && errors.name ? ' is-invalid' : ''}`}
id='name'
name='name'
placeholder='姓名'
value={formData.name}
required
onChange={handleInputChange}
disabled={loading}
></input>
{submitted && errors.name && <div className='invalid-feedback'>{errors.name}</div>}
</div>
<div className='input-group has-validation'>
<select
className={`form-select form-select-lg${submitted && errors.department ? ' is-invalid' : ''}`}
id='department'
name='department'
value={formData.department}
onChange={handleInputChange}
disabled={loading}
required
>
<option value='' disabled>
选择部门
</option>
<option value='技术部'>技术部</option>
<option value='产品部'>产品部</option>
<option value='市场部'>市场部</option>
<option value='行政部'>行政部</option>
</select>
{submitted && errors.department && <div className='invalid-feedback'>{errors.department}</div>}
</div>
<div className='input-group has-validation'>
<select
className={`form-select form-select-lg${submitted && errors.group ? ' is-invalid' : ''}`}
id='group'
name='group'
value={formData.group}
onChange={handleInputChange}
disabled={loading || !formData.department}
required
>
<option value='' disabled>
{formData.department ? '选择组别' : '请先选择部门'}
</option>
{availableGroups.map((group, index) => (
<option key={index} value={group}>
{group}
</option>
))}
</select>
{submitted && errors.group && <div className='invalid-feedback'>{errors.group}</div>}
</div>
<div className='input-group'>
<select
className='form-select form-select-lg'
id='role'
name='role'
value={formData.role}
onChange={handleInputChange}
disabled={loading}
>
<option value='member'>普通成员</option>
<option value='leader'>组长</option>
<option value='admin'>管理员</option>
</select>
</div>
<button type='submit' className='btn btn-dark btn-lg w-100' disabled={loading}>
{loading ? (
<>
<span
className='spinner-border spinner-border-sm me-2'
role='status'
aria-hidden='true'
></span>
注册中...
</>
) : (
'注册'
)}
2025-03-04 03:38:50 +08:00
</button>
</form>
<Link to='/login' className='go-to-signup w-100 link-underline-light h5 text-center'>
已有账号立即登录
2025-03-04 03:38:50 +08:00
</Link>
</div>
);
}