修改注册登录界面,新增路由保护
Change-Id: I6c665d9e92813506158113fe97c1119d7ad09d92
diff --git a/front/src/AnimePage.js b/front/src/AnimePage.js
index 118d8fb..3cf5ac9 100644
--- a/front/src/AnimePage.js
+++ b/front/src/AnimePage.js
@@ -10,6 +10,7 @@
import "./App.css";
import { useNavigate } from "react-router-dom";
import { API_BASE_URL } from "./config";
+import ForumIcon from "@mui/icons-material/Forum";
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];
diff --git a/front/src/App.js b/front/src/App.js
index 52f3a83..2f85943 100644
--- a/front/src/App.js
+++ b/front/src/App.js
@@ -24,7 +24,7 @@
import PostDetailPage from "./PostDetailPage";
import LoginPage from './LoginPage';
import RegisterPage from './RegisterPage';
-
+import RequireAuth from './RequireAuth';
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -150,18 +150,21 @@
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route path="/" element={<Navigate to="/login" replace />} />
- <Route path="/movie" element={<MoviePage />} />
- <Route path="/tv" element={<TVPage />} />
- <Route path="/music" element={<MusicPage />} />
- <Route path="/anime" element={<AnimePage />} />
- <Route path="/game" element={<GamePage />} />
- <Route path="/sport" element={<SportPage />} />
- <Route path="/forum" element={<ForumPage />} />
- <Route path="/forum/:postId" element={<PostDetailPage />} />
- <Route path="/info" element={<InfoPage />} />
- <Route path="/user" element={<UserProfile />} />
- <Route path="/publish" element={<PublishPage />} />
- <Route path="/torrent/:torrentId" element={<TorrentDetailPage />} />
+ {/* Protected routes */}
+ <Route element={<RequireAuth />}>
+ <Route path="/movie" element={<MoviePage />} />
+ <Route path="/tv" element={<TVPage />} />
+ <Route path="/music" element={<MusicPage />} />
+ <Route path="/anime" element={<AnimePage />} />
+ <Route path="/game" element={<GamePage />} />
+ <Route path="/sport" element={<SportPage />} />
+ <Route path="/forum" element={<ForumPage />} />
+ <Route path="/forum/:postId" element={<PostDetailPage />} />
+ <Route path="/info" element={<InfoPage />} />
+ <Route path="/user" element={<UserProfile />} />
+ <Route path="/publish" element={<PublishPage />} />
+ <Route path="/torrent/:torrentId" element={<TorrentDetailPage />} />
+ </Route>
</Routes>
</Router>
);
diff --git a/front/src/ForumPage.js b/front/src/ForumPage.js
index ed94e0f..abcba7d 100644
--- a/front/src/ForumPage.js
+++ b/front/src/ForumPage.js
@@ -1,5 +1,6 @@
-import React from "react";
+import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
+import { API_BASE_URL } from "./config";
// 示例数据
const posts = [
@@ -27,6 +28,20 @@
export default function ForumPage() {
const navigate = useNavigate();
+ const [posts, setPosts] = useState([]);
+
+ useEffect(() => {
+ // get userId from cookie
+ const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
+ const userId = match ? match[2] : null;
+ console.log("User ID from cookie:", userId);
+ if (!userId) return;
+ fetch(`${API_BASE_URL}/api/forum`)
+ .then(res => res.json())
+ .then(data => setPosts(data))
+ .catch(() => setPosts([]));
+ }, []);
+
return (
<div style={{ maxWidth: 700, margin: "40px auto" }}>
<div style={{ display: "flex", alignItems: "center", marginBottom: 24 }}>
diff --git a/front/src/GamePage.js b/front/src/GamePage.js
index 1de4d30..c1ce231 100644
--- a/front/src/GamePage.js
+++ b/front/src/GamePage.js
@@ -10,6 +10,7 @@
import "./App.css";
import { useNavigate } from "react-router-dom";
import { API_BASE_URL } from "./config";
+import ForumIcon from "@mui/icons-material/Forum";
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];
diff --git a/front/src/InfoPage.js b/front/src/InfoPage.js
index 0ed6ade..90dc449 100644
--- a/front/src/InfoPage.js
+++ b/front/src/InfoPage.js
@@ -10,6 +10,7 @@
import "./App.css";
import { useNavigate } from "react-router-dom";
import { API_BASE_URL } from "./config";
+import ForumIcon from "@mui/icons-material/Forum";
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];
diff --git a/front/src/LoginPage.js b/front/src/LoginPage.js
index acbde03..5bb3603 100644
--- a/front/src/LoginPage.js
+++ b/front/src/LoginPage.js
@@ -2,6 +2,7 @@
import { useNavigate } from 'react-router-dom';
import { Input } from 'antd';
import './App.css';
+import { API_BASE_URL } from './config';
const LoginPage = () => {
const [formData, setFormData] = useState({ username: '', password: '' });
@@ -13,15 +14,38 @@
setFormData({ ...formData, [name]: value });
};
- const handleLogin = () => {
+ const handleLogin = async () => {
if (formData.password.length < 8) {
setErrorMessage('密码必须至少包含八位字符!');
return;
}
- // Simulate successful login
- setErrorMessage('');
- navigate('/movie');
+ // send login request to backend
+ try {
+ // console.log('登录信息:', formData);
+ const response = await fetch(`${API_BASE_URL}/api/login`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ email: formData.username, password: formData.password })
+ });
+ console.log(response);
+ const data = await response.json();
+ if (!response.ok) {
+ setErrorMessage(data.message || '登录失败,请检查账号密码');
+ return;
+ }
+ // store returned userId in cookie
+ const userId = data.userId || data.userid || data.id;
+ if (!userId) {
+ setErrorMessage('登录失败,未返回用户ID');
+ return;
+ }
+ document.cookie = `userId=${userId}; path=/`;
+ setErrorMessage('');
+ navigate('/movie');
+ } catch (error) {
+ setErrorMessage('网络错误,请稍后重试');
+ }
};
const handleRegister = () => {
@@ -46,9 +70,9 @@
<h1 style={{ textAlign: 'center', marginBottom: 32, color: '#222', fontWeight: 700, fontSize: 32, letterSpacing: 2 }}>欢迎登录</h1>
<form className="login-form">
<div className="form-row" style={{ marginBottom: 24 }}>
- <label htmlFor="username" style={{ display: 'block', marginBottom: 8, color: '#333', fontWeight: 500, fontSize: 16 }}>用户名</label>
+ <label htmlFor="username" style={{ display: 'block', marginBottom: 8, color: '#333', fontWeight: 500, fontSize: 16 }}>邮箱</label>
<Input
- placeholder="请输入用户名"
+ placeholder="请输入邮箱"
id="username"
name="username"
value={formData.username}
diff --git a/front/src/MoviePage.js b/front/src/MoviePage.js
index 83ccad1..faef3bd 100644
--- a/front/src/MoviePage.js
+++ b/front/src/MoviePage.js
@@ -7,6 +7,7 @@
import SportsMartialArtsIcon from "@mui/icons-material/SportsMartialArts";
import PersonIcon from "@mui/icons-material/Person";
import AccountCircleIcon from "@mui/icons-material/AccountCircle";
+import ForumIcon from "@mui/icons-material/Forum";
import { useNavigate } from "react-router-dom";
import "./App.css";
import { API_BASE_URL } from "./config";
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];
diff --git a/front/src/MusicPage.js b/front/src/MusicPage.js
index fb03fe1..d244629 100644
--- a/front/src/MusicPage.js
+++ b/front/src/MusicPage.js
@@ -10,6 +10,7 @@
import "./App.css";
import { useNavigate } from "react-router-dom";
import { API_BASE_URL } from "./config";
+import ForumIcon from "@mui/icons-material/Forum";
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];
diff --git a/front/src/RegisterPage.js b/front/src/RegisterPage.js
index ffd11a4..a527850 100644
--- a/front/src/RegisterPage.js
+++ b/front/src/RegisterPage.js
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Input } from 'antd';
+import { API_BASE_URL } from './config';
import './App.css';
const RegisterPage = () => {
@@ -13,7 +14,7 @@
setFormData({ ...formData, [name]: value });
};
- const handleRegister = () => {
+ const handleRegister = async () => {
if (formData.password.length !== 8) {
setErrorMessage('密码必须为八位字符!');
return;
@@ -24,12 +25,25 @@
return;
}
- // Simulate successful registration
- setErrorMessage('');
- // 存储注册信息到 sessionStorage
- sessionStorage.setItem('registeredUser', JSON.stringify({ username: formData.username, password: formData.password }));
- alert('注册成功!');
- navigate('/login');
+ // send registration request to backend
+ try {
+ console.log('注册信息:', formData);
+ const response = await fetch(`${API_BASE_URL}/api/register`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username: formData.username, password: formData.password, invite_email: formData.inviteCode })
+ });
+ const data = await response.json();
+ if (!response.ok) {
+ setErrorMessage(data.message || '注册失败,请重试');
+ return;
+ }
+ setErrorMessage('');
+ navigate('/login');
+ alert('注册成功!');
+ } catch (error) {
+ setErrorMessage('网络错误,请稍后重试');
+ }
};
return (
diff --git a/front/src/RequireAuth.js b/front/src/RequireAuth.js
new file mode 100644
index 0000000..77cde56
--- /dev/null
+++ b/front/src/RequireAuth.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import { Navigate, Outlet } from 'react-router-dom';
+
+// Component to protect routes that require authentication
+const RequireAuth = () => {
+ // Check if userId cookie exists
+ const getCookie = (name) => {
+ const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
+ return match ? match[2] : null;
+ };
+
+ const userId = getCookie('userId');
+ // If not authenticated, redirect to login
+ return userId ? <Outlet /> : <Navigate to="/login" replace />;
+};
+
+export default RequireAuth;
diff --git a/front/src/SportPage.js b/front/src/SportPage.js
index 4c9d17d..a221c09 100644
--- a/front/src/SportPage.js
+++ b/front/src/SportPage.js
@@ -10,6 +10,7 @@
import "./App.css";
import { useNavigate } from "react-router-dom";
import { API_BASE_URL } from "./config";
+import ForumIcon from "@mui/icons-material/Forum";
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];
diff --git a/front/src/TVPage.js b/front/src/TVPage.js
index 216dfcc..1bc9a07 100644
--- a/front/src/TVPage.js
+++ b/front/src/TVPage.js
@@ -10,6 +10,7 @@
import { useNavigate } from "react-router-dom";
import "./App.css";
import { API_BASE_URL } from "./config";
+import ForumIcon from "@mui/icons-material/Forum";
const navItems = [
{ label: "电影", icon: <MovieIcon />, path: "/movie" },
@@ -19,6 +20,7 @@
{ label: "游戏", icon: <SportsEsportsIcon />, path: "/game" },
{ label: "体育", icon: <SportsMartialArtsIcon />, path: "/sport" },
{ label: "资料", icon: <PersonIcon />, path: "/info" },
+ { label: "论坛", icon: <ForumIcon />, path: "/forum" },
{ label: "发布", icon: <AccountCircleIcon />, path: "/publish" }, // Added Publish option
];