Compare commits

...

4 Commits
master ... dev

Author SHA1 Message Date
MYW 5c67f4efbb project 2 years ago
MYW aed87f4e7d project 2 years ago
MYW 2583502638 project 2 years ago
MYW 511fe85959 project 2 years ago
  1. 6
      .babelrc
  2. 1
      .gitignore
  3. 11
      index.html
  4. 11556
      package-lock.json
  5. 41
      package.json
  6. 12
      src/App.js
  7. 16
      src/components/button/Button.js
  8. 5
      src/components/index.js
  9. 49
      src/components/input/EmailInput.js
  10. 51
      src/components/input/PasswdInput.js
  11. 10
      src/index.js
  12. 11
      src/pages/layouts/Layouts.js
  13. 41
      src/pages/login/Login.js
  14. 24
      src/router/index.js
  15. 12
      src/router/routes.js
  16. 22
      src/store/LoginStore.js
  17. 51
      src/styles/index.css
  18. 59
      src/styles/index.less
  19. 25
      src/utils/http.js
  20. 18
      src/utils/token.js
  21. 40
      webpack.config.js

6
.babelrc

@ -0,0 +1,6 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}

1
.gitignore

@ -0,0 +1 @@
node_modules

11
index.html

@ -0,0 +1,11 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

11556
package-lock.json
File diff suppressed because it is too large
View File

41
package.json

@ -0,0 +1,41 @@
{
"name": "react-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack server --open --mode development",
"build": "webpack --mode production"
},
"repository": {
"type": "git",
"url": "https://git.deepdev.pro/MYW/react-project.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.27.2",
"mobx": "^6.6.1",
"mobx-react-lite": "^3.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0",
"uuid": "^8.3.2"
},
"devDependencies": {
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"html-loader": "^4.1.0",
"html-webpack-plugin": "^5.5.0",
"less": "^4.1.3",
"style-loader": "^3.3.1",
"typescript": "^4.7.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.10.0"
}
}

12
src/App.js

@ -0,0 +1,12 @@
import React from 'react';
import Router from './router/index';
function App() {
return (
<div className="App">
<Router />
</div>
);
}
export default App;

16
src/components/button/Button.js

@ -0,0 +1,16 @@
import React from "react";
function LoginButton (props) {
const { onSubmit } = props
return(
<button
className="submit"
type="submit"
onClick={() => onSubmit()}
>提交</button>
)
}
export default LoginButton

5
src/components/index.js

@ -0,0 +1,5 @@
import EmailInput from "./input/EmailInput";
import PasswdInput from "./input/PasswdInput";
import LoginButton from "./button/Button";
export { EmailInput, LoginButton, PasswdInput}

49
src/components/input/EmailInput.js

@ -0,0 +1,49 @@
import React, { useState } from 'react';
const EmailInput = (props) => {
const { onChange } = props;
const [value, setValue] = useState('');
const [EmailMessage, setEmailMessage] = useState('');
const EmailInputChange = e => {
setValue(e.target.value);
if (judge() && onChange) {
onChange(e.target.value);
}
};
const judge = () => {
const rules = /^[-_A-Za-z0-9]+@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,3}$/;
if (rules.test(value)) {
setEmailMessage('');
return true;
} else {
setEmailMessage('请输入正确邮箱');
}
return false;
};
const EmailInputOnBlur = () => {
judge();
};
return (
<div>
<input
className='email'
type="text"
placeholder="请输入邮箱"
value={value}
onChange={e => EmailInputChange(e)}
onBlur={EmailInputOnBlur}
/>
<p
>{EmailMessage}</p>
</div>
);
};
export default EmailInput;

51
src/components/input/PasswdInput.js

@ -0,0 +1,51 @@
import React, { useState } from "react";
const PasswdInput = (props) => {
const {onChange} = props
const [value, setValue] = useState('')
const [passwdMessage, setpasswdMessage] = useState('')
const PasswdInputChange = (e) => {
setValue(e.target.value)
if( Judge() && onChange ){
onChange(e.target.value);
}
}
const Judge = () => {
const rules = /^[\w_-]{6,16}$/
if(rules.test(value)) {
setpasswdMessage('')
return true
} else {
setpasswdMessage('请输入6~16位的密码')
return false
}
}
const PasswdInputOnBlur = () => {
Judge()
};
return (
<div>
<input
className="passwd"
type="text"
placeholder="请输入密码"
value={value}
onChange={e => PasswdInputChange(e)}
onBlur={PasswdInputOnBlur}
/>
<p
>{passwdMessage}</p>
</div>
)
}
export default PasswdInput

10
src/index.js

@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App'
import './styles/index.css'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<App />
)

11
src/pages/layouts/Layouts.js

@ -0,0 +1,11 @@
import React from "react";
function Layouts ({children}) {
return (
<>
<div className="page_container">{children}</div>
</>
)
}
export default Layouts

41
src/pages/login/Login.js

@ -0,0 +1,41 @@
import React, { useState } from "react"
import { EmailInput, LoginButton, PasswdInput } from '../../components/index'
import loginStore from '../../store/LoginStore'
import { observer } from 'mobx-react-lite'
import Layouts from "../layouts/Layouts"
function Login() {
const [email, setEmail] = useState('')
const [passwd, setPasswd] = useState('')
const onSubmit = async (emailValue, passwdValue) => {
if (email === '' || passwd === '') {
alert('请输入密码或账号')
} else {
await loginStore.getToken({ email: emailValue, password: passwdValue, recaptcha: 'shoa-P8fe1pho<u4' })
}
}
return (
<Layouts>
<div className="login_container">
<h1 className="header">登入</h1>
<p className="text">邮箱</p>
<EmailInput
onChange={(value) => { setEmail(value) }}
></EmailInput>
<p className="text">密码</p>
<PasswdInput
onChange={(value) => { setPasswd(value) }}
></PasswdInput>
<LoginButton onSubmit={() => onSubmit(email, passwd)}></LoginButton>
</div>
</Layouts>
)
}
export default observer(Login)

24
src/router/index.js

@ -0,0 +1,24 @@
import React from 'react';
import routes from "./routes";
import { BrowserRouter, Route, Routes } from "react-router-dom";
function router() {
return (
<BrowserRouter>
<Routes>
{routes.map((item) => {
return (
<Route
key={item.id}
path={item.path}
element={<item.component/>}
/>
);
})}
</Routes>
</BrowserRouter>
);
}
export default router;

12
src/router/routes.js

@ -0,0 +1,12 @@
import { lazy } from "react"
import { v4 as uuid} from 'uuid'
const routers = [
{
id: uuid(),
path: '/login',
component: lazy(() => import('../pages/login/Login'))
}
]
export default routers

22
src/store/LoginStore.js

@ -0,0 +1,22 @@
import http from '../utils/http'
import { makeAutoObservable } from 'mobx'
import { setToken, getToken } from '../utils/token'
class LoginStore {
token = getToken() || ''
constructor() {
makeAutoObservable(this)
}
getToken = async ({ email, password, recaptcha }) => {
const res = await http.post('/user/login', { email, password, recaptcha })
console.log(res.data)
this.token = res.data.accessToken
setToken(this.token)
}
}
const loginStore = new LoginStore()
export default loginStore

51
src/styles/index.css

@ -0,0 +1,51 @@
* {
margin: 0;
padding: 0;
}
body {
background-color: #F5F5F5;
}
.page_container {
position: relative;
width: 80%;
height: 100%;
margin: 0 auto;
background-color: #FFFFFF;
}
.login_container {
display: flex;
width: 500px;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
left: 50%;
top: 20%;
transform: translate(-50%, -50%);
}
.header {
font-weight: 400;
margin-bottom: 30px;
}
.text {
margin-left: -265px;
}
.email,
.passwd,
.submit {
width: 300px;
height: 30px;
border: none;
border-radius: 5px;
}
.email,
.passwd {
background-color: #F5F5F5;
margin-bottom: 20px;
}
.submit {
width: 300px;
margin-top: 10px;
color: #FFFFFF;
background-color: #00BFFF;
}

59
src/styles/index.less

@ -0,0 +1,59 @@
* {
margin: 0;
padding: 0;
}
body {
background-color: #F5F5F5;
}
.page_container {
position: relative;
width: 80%;
height: 100%;
margin: 0 auto;
background-color: #FFFFFF;
}
.login_container {
display: flex;
width: 500px;
flex-direction: column;
justify-content: center;
align-items: center;
position: absolute;
left: 50%;
top: 20%;
transform: translate(-50%, -50%);
}
.header {
font-weight: 400;
margin-bottom: 30px;
}
.text {
margin-left: -265px;
}
.email,
.passwd,
.submit {
width: 300px;
height: 30px;
border: none;
border-radius: 5px;
}
.email,
.passwd {
background-color: #F5F5F5;
margin-bottom: 20px;
}
.submit {
width: 300px;
margin-top: 10px;
color: #FFFFFF;
background-color: #00BFFF;
}

25
src/utils/http.js

@ -0,0 +1,25 @@
import axios from "axios";
const http = axios.create({
baseURL: 'http://mobie.api.test.com',
timeout: 5000,
})
// 添加请求拦截器
http.interceptors.request.use(function (config) {
return config;
}, function (error) {
return Promise.reject(error);
});
// 添加响应拦截器
http.interceptors.response.use(function (response) {
return response.data;
}, function (error) {
if(error.response.status === 422) {
alert('邮箱或者密码错误')
}
return Promise.reject(error);
});
export default http

18
src/utils/token.js

@ -0,0 +1,18 @@
// 封装 localStorage 存取 token
const key = 'pc-key'
// 存取 token
const setToken = (token) => {
return window.localStorage.setItem(key, token)
}
// 获取 token
const getToken = () => {
return window.localStorage.getItem(key)
}
export {
setToken,
getToken
}

40
webpack.config.js

@ -0,0 +1,40 @@
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
},
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./index.html",
filename: "./index.html"
})
],
devServer: {
historyApiFallback: true
}
};
Loading…
Cancel
Save