新增路由管理
Change-Id: I8139fd09f135c42944f60ca473ee208e69549dc2
diff --git a/Merge/front/src/pages/LoginPage/LoginPage.js b/Merge/front/src/pages/LoginPage/LoginPage.js
index c315b7d..31453a4 100644
--- a/Merge/front/src/pages/LoginPage/LoginPage.js
+++ b/Merge/front/src/pages/LoginPage/LoginPage.js
@@ -1,380 +1,234 @@
-import React, { useState, useEffect } from 'react';
-import { Link } from 'react-router-dom';
-import { Input, Checkbox, Modal, Alert } from 'antd';
-import { MailOutlined, LockOutlined, ExclamationCircleOutlined, CheckCircleOutlined } from '@ant-design/icons';
-import {
- getRememberedLoginInfo,
- saveRememberedLoginInfo,
- saveAuthInfo,
- isLoggedIn
-} from '../../utils/auth';
-import { hashPassword } from '../../utils/crypto';
-import './LoginPage.css';
+// src/pages/LoginPage/LoginPage.jsx
+import React, { useState, useEffect } from 'react'
+import { useNavigate, Link } from 'react-router-dom'
+import { Input, Checkbox, Modal, Alert } from 'antd'
+import {
+ MailOutlined,
+ LockOutlined,
+ ExclamationCircleOutlined,
+ CheckCircleOutlined
+} from '@ant-design/icons'
+import {
+ getRememberedLoginInfo,
+ saveRememberedLoginInfo,
+ saveAuthInfo,
+ isLoggedIn
+} from '../../utils/auth'
+import { hashPassword } from '../../utils/crypto'
+import './LoginPage.css'
-const baseURL = 'http://10.126.59.25:8082';
+const baseURL = 'http://10.126.59.25:8082'
-const LoginPage = () => {
+export default function LoginPage() {
+ const navigate = useNavigate()
+
const [formData, setFormData] = useState({
email: '',
password: ''
- });
-
- const [rememberMe, setRememberMe] = useState(false);
- const [isLoading, setIsLoading] = useState(false);
- const [errors, setErrors] = useState({
- email: '',
- password: ''
- });
+ })
+ const [rememberMe, setRememberMe] = useState(false)
+ const [isLoading, setIsLoading] = useState(false)
+ const [errors, setErrors] = useState({ email: '', password: '' })
const [errorModal, setErrorModal] = useState({
visible: false,
title: '',
content: ''
- });
+ })
const [successAlert, setSuccessAlert] = useState({
visible: false,
message: ''
- });
+ })
// 显示错误弹窗
const showErrorModal = (title, content) => {
- setErrorModal({
- visible: true,
- title: title,
- content: content
- });
- };
-
+ setErrorModal({ visible: true, title, content })
+ }
// 关闭错误弹窗
const closeErrorModal = () => {
- setErrorModal({
- visible: false,
- title: '',
- content: ''
- });
- };
-
+ setErrorModal({ visible: false, title: '', content: '' })
+ }
// 显示成功提示
const showSuccessAlert = (message) => {
- setSuccessAlert({
- visible: true,
- message: message
- });
-
- // 3秒后自动隐藏
+ setSuccessAlert({ visible: true, message })
setTimeout(() => {
- setSuccessAlert({
- visible: false,
- message: ''
- });
- }, 3000);
- };
+ setSuccessAlert({ visible: false, message: '' })
+ }, 3000)
+ }
- // 页面加载时检查是否有记住的登录信息
+ // 初始化:检查登录 & 填充“记住我”
useEffect(() => {
- // 检查是否已经登录
if (isLoggedIn()) {
- // 如果已经有token,可以选择直接跳转到主页面
- // window.location.href = '/test-dashboard';
- console.log('用户已登录');
+ console.log('用户已登录')
+ // 如果要自动跳转可以在这里:
+ // navigate('/home', { replace: true })
}
-
- // 获取记住的登录信息
- const rememberedInfo = getRememberedLoginInfo();
- if (rememberedInfo.rememberMe && rememberedInfo.email) {
- setFormData({
- email: rememberedInfo.email,
- password: rememberedInfo.password
- });
- setRememberMe(true);
+ const { email, password, rememberMe } = getRememberedLoginInfo()
+ if (rememberMe && email) {
+ setFormData({ email, password })
+ setRememberMe(true)
}
- }, []);
+ }, [navigate])
const handleEmailChange = (e) => {
- const value = e.target.value;
- setFormData(prev => ({
- ...prev,
- email: value
- }));
-
- // 清除邮箱错误提示
- if (errors.email) {
- setErrors(prev => ({
- ...prev,
- email: ''
- }));
- }
- };
-
+ setFormData(f => ({ ...f, email: e.target.value }))
+ if (errors.email) setErrors(e => ({ ...e, email: '' }))
+ }
const handlePasswordChange = (e) => {
- const value = e.target.value;
- setFormData(prev => ({
- ...prev,
- password: value
- }));
-
- // 清除密码错误提示
- if (errors.password) {
- setErrors(prev => ({
- ...prev,
- password: ''
- }));
- }
- };
-
+ setFormData(f => ({ ...f, password: e.target.value }))
+ if (errors.password) setErrors(e => ({ ...e, password: '' }))
+ }
const handleRememberMeChange = (e) => {
- const checked = e.target.checked;
- setRememberMe(checked);
-
- // 如果取消记住我,清除已保存的登录信息
+ const checked = e.target.checked
+ setRememberMe(checked)
if (!checked) {
- saveRememberedLoginInfo('', '', false);
+ saveRememberedLoginInfo('', '', false)
}
- };
+ }
const validateForm = () => {
- const newErrors = {
- email: '',
- password: ''
- };
-
- let hasError = false;
-
- // 验证邮箱
- if (!formData.email || typeof formData.email !== 'string' || !formData.email.trim()) {
- newErrors.email = '请输入邮箱地址';
- hasError = true;
- } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
- newErrors.email = '请输入有效的邮箱地址';
- hasError = true;
+ const newErr = { email: '', password: '' }
+ let hasError = false
+ if (!formData.email.trim() || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
+ newErr.email = '请输入有效的邮箱地址'
+ hasError = true
}
-
- // 验证密码
- if (!formData.password || typeof formData.password !== 'string' || !formData.password.trim()) {
- newErrors.password = '请输入密码';
- hasError = true;
- } else if (formData.password.length < 6) {
- newErrors.password = '密码长度至少6位';
- hasError = true;
+ if (!formData.password.trim() || formData.password.length < 6) {
+ newErr.password = '密码长度至少6位'
+ hasError = true
}
-
- setErrors(newErrors);
- return !hasError;
- };
+ setErrors(newErr)
+ return !hasError
+ }
const handleSubmit = async (e) => {
- e.preventDefault();
-
- // 验证表单
- if (!validateForm()) {
- return;
- }
-
- setIsLoading(true);
-
+ e.preventDefault()
+ if (!validateForm()) return
+
+ setIsLoading(true)
try {
- // 发送登录请求到后端
- const response = await fetch(baseURL + '/login', {
+ const res = await fetch(baseURL + '/login', {
method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
+ headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
- email: formData.email, // 后端支持邮箱登录
- password: hashPassword(formData.password) // 前端加密密码
+ email: formData.email,
+ password: hashPassword(formData.password)
})
- });
-
- const result = await response.json();
-
+ })
+ const result = await res.json()
if (result.success) {
- // 显示成功提示
- showSuccessAlert('登录成功!正在跳转...');
-
- // 保存认证信息
- saveAuthInfo(result.token, result.user, rememberMe);
-
- // 保存或清除记住的登录信息
- saveRememberedLoginInfo(formData.email, formData.password, rememberMe);
-
- // 延迟跳转,让用户看到成功提示
+ showSuccessAlert('登录成功!正在跳转...')
+ saveAuthInfo(result.token, result.user, rememberMe)
+ saveRememberedLoginInfo(formData.email, formData.password, rememberMe)
setTimeout(() => {
- window.location.href = '/test-dashboard';
- }, 1500);
+ // 根据不同角色跳转
+ switch (result.user.role) {
+ case 'admin':
+ navigate('/admin', { replace: true })
+ break
+ case 'superadmin':
+ navigate('/superadmin', { replace: true })
+ break
+ default:
+ navigate('/home', { replace: true })
+ }
+ }, 1500)
} else {
- // 登录失败,显示错误信息
- let errorTitle = '登录失败';
- let errorContent = result.message || '登录失败,请检查您的邮箱和密码';
-
- // 根据错误类型提供更详细的信息
+ let title = '登录失败'
+ let content = result.message || '登录失败,请检查您的邮箱和密码'
if (result.message) {
- if (result.message.includes('邮箱') || result.message.includes('email')) {
- errorTitle = '邮箱验证失败';
- errorContent = '您输入的邮箱地址不存在或格式不正确,请检查后重试。';
- } else if (result.message.includes('密码') || result.message.includes('password')) {
- errorTitle = '密码验证失败';
- errorContent = '您输入的密码不正确,请检查后重试。如果忘记密码,请点击"忘记密码"进行重置。';
- } else if (result.message.includes('用户不存在')) {
- errorTitle = '用户不存在';
- errorContent = '该邮箱尚未注册,请先注册账户或检查邮箱地址是否正确。';
- } else if (result.message.includes('账户被锁定') || result.message.includes('locked')) {
- errorTitle = '账户被锁定';
- errorContent = '您的账户因安全原因被暂时锁定,请联系客服或稍后重试。';
+ if (/邮箱|email/.test(result.message)) {
+ title = '邮箱验证失败'
+ content = '请输入正确的邮箱地址'
+ } else if (/密码|password/.test(result.message)) {
+ title = '密码验证失败'
+ content = '密码不正确,请重试'
}
}
-
- showErrorModal(errorTitle, errorContent);
+ showErrorModal(title, content)
}
- } catch (error) {
- console.error('登录请求失败:', error);
-
- // 根据错误类型显示不同的错误信息
- if (error.name === 'TypeError' && error.message.includes('fetch')) {
- showErrorModal('网络连接失败', '无法连接到服务器,请检查您的网络连接后重试。如果问题持续存在,请联系客服。');
- } else if (error.name === 'AbortError') {
- showErrorModal('请求超时', '请求超时,请检查网络连接后重试。');
- } else {
- showErrorModal('登录失败', '网络连接失败,请检查网络或稍后重试。如果问题持续存在,请联系客服。');
- }
+ } catch (err) {
+ console.error(err)
+ showErrorModal('网络异常', '无法连接到服务器,请稍后重试')
} finally {
- setIsLoading(false);
+ setIsLoading(false)
}
- };
+ }
return (
<div className="login-container">
- <div className="login-background"></div>
-
+ <div className="login-background" />
{isLoading && (
<div className="loading-overlay">
<div className="loading-content">
- <div className="loading-spinner-large"></div>
+ <div className="loading-spinner-large" />
<p className="loading-text">正在登录...</p>
</div>
</div>
)}
-
<div className="login-content">
<div className="login-card">
- {/* 成功提示 */}
{successAlert.visible && (
- <div style={{ marginBottom: '16px' }}>
- <Alert
- message={successAlert.message}
- type="success"
- icon={<CheckCircleOutlined />}
- showIcon
- closable
- onClose={() => setSuccessAlert({ visible: false, message: '' })}
- style={{
- borderRadius: '8px',
- border: '1px solid #b7eb8f',
- backgroundColor: '#f6ffed'
- }}
- />
- </div>
+ <Alert
+ message={successAlert.message}
+ type="success"
+ icon={<CheckCircleOutlined />}
+ closable
+ style={{ marginBottom: 16, borderRadius: 8 }}
+ />
)}
-
<div className="login-header">
- <h1 className="login-title">欢迎来到小红书</h1>
- <p className="login-subtitle">标记我的生活</p>
+ <h1>欢迎来到小红书</h1>
+ <p>标记我的生活</p>
</div>
-
<form className="login-form" onSubmit={handleSubmit}>
<div className="form-group">
<Input
type="email"
- id="email"
- name="email"
- className={`form-input ${errors.email ? 'input-error' : ''}`}
- placeholder="请输入您的邮箱"
+ placeholder="邮箱"
value={formData.email}
onChange={handleEmailChange}
prefix={<MailOutlined />}
- size="large"
- title=""
status={errors.email ? 'error' : ''}
/>
- {errors.email && (
- <div className="error-message">
- {errors.email}
- </div>
- )}
+ {errors.email && <div className="error-message">{errors.email}</div>}
</div>
-
<div className="form-group">
<Input.Password
- id="password"
- name="password"
- className={`form-input ${errors.password ? 'input-error' : ''}`}
- placeholder="请输入您的密码"
+ placeholder="密码"
value={formData.password}
onChange={handlePasswordChange}
prefix={<LockOutlined />}
- size="large"
- title=""
status={errors.password ? 'error' : ''}
/>
- {errors.password && (
- <div className="error-message">
- {errors.password}
- </div>
- )}
+ {errors.password && <div className="error-message">{errors.password}</div>}
</div>
-
<div className="form-options">
- <Checkbox
- checked={rememberMe}
- onChange={handleRememberMeChange}
- >
+ <Checkbox checked={rememberMe} onChange={handleRememberMeChange}>
记住我
</Checkbox>
- <Link to="/forgot-password" className="forgot-password">忘记密码?</Link>
+ <Link to="/forgot-password">忘记密码?</Link>
</div>
-
<button
type="submit"
className={`login-button ${isLoading ? 'loading' : ''}`}
disabled={isLoading}
>
- {isLoading ? (
- <>
- <div className="loading-spinner"></div>
- 登录中...
- </>
- ) : (
- '登录'
- )}
+ {isLoading ? '登录中...' : '登录'}
</button>
</form>
-
<div className="signup-link">
- <p>还没有账户? <Link to="/register">立即注册</Link></p>
+ <p>还没有账户?<Link to="/register">立即注册</Link></p>
</div>
</div>
</div>
-
- {/* 错误弹窗 */}
<Modal
- title={
- <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
- <ExclamationCircleOutlined style={{ color: '#ff4d4f', fontSize: '18px' }} />
- {errorModal.title}
- </div>
- }
+ title={<><ExclamationCircleOutlined style={{ color: '#ff4d4f' }} /> {errorModal.title}</>}
open={errorModal.visible}
onOk={closeErrorModal}
- onCancel={closeErrorModal}
- okText="我知道了"
cancelButtonProps={{ style: { display: 'none' } }}
- centered
- className="error-modal"
>
- <div style={{ padding: '16px 0', fontSize: '14px', lineHeight: '1.6' }}>
- {errorModal.content}
- </div>
+ <p>{errorModal.content}</p>
</Modal>
</div>
- );
-};
-
-export default LoginPage;
+ )
+}