动态菜单和动态路由的 antd pro

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. import React, { Component } from 'react';
  2. import { connect } from 'dva';
  3. import { routerRedux, Link } from 'dva/router';
  4. import { Form, Input, Button, Select, Row, Col, Popover, Progress } from 'antd';
  5. import styles from './Register.less';
  6. const FormItem = Form.Item;
  7. const { Option } = Select;
  8. const InputGroup = Input.Group;
  9. const passwordStatusMap = {
  10. ok: <div className={styles.success}>强度:强</div>,
  11. pass: <div className={styles.warning}>强度:中</div>,
  12. poor: <div className={styles.error}>强度:太短</div>,
  13. };
  14. const passwordProgressMap = {
  15. ok: 'success',
  16. pass: 'normal',
  17. poor: 'exception',
  18. };
  19. @connect(({ register, loading }) => ({
  20. register,
  21. submitting: loading.effects['register/submit'],
  22. }))
  23. @Form.create()
  24. export default class Register extends Component {
  25. state = {
  26. count: 0,
  27. confirmDirty: false,
  28. visible: false,
  29. help: '',
  30. prefix: '86',
  31. };
  32. componentWillReceiveProps(nextProps) {
  33. const account = this.props.form.getFieldValue('mail');
  34. if (nextProps.register.status === 'ok') {
  35. this.props.dispatch(
  36. routerRedux.push({
  37. pathname: '/user/register-result',
  38. state: {
  39. account,
  40. },
  41. })
  42. );
  43. }
  44. }
  45. componentWillUnmount() {
  46. clearInterval(this.interval);
  47. }
  48. onGetCaptcha = () => {
  49. let count = 59;
  50. this.setState({ count });
  51. this.interval = setInterval(() => {
  52. count -= 1;
  53. this.setState({ count });
  54. if (count === 0) {
  55. clearInterval(this.interval);
  56. }
  57. }, 1000);
  58. };
  59. getPasswordStatus = () => {
  60. const { form } = this.props;
  61. const value = form.getFieldValue('password');
  62. if (value && value.length > 9) {
  63. return 'ok';
  64. }
  65. if (value && value.length > 5) {
  66. return 'pass';
  67. }
  68. return 'poor';
  69. };
  70. handleSubmit = e => {
  71. e.preventDefault();
  72. this.props.form.validateFields({ force: true }, (err, values) => {
  73. if (!err) {
  74. this.props.dispatch({
  75. type: 'register/submit',
  76. payload: {
  77. ...values,
  78. prefix: this.state.prefix,
  79. },
  80. });
  81. }
  82. });
  83. };
  84. handleConfirmBlur = e => {
  85. const { value } = e.target;
  86. this.setState({ confirmDirty: this.state.confirmDirty || !!value });
  87. };
  88. checkConfirm = (rule, value, callback) => {
  89. const { form } = this.props;
  90. if (value && value !== form.getFieldValue('password')) {
  91. callback('两次输入的密码不匹配!');
  92. } else {
  93. callback();
  94. }
  95. };
  96. checkPassword = (rule, value, callback) => {
  97. if (!value) {
  98. this.setState({
  99. help: '请输入密码!',
  100. visible: !!value,
  101. });
  102. callback('error');
  103. } else {
  104. this.setState({
  105. help: '',
  106. });
  107. if (!this.state.visible) {
  108. this.setState({
  109. visible: !!value,
  110. });
  111. }
  112. if (value.length < 6) {
  113. callback('error');
  114. } else {
  115. const { form } = this.props;
  116. if (value && this.state.confirmDirty) {
  117. form.validateFields(['confirm'], { force: true });
  118. }
  119. callback();
  120. }
  121. }
  122. };
  123. changePrefix = value => {
  124. this.setState({
  125. prefix: value,
  126. });
  127. };
  128. renderPasswordProgress = () => {
  129. const { form } = this.props;
  130. const value = form.getFieldValue('password');
  131. const passwordStatus = this.getPasswordStatus();
  132. return value && value.length ? (
  133. <div className={styles[`progress-${passwordStatus}`]}>
  134. <Progress
  135. status={passwordProgressMap[passwordStatus]}
  136. className={styles.progress}
  137. strokeWidth={6}
  138. percent={value.length * 10 > 100 ? 100 : value.length * 10}
  139. showInfo={false}
  140. />
  141. </div>
  142. ) : null;
  143. };
  144. render() {
  145. const { form, submitting } = this.props;
  146. const { getFieldDecorator } = form;
  147. const { count, prefix } = this.state;
  148. return (
  149. <div className={styles.main}>
  150. <h3>注册</h3>
  151. <Form onSubmit={this.handleSubmit}>
  152. <FormItem>
  153. {getFieldDecorator('mail', {
  154. rules: [
  155. {
  156. required: true,
  157. message: '请输入邮箱地址!',
  158. },
  159. {
  160. type: 'email',
  161. message: '邮箱地址格式错误!',
  162. },
  163. ],
  164. })(<Input size="large" placeholder="邮箱" />)}
  165. </FormItem>
  166. <FormItem help={this.state.help}>
  167. <Popover
  168. content={
  169. <div style={{ padding: '4px 0' }}>
  170. {passwordStatusMap[this.getPasswordStatus()]}
  171. {this.renderPasswordProgress()}
  172. <div style={{ marginTop: 10 }}>
  173. 请至少输入 6 个字符。请不要使用容易被猜到的密码。
  174. </div>
  175. </div>
  176. }
  177. overlayStyle={{ width: 240 }}
  178. placement="right"
  179. visible={this.state.visible}
  180. >
  181. {getFieldDecorator('password', {
  182. rules: [
  183. {
  184. validator: this.checkPassword,
  185. },
  186. ],
  187. })(<Input size="large" type="password" placeholder="至少6位密码,区分大小写" />)}
  188. </Popover>
  189. </FormItem>
  190. <FormItem>
  191. {getFieldDecorator('confirm', {
  192. rules: [
  193. {
  194. required: true,
  195. message: '请确认密码!',
  196. },
  197. {
  198. validator: this.checkConfirm,
  199. },
  200. ],
  201. })(<Input size="large" type="password" placeholder="确认密码" />)}
  202. </FormItem>
  203. <FormItem>
  204. <InputGroup compact>
  205. <Select
  206. size="large"
  207. value={prefix}
  208. onChange={this.changePrefix}
  209. style={{ width: '20%' }}
  210. >
  211. <Option value="86">+86</Option>
  212. <Option value="87">+87</Option>
  213. </Select>
  214. {getFieldDecorator('mobile', {
  215. rules: [
  216. {
  217. required: true,
  218. message: '请输入手机号!',
  219. },
  220. {
  221. pattern: /^1\d{10}$/,
  222. message: '手机号格式错误!',
  223. },
  224. ],
  225. })(<Input size="large" style={{ width: '80%' }} placeholder="11位手机号" />)}
  226. </InputGroup>
  227. </FormItem>
  228. <FormItem>
  229. <Row gutter={8}>
  230. <Col span={16}>
  231. {getFieldDecorator('captcha', {
  232. rules: [
  233. {
  234. required: true,
  235. message: '请输入验证码!',
  236. },
  237. ],
  238. })(<Input size="large" placeholder="验证码" />)}
  239. </Col>
  240. <Col span={8}>
  241. <Button
  242. size="large"
  243. disabled={count}
  244. className={styles.getCaptcha}
  245. onClick={this.onGetCaptcha}
  246. >
  247. {count ? `${count} s` : '获取验证码'}
  248. </Button>
  249. </Col>
  250. </Row>
  251. </FormItem>
  252. <FormItem>
  253. <Button
  254. size="large"
  255. loading={submitting}
  256. className={styles.submit}
  257. type="primary"
  258. htmlType="submit"
  259. >
  260. 注册
  261. </Button>
  262. <Link className={styles.login} to="/user/login">
  263. 使用已有账户登录
  264. </Link>
  265. </FormItem>
  266. </Form>
  267. </div>
  268. );
  269. }
  270. }