RegisterForm.js 5.7 KB

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