RegisterForm.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import React, { useEffect, useState } from 'react';
  2. import {
  3. Button,
  4. Form,
  5. Grid,
  6. Header,
  7. Image,
  8. Message,
  9. Segment,
  10. } from 'semantic-ui-react';
  11. import { Link, useNavigate } from 'react-router-dom';
  12. import { API, showError, showInfo, showSuccess } from '../helpers';
  13. import Turnstile from 'react-turnstile';
  14. const RegisterForm = () => {
  15. const [inputs, setInputs] = useState({
  16. username: '',
  17. password: '',
  18. password2: '',
  19. email: '',
  20. verification_code: '',
  21. });
  22. const { username, password, password2 } = inputs;
  23. const [showEmailVerification, setShowEmailVerification] = useState(false);
  24. const [turnstileEnabled, setTurnstileEnabled] = useState(false);
  25. const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
  26. const [turnstileToken, setTurnstileToken] = useState('');
  27. const [loading, setLoading] = useState(false);
  28. useEffect(() => {
  29. let status = localStorage.getItem('status');
  30. if (status) {
  31. status = JSON.parse(status);
  32. setShowEmailVerification(status.email_verification);
  33. if (status.turnstile_check) {
  34. setTurnstileEnabled(true);
  35. setTurnstileSiteKey(status.turnstile_site_key);
  36. }
  37. }
  38. });
  39. let navigate = useNavigate();
  40. function handleChange(e) {
  41. const { name, value } = e.target;
  42. console.log(name, value);
  43. setInputs((inputs) => ({ ...inputs, [name]: value }));
  44. }
  45. async function handleSubmit(e) {
  46. if (password.length < 8) {
  47. showInfo('密码长度不得小于 8 位!');
  48. return;
  49. }
  50. if (password !== password2) {
  51. showInfo('两次输入的密码不一致');
  52. return;
  53. }
  54. if (username && password) {
  55. if (turnstileEnabled && turnstileToken === '') {
  56. showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
  57. return;
  58. }
  59. setLoading(true);
  60. const res = await API.post(
  61. `/api/user/register?turnstile=${turnstileToken}`,
  62. inputs
  63. );
  64. const { success, message } = res.data;
  65. if (success) {
  66. navigate('/login');
  67. showSuccess('注册成功!');
  68. } else {
  69. showError(message);
  70. }
  71. setLoading(false);
  72. }
  73. }
  74. const sendVerificationCode = async () => {
  75. if (inputs.email === '') return;
  76. if (turnstileEnabled && turnstileToken === '') {
  77. showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
  78. return;
  79. }
  80. setLoading(true);
  81. const res = await API.get(
  82. `/api/verification?email=${inputs.email}&turnstile=${turnstileToken}`
  83. );
  84. const { success, message } = res.data;
  85. if (success) {
  86. showSuccess('验证码发送成功,请检查你的邮箱!');
  87. } else {
  88. showError(message);
  89. }
  90. setLoading(false);
  91. };
  92. return (
  93. <Grid textAlign='center' style={{ marginTop: '48px' }}>
  94. <Grid.Column style={{ maxWidth: 450 }}>
  95. <Header as='h2' color='teal' textAlign='center'>
  96. <Image src='/logo.png' /> 新用户注册
  97. </Header>
  98. <Form size='large'>
  99. <Segment>
  100. <Form.Input
  101. fluid
  102. icon='user'
  103. iconPosition='left'
  104. placeholder='输入用户名,最长 12 位'
  105. onChange={handleChange}
  106. name='username'
  107. />
  108. <Form.Input
  109. fluid
  110. icon='lock'
  111. iconPosition='left'
  112. placeholder='输入密码,最短 8 位,最长 20 位'
  113. onChange={handleChange}
  114. name='password'
  115. type='password'
  116. />
  117. <Form.Input
  118. fluid
  119. icon='lock'
  120. iconPosition='left'
  121. placeholder='输入密码,最短 8 位,最长 20 位'
  122. onChange={handleChange}
  123. name='password2'
  124. type='password'
  125. />
  126. {showEmailVerification ? (
  127. <>
  128. <Form.Input
  129. fluid
  130. icon='mail'
  131. iconPosition='left'
  132. placeholder='输入邮箱地址'
  133. onChange={handleChange}
  134. name='email'
  135. type='email'
  136. action={
  137. <Button onClick={sendVerificationCode} disabled={loading}>
  138. 获取验证码
  139. </Button>
  140. }
  141. />
  142. <Form.Input
  143. fluid
  144. icon='lock'
  145. iconPosition='left'
  146. placeholder='输入验证码'
  147. onChange={handleChange}
  148. name='verification_code'
  149. />
  150. </>
  151. ) : (
  152. <></>
  153. )}
  154. {turnstileEnabled ? (
  155. <Turnstile
  156. sitekey={turnstileSiteKey}
  157. onVerify={(token) => {
  158. setTurnstileToken(token);
  159. }}
  160. />
  161. ) : (
  162. <></>
  163. )}
  164. <Button
  165. color='teal'
  166. fluid
  167. size='large'
  168. onClick={handleSubmit}
  169. loading={loading}
  170. >
  171. 注册
  172. </Button>
  173. </Segment>
  174. </Form>
  175. <Message>
  176. 已有账户?
  177. <Link to='/login' className='btn btn-link'>
  178. 点击登录
  179. </Link>
  180. </Message>
  181. </Grid.Column>
  182. </Grid>
  183. );
  184. };
  185. export default RegisterForm;