Register.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. import React, { Component } from 'react';
  2. import { connect } from 'dva';
  3. import { formatMessage, FormattedMessage } from 'umi-plugin-react/locale';
  4. import Link from 'umi/link';
  5. import router from 'umi/router';
  6. import { Form, Input, Button, message, Select, Row, Col, Popover, Progress } from 'antd';
  7. import styles from './Register.less';
  8. const FormItem = Form.Item;
  9. const { Option } = Select;
  10. const InputGroup = Input.Group;
  11. const passwordStatusMap = {
  12. ok: (
  13. <div className={styles.success}>
  14. <FormattedMessage id="validation.password.strength.strong" />
  15. </div>
  16. ),
  17. pass: (
  18. <div className={styles.warning}>
  19. <FormattedMessage id="validation.password.strength.medium" />
  20. </div>
  21. ),
  22. poor: (
  23. <div className={styles.error}>
  24. <FormattedMessage id="validation.password.strength.short" />
  25. </div>
  26. ),
  27. };
  28. const passwordProgressMap = {
  29. ok: 'success',
  30. pass: 'normal',
  31. poor: 'exception',
  32. };
  33. @connect(({ register, loading }) => ({
  34. register,
  35. submitting: loading.effects['register/submit'],
  36. }))
  37. @Form.create()
  38. class Register extends Component {
  39. state = {
  40. count: 0,
  41. confirmDirty: false,
  42. visible: false,
  43. help: '',
  44. prefix: '86',
  45. };
  46. componentDidUpdate() {
  47. const { form, register } = this.props;
  48. const account = form.getFieldValue('mail');
  49. if (register.status === 'ok') {
  50. router.push({
  51. pathname: '/user/register-result',
  52. state: {
  53. account,
  54. },
  55. });
  56. }
  57. }
  58. componentWillUnmount() {
  59. clearInterval(this.interval);
  60. }
  61. onGetCaptcha = () => {
  62. let count = 59;
  63. this.setState({ count });
  64. this.interval = setInterval(() => {
  65. count -= 1;
  66. this.setState({ count });
  67. if (count === 0) {
  68. clearInterval(this.interval);
  69. }
  70. }, 1000);
  71. message.warning(formatMessage({ id: 'app.login.verification-code-warning' }));
  72. };
  73. getPasswordStatus = () => {
  74. const { form } = this.props;
  75. const value = form.getFieldValue('password');
  76. if (value && value.length > 9) {
  77. return 'ok';
  78. }
  79. if (value && value.length > 5) {
  80. return 'pass';
  81. }
  82. return 'poor';
  83. };
  84. handleSubmit = e => {
  85. e.preventDefault();
  86. const { form, dispatch } = this.props;
  87. form.validateFields({ force: true }, (err, values) => {
  88. if (!err) {
  89. const { prefix } = this.state;
  90. dispatch({
  91. type: 'register/submit',
  92. payload: {
  93. ...values,
  94. prefix,
  95. },
  96. });
  97. }
  98. });
  99. };
  100. handleConfirmBlur = e => {
  101. const { value } = e.target;
  102. const { confirmDirty } = this.state;
  103. this.setState({ confirmDirty: confirmDirty || !!value });
  104. };
  105. checkConfirm = (rule, value, callback) => {
  106. const { form } = this.props;
  107. if (value && value !== form.getFieldValue('password')) {
  108. callback(formatMessage({ id: 'validation.password.twice' }));
  109. } else {
  110. callback();
  111. }
  112. };
  113. checkPassword = (rule, value, callback) => {
  114. const { visible, confirmDirty } = this.state;
  115. if (!value) {
  116. this.setState({
  117. help: formatMessage({ id: 'validation.password.required' }),
  118. visible: !!value,
  119. });
  120. callback('error');
  121. } else {
  122. this.setState({
  123. help: '',
  124. });
  125. if (!visible) {
  126. this.setState({
  127. visible: !!value,
  128. });
  129. }
  130. if (value.length < 6) {
  131. callback('error');
  132. } else {
  133. const { form } = this.props;
  134. if (value && confirmDirty) {
  135. form.validateFields(['confirm'], { force: true });
  136. }
  137. callback();
  138. }
  139. }
  140. };
  141. changePrefix = value => {
  142. this.setState({
  143. prefix: value,
  144. });
  145. };
  146. renderPasswordProgress = () => {
  147. const { form } = this.props;
  148. const value = form.getFieldValue('password');
  149. const passwordStatus = this.getPasswordStatus();
  150. return value && value.length ? (
  151. <div className={styles[`progress-${passwordStatus}`]}>
  152. <Progress
  153. status={passwordProgressMap[passwordStatus]}
  154. className={styles.progress}
  155. strokeWidth={6}
  156. percent={value.length * 10 > 100 ? 100 : value.length * 10}
  157. showInfo={false}
  158. />
  159. </div>
  160. ) : null;
  161. };
  162. render() {
  163. const { form, submitting } = this.props;
  164. const { getFieldDecorator } = form;
  165. const { count, prefix, help, visible } = this.state;
  166. return (
  167. <div className={styles.main}>
  168. <h3>
  169. <FormattedMessage id="app.register.register" />
  170. </h3>
  171. <Form onSubmit={this.handleSubmit}>
  172. <FormItem>
  173. {getFieldDecorator('mail', {
  174. rules: [
  175. {
  176. required: true,
  177. message: formatMessage({ id: 'validation.email.required' }),
  178. },
  179. {
  180. type: 'email',
  181. message: formatMessage({ id: 'validation.email.wrong-format' }),
  182. },
  183. ],
  184. })(
  185. <Input size="large" placeholder={formatMessage({ id: 'form.email.placeholder' })} />
  186. )}
  187. </FormItem>
  188. <FormItem help={help}>
  189. <Popover
  190. getPopupContainer={node => node.parentNode}
  191. content={
  192. <div style={{ padding: '4px 0' }}>
  193. {passwordStatusMap[this.getPasswordStatus()]}
  194. {this.renderPasswordProgress()}
  195. <div style={{ marginTop: 10 }}>
  196. <FormattedMessage id="validation.password.strength.msg" />
  197. </div>
  198. </div>
  199. }
  200. overlayStyle={{ width: 240 }}
  201. placement="right"
  202. visible={visible}
  203. >
  204. {getFieldDecorator('password', {
  205. rules: [
  206. {
  207. validator: this.checkPassword,
  208. },
  209. ],
  210. })(
  211. <Input
  212. size="large"
  213. type="password"
  214. placeholder={formatMessage({ id: 'form.password.placeholder' })}
  215. />
  216. )}
  217. </Popover>
  218. </FormItem>
  219. <FormItem>
  220. {getFieldDecorator('confirm', {
  221. rules: [
  222. {
  223. required: true,
  224. message: formatMessage({ id: 'validation.confirm-password.required' }),
  225. },
  226. {
  227. validator: this.checkConfirm,
  228. },
  229. ],
  230. })(
  231. <Input
  232. size="large"
  233. type="password"
  234. placeholder={formatMessage({ id: 'form.confirm-password.placeholder' })}
  235. />
  236. )}
  237. </FormItem>
  238. <FormItem>
  239. <InputGroup compact>
  240. <Select
  241. size="large"
  242. value={prefix}
  243. onChange={this.changePrefix}
  244. style={{ width: '20%' }}
  245. >
  246. <Option value="86">+86</Option>
  247. <Option value="87">+87</Option>
  248. </Select>
  249. {getFieldDecorator('mobile', {
  250. rules: [
  251. {
  252. required: true,
  253. message: formatMessage({ id: 'validation.phone-number.required' }),
  254. },
  255. {
  256. pattern: /^\d{11}$/,
  257. message: formatMessage({ id: 'validation.phone-number.wrong-format' }),
  258. },
  259. ],
  260. })(
  261. <Input
  262. size="large"
  263. style={{ width: '80%' }}
  264. placeholder={formatMessage({ id: 'form.phone-number.placeholder' })}
  265. />
  266. )}
  267. </InputGroup>
  268. </FormItem>
  269. <FormItem>
  270. <Row gutter={8}>
  271. <Col span={16}>
  272. {getFieldDecorator('captcha', {
  273. rules: [
  274. {
  275. required: true,
  276. message: formatMessage({ id: 'validation.verification-code.required' }),
  277. },
  278. ],
  279. })(
  280. <Input
  281. size="large"
  282. placeholder={formatMessage({ id: 'form.verification-code.placeholder' })}
  283. />
  284. )}
  285. </Col>
  286. <Col span={8}>
  287. <Button
  288. size="large"
  289. disabled={count}
  290. className={styles.getCaptcha}
  291. onClick={this.onGetCaptcha}
  292. >
  293. {count
  294. ? `${count} s`
  295. : formatMessage({ id: 'app.register.get-verification-code' })}
  296. </Button>
  297. </Col>
  298. </Row>
  299. </FormItem>
  300. <FormItem>
  301. <Button
  302. size="large"
  303. loading={submitting}
  304. className={styles.submit}
  305. type="primary"
  306. htmlType="submit"
  307. >
  308. <FormattedMessage id="app.register.register" />
  309. </Button>
  310. <Link className={styles.login} to="/User/Login">
  311. <FormattedMessage id="app.register.sign-in" />
  312. </Link>
  313. </FormItem>
  314. </Form>
  315. </div>
  316. );
  317. }
  318. }
  319. export default Register;