RegisterForm.js 5.7 KB

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