SignUp.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { useIntl } from "react-intl";
  2. import {
  3. ProForm,
  4. ProFormDependency,
  5. ProFormInstance,
  6. ProFormText,
  7. } from "@ant-design/pro-components";
  8. import { Button, message, Modal, Result } from "antd";
  9. import { useNavigate } from "react-router-dom";
  10. import { EyeInvisibleOutlined, EyeTwoTone } from "@ant-design/icons";
  11. import { get, post } from "../../../request";
  12. import LangSelect from "../../general/LangSelect";
  13. import { useRef, useState } from "react";
  14. import {
  15. IInviteResponse,
  16. ISignInResponse,
  17. ISignUpRequest,
  18. } from "../../api/Auth";
  19. interface IFormData {
  20. email: string;
  21. username: string;
  22. nickname: string;
  23. password: string;
  24. password2: string;
  25. lang: string;
  26. }
  27. interface IWidget {
  28. token?: string;
  29. }
  30. const SignUpWidget = ({ token }: IWidget) => {
  31. const intl = useIntl();
  32. const navigate = useNavigate();
  33. const [success, setSuccess] = useState(false);
  34. const [nickname, setNickname] = useState<string>();
  35. const formRef = useRef<ProFormInstance>();
  36. return success ? (
  37. <Result
  38. status="success"
  39. title="注册成功"
  40. subTitle={
  41. <Button
  42. type="primary"
  43. onClick={() => navigate("/anonymous/users/sign-in")}
  44. >
  45. {intl.formatMessage({
  46. id: "nut.users.sign-up.title",
  47. })}
  48. </Button>
  49. }
  50. />
  51. ) : (
  52. <ProForm<IFormData>
  53. formRef={formRef}
  54. onFinish={async (values: IFormData) => {
  55. if (typeof token === "undefined") {
  56. return;
  57. }
  58. if (values.password !== values.password2) {
  59. Modal.error({ title: "两次密码不同" });
  60. return;
  61. }
  62. const user = {
  63. token: token,
  64. username: values.username,
  65. nickname: values.nickname ? values.nickname : values.username,
  66. email: values.email,
  67. password: values.password,
  68. lang: values.lang,
  69. };
  70. const signUp = await post<ISignUpRequest, ISignInResponse>(
  71. "/v2/sign-up",
  72. user
  73. );
  74. if (signUp.ok) {
  75. setSuccess(true);
  76. } else {
  77. message.error(signUp.message);
  78. }
  79. }}
  80. request={async () => {
  81. const url = `/v2/invite/${token}`;
  82. console.info("api request", url);
  83. const res = await get<IInviteResponse>(url);
  84. console.debug("api response", res.data);
  85. return {
  86. id: res.data.id,
  87. username: "",
  88. nickname: "",
  89. password: "",
  90. password2: "",
  91. email: res.data.email,
  92. lang: "zh-Hans",
  93. };
  94. }}
  95. >
  96. <ProForm.Group>
  97. <ProFormText
  98. width="md"
  99. name="email"
  100. required
  101. label={intl.formatMessage({
  102. id: "forms.fields.email.label",
  103. })}
  104. rules={[{ required: true, max: 255, min: 4 }]}
  105. disabled
  106. />
  107. </ProForm.Group>
  108. <ProForm.Group>
  109. <ProFormText
  110. width="md"
  111. name="username"
  112. required
  113. fieldProps={{
  114. onChange: (event) => {
  115. setNickname(event.target.value);
  116. },
  117. }}
  118. label={intl.formatMessage({
  119. id: "forms.fields.username.label",
  120. })}
  121. rules={[
  122. { required: true, max: 32, min: 6 },
  123. {
  124. pattern: new RegExp("^[0-9a-zA-Z_]{1,}", "g"),
  125. message: "只允许数字,字母,下划线",
  126. },
  127. ]}
  128. />
  129. </ProForm.Group>
  130. <ProForm.Group>
  131. <ProFormText.Password
  132. width="md"
  133. name="password"
  134. fieldProps={{
  135. type: "password",
  136. iconRender: (visible) =>
  137. visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />,
  138. }}
  139. required
  140. label={intl.formatMessage({
  141. id: "forms.fields.password.label",
  142. })}
  143. rules={[{ required: true, max: 32, min: 6 }]}
  144. />
  145. </ProForm.Group>
  146. <ProForm.Group>
  147. <ProFormText.Password
  148. width="md"
  149. name="password2"
  150. fieldProps={{
  151. type: "password",
  152. iconRender: (visible) =>
  153. visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />,
  154. }}
  155. required
  156. label={intl.formatMessage({
  157. id: "forms.fields.confirm-password.label",
  158. })}
  159. rules={[{ required: true, max: 32, min: 6 }]}
  160. />
  161. </ProForm.Group>
  162. <ProForm.Group>
  163. <ProFormDependency name={["username"]}>
  164. {({ username }) => {
  165. return (
  166. <ProFormText
  167. width="md"
  168. fieldProps={{
  169. placeholder: username,
  170. value: nickname ? nickname : username,
  171. onChange: (event) => {
  172. setNickname(event.target.value);
  173. },
  174. }}
  175. name="nickname"
  176. required
  177. label={intl.formatMessage({
  178. id: "forms.fields.nickname.label",
  179. })}
  180. rules={[{ required: false, max: 32, min: 4 }]}
  181. />
  182. );
  183. }}
  184. </ProFormDependency>
  185. </ProForm.Group>
  186. <ProForm.Group>
  187. <LangSelect label="常用的译文语言" />
  188. </ProForm.Group>
  189. </ProForm>
  190. );
  191. };
  192. export default SignUpWidget;