LoginForm.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import React, { useContext, useEffect, useState } from 'react';
  2. import {
  3. Button,
  4. Divider,
  5. Form,
  6. Grid,
  7. Header,
  8. Image,
  9. Message,
  10. Modal,
  11. Segment,
  12. } from 'semantic-ui-react';
  13. import { Link, useNavigate, useSearchParams } from 'react-router-dom';
  14. import { UserContext } from '../context/User';
  15. import { API, getLogo, showError, showSuccess, showInfo } from '../helpers';
  16. const LoginForm = () => {
  17. const [inputs, setInputs] = useState({
  18. username: '',
  19. password: '',
  20. wechat_verification_code: '',
  21. });
  22. const [searchParams, setSearchParams] = useSearchParams();
  23. const [submitted, setSubmitted] = useState(false);
  24. const { username, password } = inputs;
  25. const [userState, userDispatch] = useContext(UserContext);
  26. let navigate = useNavigate();
  27. const [status, setStatus] = useState({});
  28. const logo = getLogo();
  29. useEffect(() => {
  30. if (searchParams.get("expired")) {
  31. showError('未登录或登录已过期,请重新登录!');
  32. }
  33. let status = localStorage.getItem('status');
  34. if (status) {
  35. status = JSON.parse(status);
  36. setStatus(status);
  37. }
  38. }, []);
  39. const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false);
  40. const onGitHubOAuthClicked = () => {
  41. window.open(
  42. `https://github.com/login/oauth/authorize?client_id=${status.github_client_id}&scope=user:email`
  43. );
  44. };
  45. const onWeChatLoginClicked = () => {
  46. setShowWeChatLoginModal(true);
  47. };
  48. const onSubmitWeChatVerificationCode = async () => {
  49. const res = await API.get(
  50. `/api/oauth/wechat?code=${inputs.wechat_verification_code}`
  51. );
  52. const { success, message, data } = res.data;
  53. if (success) {
  54. userDispatch({ type: 'login', payload: data });
  55. localStorage.setItem('user', JSON.stringify(data));
  56. navigate('/');
  57. showSuccess('登录成功!');
  58. setShowWeChatLoginModal(false);
  59. } else {
  60. showError(message);
  61. }
  62. };
  63. function handleChange(e) {
  64. const { name, value } = e.target;
  65. setInputs((inputs) => ({ ...inputs, [name]: value }));
  66. }
  67. async function handleSubmit(e) {
  68. setSubmitted(true);
  69. if (username && password) {
  70. const res = await API.post(`/api/user/login`, {
  71. username,
  72. password,
  73. });
  74. const { success, message, data } = res.data;
  75. if (success) {
  76. userDispatch({ type: 'login', payload: data });
  77. localStorage.setItem('user', JSON.stringify(data));
  78. navigate('/');
  79. showSuccess('登录成功!');
  80. } else {
  81. showError(message);
  82. }
  83. }
  84. }
  85. return (
  86. <Grid textAlign="center" style={{ marginTop: '48px' }}>
  87. <Grid.Column style={{ maxWidth: 450 }}>
  88. <Header as="h2" color="" textAlign="center">
  89. <Image src={logo} /> 用户登录
  90. </Header>
  91. <Form size="large">
  92. <Segment>
  93. <Form.Input
  94. fluid
  95. icon="user"
  96. iconPosition="left"
  97. placeholder="用户名"
  98. name="username"
  99. value={username}
  100. onChange={handleChange}
  101. />
  102. <Form.Input
  103. fluid
  104. icon="lock"
  105. iconPosition="left"
  106. placeholder="密码"
  107. name="password"
  108. type="password"
  109. value={password}
  110. onChange={handleChange}
  111. />
  112. <Button color="" fluid size="large" onClick={handleSubmit}>
  113. 登录
  114. </Button>
  115. </Segment>
  116. </Form>
  117. <Message>
  118. 忘记密码?
  119. <Link to="/reset" className="btn btn-link">
  120. 点击重置
  121. </Link>
  122. ; 没有账户?
  123. <Link to="/register" className="btn btn-link">
  124. 点击注册
  125. </Link>
  126. </Message>
  127. {status.github_oauth || status.wechat_login ? (
  128. <>
  129. <Divider horizontal>Or</Divider>
  130. {status.github_oauth ? (
  131. <Button
  132. circular
  133. color="black"
  134. icon="github"
  135. onClick={onGitHubOAuthClicked}
  136. />
  137. ) : (
  138. <></>
  139. )}
  140. {status.wechat_login ? (
  141. <Button
  142. circular
  143. color="green"
  144. icon="wechat"
  145. onClick={onWeChatLoginClicked}
  146. />
  147. ) : (
  148. <></>
  149. )}
  150. </>
  151. ) : (
  152. <></>
  153. )}
  154. <Modal
  155. onClose={() => setShowWeChatLoginModal(false)}
  156. onOpen={() => setShowWeChatLoginModal(true)}
  157. open={showWeChatLoginModal}
  158. size={'mini'}
  159. >
  160. <Modal.Content>
  161. <Modal.Description>
  162. <Image src={status.wechat_qrcode} fluid />
  163. <div style={{ textAlign: 'center' }}>
  164. <p>
  165. 微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)
  166. </p>
  167. </div>
  168. <Form size="large">
  169. <Form.Input
  170. fluid
  171. placeholder="验证码"
  172. name="wechat_verification_code"
  173. value={inputs.wechat_verification_code}
  174. onChange={handleChange}
  175. />
  176. <Button
  177. color=""
  178. fluid
  179. size="large"
  180. onClick={onSubmitWeChatVerificationCode}
  181. >
  182. 登录
  183. </Button>
  184. </Form>
  185. </Modal.Description>
  186. </Modal.Content>
  187. </Modal>
  188. </Grid.Column>
  189. </Grid>
  190. );
  191. };
  192. export default LoginForm;