添加了登录的jwt LoginForm

This commit is contained in:
2023-07-09 03:00:29 +08:00
parent fdf7493195
commit 8e839c28f8
13 changed files with 373 additions and 172 deletions

View File

@@ -1,44 +1,74 @@
// App.js
import React from 'react';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import VuetifyLogo from './logo.svg';
import VuetifyName from './logo.svg';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Main from './Components';
import VideoPlayer from './VideoPlayer'; // 导入我们将创建的VideoPlayer组件
import { Route, Router, Routes } from 'react-router-dom';
import ConfigContext, { config } from './Config';
import LoginForm from './LoginForm';
import Main from './Main';
import VideoPlayer from './VideoPlayer'; // 导入我们将创建的VideoPlayer组件
import { default as VuetifyLogo, default as VuetifyName } from './logo.svg';
import axios from 'axios';
import { useLocation, useNavigate } from 'react-router-dom';
axios.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
const App = () => {
return (
const navigate = useNavigate(); // 将 navigate 声明移动到组件内部
const location = useLocation();
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
if (error.response.status === 401) {
sessionStorage.setItem('previousLocation', location.pathname); // 使用 window.location.pathname 获取当前路径
navigate('/login'); // 使用 window.location.assign() 进行导航
}
return Promise.reject(error);
}
);
return (
<ConfigContext.Provider value={config}>
<BrowserRouter>
<div>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu">
<img src={VuetifyLogo} alt="Vuetify Logo" width="40" />
</IconButton>
<Typography variant="h3" style={{ flexGrow: 1 }}>
<img src={VuetifyName} alt="Vuetify Name" width="40" />
</Typography>
</Toolbar>
</AppBar>
<div>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu">
<img src={VuetifyLogo} alt="Vuetify Logo" width="40" />
</IconButton>
<Typography variant="h3" style={{ flexGrow: 1 }}>
<img src={VuetifyName} alt="Vuetify Name" width="40" />
</Typography>
</Toolbar>
</AppBar>
</div>
<Routes>
<Route path="/" element={<Main />} />
<Route path="/res/:filename" element={<VideoPlayer />} />
<Route path="/login" element={<LoginForm />} />
<Route path="/" element={<Main />} />
<Route path="/res/:filename" element={<VideoPlayer />} />
</Routes>
</div>
</BrowserRouter>
</ConfigContext.Provider>
</ConfigContext.Provider>
);
};

View File

@@ -1,3 +1,4 @@
// CategoryNav.js
import React from 'react';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';

100
src/LoginForm.js Normal file
View File

@@ -0,0 +1,100 @@
// LoginForm.js
import React, { useContext, useState } from 'react';
import axios from 'axios';
import ConfigContext from './Config';
import { useNavigate } from 'react-router-dom';
import {
Box,
Button,
Container,
Grid,
TextField,
Typography,
} from '@mui/material';
function LoginForm() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const config = useContext(ConfigContext);
const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await axios.post(`${config.Host}/api/login`, new URLSearchParams({
username,
password,
}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
localStorage.setItem('token', response.data.token);
// 如果存在之前的页面路径,则返回,否则跳转到首页
const previousLocation = sessionStorage.getItem('previousLocation');
if (previousLocation) {
sessionStorage.removeItem('previousLocation');
navigate(previousLocation);
} else {
navigate('/');
}
} catch (error) {
setError('Invalid username or password');
}
};
return (
<Container maxWidth="xs">
<Box sx={{ marginTop: 8, display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
<Typography component="h1" variant="h5">
登录
</Typography>
{error && (
<Typography color="error" sx={{ marginTop: 1 }}>
{error}
</Typography>
)}
<Box component="form" onSubmit={handleSubmit} sx={{ width: '100%', marginTop: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
required
fullWidth
id="username"
label="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
id="password"
label="Password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
sx={{ marginTop: 3 }}
>
Login
</Button>
</Box>
</Box>
</Container>
);
}
export default LoginForm;

View File

@@ -1,3 +1,4 @@
// Main.js
import React, { useState, useEffect, useContext } from 'react';
import axios from 'axios';
import Container from '@mui/material/Container';
@@ -54,7 +55,7 @@ const Main = () => {
if (response.status === 200) {
const data = response.data.data;
console.log(`${config.Host}/movie/?page=${page}&limit=${limit}&category=${category}`);
if (data.items.length === 0 && page > 1) {
// 如果返回的数据为空且请求的页码大于1则尝试获取上一页的数据
fetchMovies(page - 1);
@@ -93,11 +94,12 @@ const Main = () => {
return (
<Container style={{ marginTop: 20 }}>
<CategoryNav
<CategoryNav
categories={categories}
currentCategory={currentCategory}
onCategoryChange={handleCategoryChange}
/>
<div style={{ textAlign: 'center', marginBottom: 20 }}>
<Pagination
count={pagination.length}
@@ -108,9 +110,7 @@ const Main = () => {
size="large"
/>
</div>
<div>
{loading ? (
<div
@@ -124,9 +124,7 @@ const Main = () => {
<CircularProgress />
</div>
) : (
<Grid container spacing={2} style={{ marginTop: 3 }}>
{pagination.movies.map((item) => (
<Grid
@@ -149,9 +147,7 @@ const Main = () => {
</Grid>
)}
</div>
<div style={{ textAlign: 'center', marginTop: 20 }}>
<Pagination
count={pagination.length}

1
src/axiosConfig.js Normal file
View File

@@ -0,0 +1 @@

View File

@@ -3,12 +3,21 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter,Router, Routes, Route} from 'react-router-dom';
import LoginForm from './LoginForm';
import Main from './Main';
import VideoPlayer from './VideoPlayer'; // 导入我们将创建的VideoPlayer组件
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function