This commit is contained in:
HFO4 2020-02-21 15:14:35 +08:00
parent d6968cab07
commit 5ad86777f2
7 changed files with 352 additions and 29 deletions

View File

@ -14,7 +14,7 @@
"qrcode-react": "^0.1.16",
"react": "^16.12.0",
"react-addons-update": "^15.6.2",
"react-content-loader": "^4.3.2",
"react-content-loader": "^5.0.2",
"react-dnd": "^9.5.1",
"react-dnd-html5-backend": "^9.5.1",
"react-dom": "^16.12.0",

View File

@ -11,6 +11,7 @@ import { CssBaseline, makeStyles, ThemeProvider } from "@material-ui/core";
import PageLoading from "./component/Placeholder/PageLoading.js";
import {changeThemeColor} from "./untils";
import NotFound from "./component/Share/NotFound";
import NoAuthRoute from "./middleware/NoAuthRoute";
// Lazy loads
const LoginForm = React.lazy(() => import("./component/Login/LoginForm"));
@ -31,6 +32,7 @@ const Tasks = React.lazy(() => import("./component/Setting/Tasks"));
const Profile = React.lazy(() => import("./component/Setting/Profile"));
const UserSetting = React.lazy(() => import("./component/Setting/UserSetting"));
const QQCallback = React.lazy(() => import("./component/Login/QQ"));
const Register = React.lazy(() => import("./component/Login/Register"));
export default function App() {
const themeConfig = useSelector(state => state.siteConfig.theme);
@ -176,11 +178,17 @@ export default function App() {
</Suspense>
</AuthRoute>
<Route path={`${path}login`} exact>
<NoAuthRoute path={`${path}login`} exact>
<Suspense fallback={<PageLoading />}>
<LoginForm />
</Suspense>
</Route>
</NoAuthRoute>
<NoAuthRoute path={`${path}signup`} exact>
<Suspense fallback={<PageLoading />}>
<Register />
</Suspense>
</NoAuthRoute>
<Route path={`${path}login/qq`}>
<Suspense fallback={<PageLoading />}>

View File

@ -412,7 +412,7 @@ function LoginForm() {
<Link href={"/Member/FindPwd"}>忘记密码</Link>
</div>
<div>
<Link href={"/SignUp"}>注册账号</Link>
<Link href={"/#/signup"}>注册账号</Link>
</div>
</div>
</Paper>

View File

@ -0,0 +1,286 @@
import React, { useCallback, useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import RegIcon from '@material-ui/icons/AssignmentIndOutlined';
import { makeStyles } from "@material-ui/core";
import {
toggleSnackbar,
} from "../../actions/index";
import Placeholder from "../Placeholder/Captcha";
import { useHistory } from "react-router-dom";
import API from "../../middleware/Api";
import Auth from "../../middleware/Auth";
import {
Button,
FormControl,
Divider,
Link,
Input,
InputLabel,
Paper,
Avatar,
Typography
} from "@material-ui/core";
import EmailIcon from "@material-ui/icons/EmailOutlined";
const useStyles = makeStyles(theme => ({
layout: {
width: "auto",
marginTop: "110px",
marginLeft: theme.spacing(3),
marginRight: theme.spacing(3),
[theme.breakpoints.up("sm")]: {
width: 400,
marginLeft: "auto",
marginRight: "auto"
},
marginBottom: 110
},
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center",
padding: `${theme.spacing(2)}px ${theme.spacing(3)}px ${theme.spacing(
3
)}px`
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(1)
},
submit: {
marginTop: theme.spacing(3)
},
link: {
marginTop: "20px",
display: "flex",
width: "100%",
justifyContent: "space-between"
},
captchaContainer: {
display: "flex",
marginTop: "10px"
},
captchaPlaceholder: {
width: 200
},
buttonContainer: {
display: "flex"
},
authnLink: {
textAlign: "center",
marginTop: 16
},
avatarSuccess:{
margin: theme.spacing(1),
backgroundColor: theme.palette.primary.main,
},
}));
function Register() {
const [input,setInput] = useState({
"email":"",
"password":"",
"password_repeat":"",
"captcha":"",
});
const [loading, setLoading] = useState(false);
const [emailActive, setEmailActive] = useState(false);
const [captchaData, setCaptchaData] = useState(null);
const title = useSelector(state => state.siteConfig.title);
const regCaptcha = useSelector(state => state.siteConfig.regCaptcha);
const dispatch = useDispatch();
const ToggleSnackbar = useCallback(
(vertical, horizontal, msg, color) =>
dispatch(toggleSnackbar(vertical, horizontal, msg, color)),
[dispatch]
);
const history = useHistory();
const handleInputChange = name => e => {
setInput({
...input,
[name]:e.target.value
})
}
const classes = useStyles();
const refreshCaptcha = () => {
API.get("/site/captcha")
.then(response => {
setCaptchaData(response.data);
})
.catch(error => {
ToggleSnackbar(
"top",
"right",
"无法加载验证码:" + error.message,
"error"
);
});
};
const register = e =>{
e.preventDefault();
if (input.password !== input.password_repeat){
ToggleSnackbar("top", "right", "两次密码输入不一致", "warning");
}
setLoading(true);
API.post("/user", {
userName: input.email,
Password: input.password,
captchaCode: input.captcha
})
.then(response => {
setLoading(false);
if (response.rawData.code === 203){
setEmailActive(true);
}else{
history.push("/login?username="+input.email)
ToggleSnackbar("top", "right", "注册成功", "success");
}
})
.catch(error => {
setLoading(false);
ToggleSnackbar("top", "right", error.message, "warning");
refreshCaptcha();
});
}
useEffect(() => {
if (regCaptcha) {
refreshCaptcha();
}
}, []);
return (
<div className={classes.layout}>
<>
{!emailActive && <Paper className={classes.paper}>
<Avatar className={classes.avatar}>
<RegIcon />
</Avatar>
<Typography component="h1" variant="h5">
注册 {title}
</Typography>
<form className={classes.form} onSubmit={register}>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="email">电子邮箱</InputLabel>
<Input
id="email"
type="email"
name="email"
onChange={handleInputChange("email")}
autoComplete
value={input.email}
autoFocus
/>
</FormControl>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="password">密码</InputLabel>
<Input
name="password"
onChange={handleInputChange("password")}
type="password"
id="password"
value={input.password}
autoComplete
/>
</FormControl>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="password">密码</InputLabel>
<Input
name="pwdRepeat"
onChange={handleInputChange("password_repeat")}
type="password"
id="pwdRepeat"
value={input.password_repeat}
autoComplete />
</FormControl>
{regCaptcha && (
<div className={classes.captchaContainer}>
<FormControl margin="normal" required fullWidth>
<InputLabel htmlFor="captcha">
验证码
</InputLabel>
<Input
name="captcha"
onChange={handleInputChange("captcha")}
type="text"
id="captcha"
value={input.captcha}
autoComplete
/>
</FormControl>{" "}
<div>
{captchaData === null && (
<div
className={
classes.captchaPlaceholder
}
>
<Placeholder />
</div>
)}
{captchaData !== null && (
<img
src={captchaData}
alt="captcha"
onClick={refreshCaptcha}
/>
)}
</div>
</div>
)}
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
disabled={loading}
className={classes.submit}
>
注册账号
</Button>
</form>
<Divider />
<div className={classes.link}>
<div>
<Link href={"/#/login"}>返回登录</Link>
</div>
<div>
<Link href={"/SignUp"}>忘记密码</Link>
</div>
</div>
</Paper>}
{emailActive &&
<Paper className={classes.paper}>
<Avatar className={classes.avatarSuccess}>
<EmailIcon />
</Avatar>
<Typography component="h1" variant="h5">
邮件激活
</Typography>
<Typography style={{marginTop:"10px"}}>一封激活邮件已经发送至您的邮箱请访问邮件中的链接以继续完成注册</Typography>
</Paper>
}
</>
</div>
);
}
export default Register;

View File

@ -1,35 +1,36 @@
import React from "react"
import ContentLoader, { Facebook } from "react-content-loader"
import {makeStyles} from "@material-ui/core/styles";
import React from "react";
import ContentLoader, { Facebook } from "react-content-loader";
import { makeStyles, useTheme } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
loader:{
width:"80%",
loader: {
width: "80%",
[theme.breakpoints.up("md")]: {
width:" 50%",
width: " 50%"
},
marginTop:30,
},
marginTop: 30
}
}));
const MyLoader = props => {
return (
<Facebook className={props.className} />
);
};
const MyLoader = (props) => (
<Facebook className={props.className}/>
)
function PageLoading (){
function PageLoading() {
const classes = useStyles();
return (
<div style={{
textAlign:"center",
}}>
<MyLoader className={classes.loader}/>
<div
style={{
textAlign: "center"
}}
>
<MyLoader className={classes.loader} />
</div>
)
);
}
export default PageLoading
export default PageLoading;

View File

@ -0,0 +1,28 @@
import React from "react";
import Auth from "./Auth"
import {
Route,
Redirect,
} from "react-router-dom";
function NoAuthRoute({ children, ...rest }) {
return (
<Route
{...rest}
render={({ location }) =>
!Auth.Check(rest.isLogin) ? (
children
) : (
<Redirect
to={{
pathname: "/home",
state: { from: location }
}}
/>
)
}
/>
);
}
export default NoAuthRoute

View File

@ -8557,10 +8557,10 @@ react-app-polyfill@^1.0.4:
regenerator-runtime "0.13.3"
whatwg-fetch "3.0.0"
react-content-loader@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-4.3.2.tgz#2f6546c883707d399a2abc2efd00edcb8f584618"
integrity sha512-Af2RW2G57+mFRXsiSXROtgvz3KmPz0lATRHNUpJ57DyVw6SRzDRNRXo04I2xhcwmwVnXsfx4s2hsHrU+Lq5jRw==
react-content-loader@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-5.0.2.tgz#f4d417ac2b3a913a4b5e406b8b36ff724bcfe15b"
integrity sha512-d9+/FX640VXyO+9dBgMWaHD5IL0+tGsCAFBhYPGNziPx2abTMUBXL1+oIlenOTYlxuOWDcUcpmgjj4Ws+0xdhA==
react-dev-utils@^9.1.0:
version "9.1.0"