正在显示
16 个修改的文件
包含
147 行增加
和
654 行删除
1 | 1 | export default { |
2 | 2 | plugins: [ |
3 | - ['umi-plugin-block-dev', {}], | |
4 | - ['umi-plugin-react', { | |
5 | - dva: true, | |
6 | - locale: true, | |
7 | - antd: true, | |
8 | - }] | |
3 | + [ | |
4 | + 'umi-plugin-block-dev', | |
5 | + { | |
6 | + layout: 'ant-design-pro-user', | |
7 | + }, | |
8 | + ], | |
9 | + [ | |
10 | + 'umi-plugin-react', | |
11 | + { | |
12 | + dva: true, | |
13 | + locale: true, | |
14 | + antd: true, | |
15 | + }, | |
16 | + ], | |
9 | 17 | ], |
10 | -} | |
18 | +}; | ... | ... |
1 | -import React, { PureComponent } from 'react'; | |
2 | -import { Dropdown } from 'antd'; | |
3 | -import classNames from 'classnames'; | |
4 | -import styles from './index.less'; | |
5 | - | |
6 | -export default class HeaderDropdown extends PureComponent { | |
7 | - render() { | |
8 | - const { overlayClassName, ...props } = this.props; | |
9 | - return ( | |
10 | - <Dropdown overlayClassName={classNames(styles.container, overlayClassName)} {...props} /> | |
11 | - ); | |
12 | - } | |
13 | -} |
1 | -@import '~antd/lib/style/themes/default.less'; | |
2 | - | |
3 | -.container > *:global(:not(.ant-dropdown-menu)) { | |
4 | - background-color: #fff; | |
5 | - box-shadow: @shadow-1-down; | |
6 | - border-radius: 4px; | |
7 | -} | |
8 | - | |
9 | -@media screen and (max-width: @screen-xs) { | |
10 | - .container { | |
11 | - width: 100% !important; | |
12 | - } | |
13 | - .container > * { | |
14 | - border-radius: 0 !important; | |
15 | - } | |
16 | -} |
1 | -import React, { PureComponent } from 'react'; | |
2 | -import { formatMessage, setLocale, getLocale } from 'umi/locale'; | |
3 | -import { Menu, Icon } from 'antd'; | |
4 | -import classNames from 'classnames'; | |
5 | -import HeaderDropdown from '../HeaderDropdown'; | |
6 | -import styles from './index.less'; | |
7 | - | |
8 | -export default class SelectLang extends PureComponent { | |
9 | - changeLang = ({ key }) => { | |
10 | - setLocale(key); | |
11 | - }; | |
12 | - | |
13 | - render() { | |
14 | - const { className } = this.props; | |
15 | - const selectedLang = getLocale(); | |
16 | - const langMenu = ( | |
17 | - <Menu className={styles.menu} selectedKeys={[selectedLang]} onClick={this.changeLang}> | |
18 | - <Menu.Item key="zh-CN"> | |
19 | - <span role="img" aria-label="简体中文"> | |
20 | - 🇨🇳 | |
21 | - </span>{' '} | |
22 | - 简体中文 | |
23 | - </Menu.Item> | |
24 | - <Menu.Item key="zh-TW"> | |
25 | - <span role="img" aria-label="繁体中文"> | |
26 | - 🇭🇰 | |
27 | - </span>{' '} | |
28 | - 繁体中文 | |
29 | - </Menu.Item> | |
30 | - <Menu.Item key="en-US"> | |
31 | - <span role="img" aria-label="English"> | |
32 | - 🇬🇧 | |
33 | - </span>{' '} | |
34 | - English | |
35 | - </Menu.Item> | |
36 | - <Menu.Item key="pt-BR"> | |
37 | - <span role="img" aria-label="Português"> | |
38 | - 🇵🇹 | |
39 | - </span>{' '} | |
40 | - Português | |
41 | - </Menu.Item> | |
42 | - </Menu> | |
43 | - ); | |
44 | - return ( | |
45 | - <HeaderDropdown overlay={langMenu} placement="bottomRight"> | |
46 | - <span className={classNames(styles.dropDown, className)}> | |
47 | - <Icon type="global" title={formatMessage({ id: 'navBar.lang' })} /> | |
48 | - </span> | |
49 | - </HeaderDropdown> | |
50 | - ); | |
51 | - } | |
52 | -} |
1 | -@import '~antd/lib/style/themes/default.less'; | |
2 | - | |
3 | -.menu { | |
4 | - :global(.anticon) { | |
5 | - margin-right: 8px; | |
6 | - } | |
7 | - :global(.ant-dropdown-menu-item) { | |
8 | - min-width: 160px; | |
9 | - } | |
10 | -} | |
11 | - | |
12 | -.dropDown { | |
13 | - cursor: pointer; | |
14 | - vertical-align: top; | |
15 | - line-height: @layout-header-height; | |
16 | - > i { | |
17 | - font-size: 14px !important; | |
18 | - transform: none !important; | |
19 | - svg { | |
20 | - position: relative; | |
21 | - top: -1px; | |
22 | - } | |
23 | - } | |
24 | -} |
1 | -import React, { Fragment } from 'react'; | |
2 | -import { formatMessage } from 'umi/locale'; | |
3 | -import Link from 'umi/link'; | |
4 | -import { Icon } from 'antd'; | |
5 | -import { GlobalFooter } from 'ant-design-pro'; | |
6 | -import SelectLang from '../SelectLang'; | |
7 | -import styles from './index.less'; | |
8 | -import logo from './logo.svg'; | |
9 | - | |
10 | -const links = [ | |
11 | - { | |
12 | - key: 'help', | |
13 | - title: formatMessage({ id: 'layout.user.link.help' }), | |
14 | - href: '', | |
15 | - }, | |
16 | - { | |
17 | - key: 'privacy', | |
18 | - title: formatMessage({ id: 'layout.user.link.privacy' }), | |
19 | - href: '', | |
20 | - }, | |
21 | - { | |
22 | - key: 'terms', | |
23 | - title: formatMessage({ id: 'layout.user.link.terms' }), | |
24 | - href: '', | |
25 | - }, | |
26 | -]; | |
27 | - | |
28 | -const copyright = ( | |
29 | - <Fragment> | |
30 | - Copyright <Icon type="copyright" /> 2018 蚂蚁金服体验技术部出品 | |
31 | - </Fragment> | |
32 | -); | |
33 | - | |
34 | -class UserLayout extends React.PureComponent { | |
35 | - // @TODO title | |
36 | - // getPageTitle() { | |
37 | - // const { routerData, location } = this.props; | |
38 | - // const { pathname } = location; | |
39 | - // let title = 'Ant Design Pro'; | |
40 | - // if (routerData[pathname] && routerData[pathname].name) { | |
41 | - // title = `${routerData[pathname].name} - Ant Design Pro`; | |
42 | - // } | |
43 | - // return title; | |
44 | - // } | |
45 | - | |
46 | - render() { | |
47 | - const { children } = this.props; | |
48 | - return ( | |
49 | - // @TODO <DocumentTitle title={this.getPageTitle()}> | |
50 | - <div className={styles.container}> | |
51 | - <div className={styles.lang}> | |
52 | - <SelectLang /> | |
53 | - </div> | |
54 | - <div className={styles.content}> | |
55 | - <div className={styles.top}> | |
56 | - <div className={styles.header}> | |
57 | - <Link to="/"> | |
58 | - <img alt="logo" className={styles.logo} src={logo} /> | |
59 | - <span className={styles.title}>Ant Design</span> | |
60 | - </Link> | |
61 | - </div> | |
62 | - <div className={styles.desc}>Ant Design 是西湖区最具影响力的 Web 设计规范</div> | |
63 | - </div> | |
64 | - {children} | |
65 | - </div> | |
66 | - <GlobalFooter links={links} copyright={copyright} /> | |
67 | - </div> | |
68 | - ); | |
69 | - } | |
70 | -} | |
71 | - | |
72 | -export default UserLayout; |
1 | -@import '~antd/lib/style/themes/default.less'; | |
2 | - | |
3 | -.container { | |
4 | - display: flex; | |
5 | - flex-direction: column; | |
6 | - height: 100vh; | |
7 | - overflow: auto; | |
8 | - background: @layout-body-background; | |
9 | -} | |
10 | - | |
11 | -.lang { | |
12 | - text-align: right; | |
13 | - width: 100%; | |
14 | - height: 40px; | |
15 | - line-height: 44px; | |
16 | - :global(.ant-dropdown-trigger) { | |
17 | - margin-right: 24px; | |
18 | - } | |
19 | -} | |
20 | - | |
21 | -.content { | |
22 | - padding: 32px 0; | |
23 | - flex: 1; | |
24 | -} | |
25 | - | |
26 | -@media (min-width: @screen-md-min) { | |
27 | - .container { | |
28 | - background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg'); | |
29 | - background-repeat: no-repeat; | |
30 | - background-position: center 110px; | |
31 | - background-size: 100%; | |
32 | - } | |
33 | - | |
34 | - .content { | |
35 | - padding: 32px 0 24px 0; | |
36 | - } | |
37 | -} | |
38 | - | |
39 | -.top { | |
40 | - text-align: center; | |
41 | -} | |
42 | - | |
43 | -.header { | |
44 | - height: 44px; | |
45 | - line-height: 44px; | |
46 | - a { | |
47 | - text-decoration: none; | |
48 | - } | |
49 | -} | |
50 | - | |
51 | -.logo { | |
52 | - height: 44px; | |
53 | - vertical-align: top; | |
54 | - margin-right: 16px; | |
55 | -} | |
56 | - | |
57 | -.title { | |
58 | - font-size: 33px; | |
59 | - color: @heading-color; | |
60 | - font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif; | |
61 | - font-weight: 600; | |
62 | - position: relative; | |
63 | - top: 2px; | |
64 | -} | |
65 | - | |
66 | -.desc { | |
67 | - font-size: @font-size-base; | |
68 | - color: @text-color-secondary; | |
69 | - margin-top: 12px; | |
70 | - margin-bottom: 40px; | |
71 | -} |
1 | -<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
2 | -<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | |
3 | - <!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch --> | |
4 | - <title>Group 28 Copy 5</title> | |
5 | - <desc>Created with Sketch.</desc> | |
6 | - <defs> | |
7 | - <linearGradient x1="62.1023273%" y1="0%" x2="108.19718%" y2="37.8635764%" id="linearGradient-1"> | |
8 | - <stop stop-color="#4285EB" offset="0%"></stop> | |
9 | - <stop stop-color="#2EC7FF" offset="100%"></stop> | |
10 | - </linearGradient> | |
11 | - <linearGradient x1="69.644116%" y1="0%" x2="54.0428975%" y2="108.456714%" id="linearGradient-2"> | |
12 | - <stop stop-color="#29CDFF" offset="0%"></stop> | |
13 | - <stop stop-color="#148EFF" offset="37.8600687%"></stop> | |
14 | - <stop stop-color="#0A60FF" offset="100%"></stop> | |
15 | - </linearGradient> | |
16 | - <linearGradient x1="69.6908165%" y1="-12.9743587%" x2="16.7228981%" y2="117.391248%" id="linearGradient-3"> | |
17 | - <stop stop-color="#FA816E" offset="0%"></stop> | |
18 | - <stop stop-color="#F74A5C" offset="41.472606%"></stop> | |
19 | - <stop stop-color="#F51D2C" offset="100%"></stop> | |
20 | - </linearGradient> | |
21 | - <linearGradient x1="68.1279872%" y1="-35.6905737%" x2="30.4400914%" y2="114.942679%" id="linearGradient-4"> | |
22 | - <stop stop-color="#FA8E7D" offset="0%"></stop> | |
23 | - <stop stop-color="#F74A5C" offset="51.2635191%"></stop> | |
24 | - <stop stop-color="#F51D2C" offset="100%"></stop> | |
25 | - </linearGradient> | |
26 | - </defs> | |
27 | - <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> | |
28 | - <g id="logo" transform="translate(-20.000000, -20.000000)"> | |
29 | - <g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)"> | |
30 | - <g id="Group-27-Copy-3"> | |
31 | - <g id="Group-25" fill-rule="nonzero"> | |
32 | - <g id="2"> | |
33 | - <path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-1)"></path> | |
34 | - <path d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z" id="Shape" fill="url(#linearGradient-2)"></path> | |
35 | - </g> | |
36 | - <path d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z" id="Shape" fill="url(#linearGradient-3)"></path> | |
37 | - </g> | |
38 | - <ellipse id="Combined-Shape" fill="url(#linearGradient-4)" cx="100.519339" cy="100.436681" rx="23.6001926" ry="23.580786"></ellipse> | |
39 | - </g> | |
40 | - </g> | |
41 | - </g> | |
42 | - </g> | |
43 | -</svg> | |
\ No newline at end of file |
... | ... | @@ -4,7 +4,6 @@ import { formatMessage, FormattedMessage } from 'umi/locale'; |
4 | 4 | import Link from 'umi/link'; |
5 | 5 | import router from 'umi/router'; |
6 | 6 | import { Form, Input, Button, Select, Row, Col, Popover, Progress } from 'antd'; |
7 | -import UserLayout from './components/UserLayout'; | |
8 | 7 | import styles from './style.less'; |
9 | 8 | |
10 | 9 | const FormItem = Form.Item; |
... | ... | @@ -35,12 +34,12 @@ const passwordProgressMap = { |
35 | 34 | poor: 'exception', |
36 | 35 | }; |
37 | 36 | |
38 | -@connect(({ register, loading }) => ({ | |
39 | - register, | |
40 | - submitting: loading.effects['register/submit'], | |
37 | +@connect(({ BLOCK_NAME_CAMEL_CASE, loading }) => ({ | |
38 | + BLOCK_NAME_CAMEL_CASE, | |
39 | + submitting: loading.effects['BLOCK_NAME_CAMEL_CASE/submit'], | |
41 | 40 | })) |
42 | 41 | @Form.create() |
43 | -class Register extends Component { | |
42 | +class PAGE_NAME_UPPER_CAMEL_CASE extends Component { | |
44 | 43 | state = { |
45 | 44 | count: 0, |
46 | 45 | confirmDirty: false, |
... | ... | @@ -50,9 +49,9 @@ class Register extends Component { |
50 | 49 | }; |
51 | 50 | |
52 | 51 | componentDidUpdate() { |
53 | - const { form, register } = this.props; | |
52 | + const { form, BLOCK_NAME_CAMEL_CASE } = this.props; | |
54 | 53 | const account = form.getFieldValue('mail'); |
55 | - if (register.status === 'ok') { | |
54 | + if (BLOCK_NAME_CAMEL_CASE.status === 'ok') { | |
56 | 55 | router.push({ |
57 | 56 | pathname: '/user/register-result', |
58 | 57 | state: { |
... | ... | @@ -97,7 +96,7 @@ class Register extends Component { |
97 | 96 | if (!err) { |
98 | 97 | const { prefix } = this.state; |
99 | 98 | dispatch({ |
100 | - type: 'register/submit', | |
99 | + type: 'BLOCK_NAME_CAMEL_CASE/submit', | |
101 | 100 | payload: { |
102 | 101 | ...values, |
103 | 102 | prefix, |
... | ... | @@ -179,159 +178,157 @@ class Register extends Component { |
179 | 178 | const { getFieldDecorator } = form; |
180 | 179 | const { count, prefix, help, visible } = this.state; |
181 | 180 | return ( |
182 | - <UserLayout> | |
183 | - <div className={styles.main}> | |
184 | - <h3> | |
185 | - <FormattedMessage id="app.register.register" /> | |
186 | - </h3> | |
187 | - <Form onSubmit={this.handleSubmit}> | |
188 | - <FormItem> | |
189 | - {getFieldDecorator('mail', { | |
181 | + <div className={styles.main}> | |
182 | + <h3> | |
183 | + <FormattedMessage id="app.register.register" /> | |
184 | + </h3> | |
185 | + <Form onSubmit={this.handleSubmit}> | |
186 | + <FormItem> | |
187 | + {getFieldDecorator('mail', { | |
188 | + rules: [ | |
189 | + { | |
190 | + required: true, | |
191 | + message: formatMessage({ id: 'validation.email.required' }), | |
192 | + }, | |
193 | + { | |
194 | + type: 'email', | |
195 | + message: formatMessage({ id: 'validation.email.wrong-format' }), | |
196 | + }, | |
197 | + ], | |
198 | + })( | |
199 | + <Input size="large" placeholder={formatMessage({ id: 'form.email.placeholder' })} /> | |
200 | + )} | |
201 | + </FormItem> | |
202 | + <FormItem help={help}> | |
203 | + <Popover | |
204 | + getPopupContainer={node => node.parentNode} | |
205 | + content={ | |
206 | + <div style={{ padding: '4px 0' }}> | |
207 | + {passwordStatusMap[this.getPasswordStatus()]} | |
208 | + {this.renderPasswordProgress()} | |
209 | + <div style={{ marginTop: 10 }}> | |
210 | + <FormattedMessage id="validation.password.strength.msg" /> | |
211 | + </div> | |
212 | + </div> | |
213 | + } | |
214 | + overlayStyle={{ width: 240 }} | |
215 | + placement="right" | |
216 | + visible={visible} | |
217 | + > | |
218 | + {getFieldDecorator('password', { | |
190 | 219 | rules: [ |
191 | 220 | { |
192 | - required: true, | |
193 | - message: formatMessage({ id: 'validation.email.required' }), | |
194 | - }, | |
195 | - { | |
196 | - type: 'email', | |
197 | - message: formatMessage({ id: 'validation.email.wrong-format' }), | |
221 | + validator: this.checkPassword, | |
198 | 222 | }, |
199 | 223 | ], |
200 | 224 | })( |
201 | - <Input size="large" placeholder={formatMessage({ id: 'form.email.placeholder' })} /> | |
225 | + <Input | |
226 | + size="large" | |
227 | + type="password" | |
228 | + placeholder={formatMessage({ id: 'form.password.placeholder' })} | |
229 | + /> | |
202 | 230 | )} |
203 | - </FormItem> | |
204 | - <FormItem help={help}> | |
205 | - <Popover | |
206 | - getPopupContainer={node => node.parentNode} | |
207 | - content={ | |
208 | - <div style={{ padding: '4px 0' }}> | |
209 | - {passwordStatusMap[this.getPasswordStatus()]} | |
210 | - {this.renderPasswordProgress()} | |
211 | - <div style={{ marginTop: 10 }}> | |
212 | - <FormattedMessage id="validation.password.strength.msg" /> | |
213 | - </div> | |
214 | - </div> | |
215 | - } | |
216 | - overlayStyle={{ width: 240 }} | |
217 | - placement="right" | |
218 | - visible={visible} | |
231 | + </Popover> | |
232 | + </FormItem> | |
233 | + <FormItem> | |
234 | + {getFieldDecorator('confirm', { | |
235 | + rules: [ | |
236 | + { | |
237 | + required: true, | |
238 | + message: formatMessage({ id: 'validation.confirm-password.required' }), | |
239 | + }, | |
240 | + { | |
241 | + validator: this.checkConfirm, | |
242 | + }, | |
243 | + ], | |
244 | + })( | |
245 | + <Input | |
246 | + size="large" | |
247 | + type="password" | |
248 | + placeholder={formatMessage({ id: 'form.confirm-password.placeholder' })} | |
249 | + /> | |
250 | + )} | |
251 | + </FormItem> | |
252 | + <FormItem> | |
253 | + <InputGroup compact> | |
254 | + <Select | |
255 | + size="large" | |
256 | + value={prefix} | |
257 | + onChange={this.changePrefix} | |
258 | + style={{ width: '20%' }} | |
219 | 259 | > |
220 | - {getFieldDecorator('password', { | |
221 | - rules: [ | |
222 | - { | |
223 | - validator: this.checkPassword, | |
224 | - }, | |
225 | - ], | |
226 | - })( | |
227 | - <Input | |
228 | - size="large" | |
229 | - type="password" | |
230 | - placeholder={formatMessage({ id: 'form.password.placeholder' })} | |
231 | - /> | |
232 | - )} | |
233 | - </Popover> | |
234 | - </FormItem> | |
235 | - <FormItem> | |
236 | - {getFieldDecorator('confirm', { | |
260 | + <Option value="86">+86</Option> | |
261 | + <Option value="87">+87</Option> | |
262 | + </Select> | |
263 | + {getFieldDecorator('mobile', { | |
237 | 264 | rules: [ |
238 | 265 | { |
239 | 266 | required: true, |
240 | - message: formatMessage({ id: 'validation.confirm-password.required' }), | |
267 | + message: formatMessage({ id: 'validation.phone-number.required' }), | |
241 | 268 | }, |
242 | 269 | { |
243 | - validator: this.checkConfirm, | |
270 | + pattern: /^\d{11}$/, | |
271 | + message: formatMessage({ id: 'validation.phone-number.wrong-format' }), | |
244 | 272 | }, |
245 | 273 | ], |
246 | 274 | })( |
247 | 275 | <Input |
248 | 276 | size="large" |
249 | - type="password" | |
250 | - placeholder={formatMessage({ id: 'form.confirm-password.placeholder' })} | |
277 | + style={{ width: '80%' }} | |
278 | + placeholder={formatMessage({ id: 'form.phone-number.placeholder' })} | |
251 | 279 | /> |
252 | 280 | )} |
253 | - </FormItem> | |
254 | - <FormItem> | |
255 | - <InputGroup compact> | |
256 | - <Select | |
257 | - size="large" | |
258 | - value={prefix} | |
259 | - onChange={this.changePrefix} | |
260 | - style={{ width: '20%' }} | |
261 | - > | |
262 | - <Option value="86">+86</Option> | |
263 | - <Option value="87">+87</Option> | |
264 | - </Select> | |
265 | - {getFieldDecorator('mobile', { | |
281 | + </InputGroup> | |
282 | + </FormItem> | |
283 | + <FormItem> | |
284 | + <Row gutter={8}> | |
285 | + <Col span={16}> | |
286 | + {getFieldDecorator('captcha', { | |
266 | 287 | rules: [ |
267 | 288 | { |
268 | 289 | required: true, |
269 | - message: formatMessage({ id: 'validation.phone-number.required' }), | |
270 | - }, | |
271 | - { | |
272 | - pattern: /^\d{11}$/, | |
273 | - message: formatMessage({ id: 'validation.phone-number.wrong-format' }), | |
290 | + message: formatMessage({ id: 'validation.verification-code.required' }), | |
274 | 291 | }, |
275 | 292 | ], |
276 | 293 | })( |
277 | 294 | <Input |
278 | 295 | size="large" |
279 | - style={{ width: '80%' }} | |
280 | - placeholder={formatMessage({ id: 'form.phone-number.placeholder' })} | |
296 | + placeholder={formatMessage({ id: 'form.verification-code.placeholder' })} | |
281 | 297 | /> |
282 | 298 | )} |
283 | - </InputGroup> | |
284 | - </FormItem> | |
285 | - <FormItem> | |
286 | - <Row gutter={8}> | |
287 | - <Col span={16}> | |
288 | - {getFieldDecorator('captcha', { | |
289 | - rules: [ | |
290 | - { | |
291 | - required: true, | |
292 | - message: formatMessage({ id: 'validation.verification-code.required' }), | |
293 | - }, | |
294 | - ], | |
295 | - })( | |
296 | - <Input | |
297 | - size="large" | |
298 | - placeholder={formatMessage({ id: 'form.verification-code.placeholder' })} | |
299 | - /> | |
300 | - )} | |
301 | - </Col> | |
302 | - <Col span={8}> | |
303 | - <Button | |
304 | - size="large" | |
305 | - disabled={count} | |
306 | - className={styles.getCaptcha} | |
307 | - onClick={this.onGetCaptcha} | |
308 | - > | |
309 | - {count | |
310 | - ? `${count} s` | |
311 | - : formatMessage({ id: 'app.register.get-verification-code' })} | |
312 | - </Button> | |
313 | - </Col> | |
314 | - </Row> | |
315 | - </FormItem> | |
316 | - <FormItem> | |
317 | - <Button | |
318 | - size="large" | |
319 | - loading={submitting} | |
320 | - className={styles.submit} | |
321 | - type="primary" | |
322 | - htmlType="submit" | |
323 | - > | |
324 | - <FormattedMessage id="app.register.register" /> | |
325 | - </Button> | |
326 | - <Link className={styles.login} to="/User/Login"> | |
327 | - <FormattedMessage id="app.register.sign-in" /> | |
328 | - </Link> | |
329 | - </FormItem> | |
330 | - </Form> | |
331 | - </div> | |
332 | - </UserLayout> | |
299 | + </Col> | |
300 | + <Col span={8}> | |
301 | + <Button | |
302 | + size="large" | |
303 | + disabled={count} | |
304 | + className={styles.getCaptcha} | |
305 | + onClick={this.onGetCaptcha} | |
306 | + > | |
307 | + {count | |
308 | + ? `${count} s` | |
309 | + : formatMessage({ id: 'app.register.get-verification-code' })} | |
310 | + </Button> | |
311 | + </Col> | |
312 | + </Row> | |
313 | + </FormItem> | |
314 | + <FormItem> | |
315 | + <Button | |
316 | + size="large" | |
317 | + loading={submitting} | |
318 | + className={styles.submit} | |
319 | + type="primary" | |
320 | + htmlType="submit" | |
321 | + > | |
322 | + <FormattedMessage id="app.register.register" /> | |
323 | + </Button> | |
324 | + <Link className={styles.login} to="/User/Login"> | |
325 | + <FormattedMessage id="app.register.sign-in" /> | |
326 | + </Link> | |
327 | + </FormItem> | |
328 | + </Form> | |
329 | + </div> | |
333 | 330 | ); |
334 | 331 | } |
335 | 332 | } |
336 | 333 | |
337 | -export default Register; | |
334 | +export default PAGE_NAME_UPPER_CAMEL_CASE; | ... | ... |
1 | 1 | import { fakeRegister } from './service'; |
2 | -import { setAuthority } from './utils/authority'; | |
3 | -import { reloadAuthorized } from './utils/Authorized'; | |
4 | 2 | |
5 | 3 | export default { |
6 | - namespace: 'register', | |
4 | + namespace: 'BLOCK_NAME_CAMEL_CASE', | |
7 | 5 | |
8 | 6 | state: { |
9 | 7 | status: undefined, |
... | ... | @@ -21,8 +19,6 @@ export default { |
21 | 19 | |
22 | 20 | reducers: { |
23 | 21 | registerHandle(state, { payload }) { |
24 | - setAuthority('user'); | |
25 | - reloadAuthorized(); | |
26 | 22 | return { |
27 | 23 | ...state, |
28 | 24 | status: payload.status, | ... | ... |
1 | -import RenderAuthorized from 'ant-design-pro/lib/Authorized'; | |
2 | -import { getAuthority } from './authority'; | |
3 | - | |
4 | -let Authorized = RenderAuthorized(getAuthority()); // eslint-disable-line | |
5 | - | |
6 | -// Reload the rights component | |
7 | -const reloadAuthorized = () => { | |
8 | - Authorized = RenderAuthorized(getAuthority()); | |
9 | -}; | |
10 | - | |
11 | -export { reloadAuthorized }; | |
12 | -export default Authorized; |
1 | -// use localStorage to store the authority info, which might be sent from server in actual project. | |
2 | -export function getAuthority(str) { | |
3 | - // return localStorage.getItem('antd-pro-authority') || ['admin', 'user']; | |
4 | - const authorityString = | |
5 | - typeof str === 'undefined' ? localStorage.getItem('antd-pro-authority') : str; | |
6 | - // authorityString could be admin, "admin", ["admin"] | |
7 | - let authority; | |
8 | - try { | |
9 | - authority = JSON.parse(authorityString); | |
10 | - } catch (e) { | |
11 | - authority = authorityString; | |
12 | - } | |
13 | - if (typeof authority === 'string') { | |
14 | - return [authority]; | |
15 | - } | |
16 | - return authority || ['admin']; | |
17 | -} | |
18 | - | |
19 | -export function setAuthority(authority) { | |
20 | - const proAuthority = typeof authority === 'string' ? [authority] : authority; | |
21 | - return localStorage.setItem('antd-pro-authority', JSON.stringify(proAuthority)); | |
22 | -} |
1 | -import moment from 'moment'; | |
2 | -import React from 'react'; | |
3 | -import nzh from 'nzh/cn'; | |
4 | -import { parse, stringify } from 'qs'; | |
5 | - | |
6 | -export function fixedZero(val) { | |
7 | - return val * 1 < 10 ? `0${val}` : val; | |
8 | -} | |
9 | - | |
10 | -export function getTimeDistance(type) { | |
11 | - const now = new Date(); | |
12 | - const oneDay = 1000 * 60 * 60 * 24; | |
13 | - | |
14 | - if (type === 'today') { | |
15 | - now.setHours(0); | |
16 | - now.setMinutes(0); | |
17 | - now.setSeconds(0); | |
18 | - return [moment(now), moment(now.getTime() + (oneDay - 1000))]; | |
19 | - } | |
20 | - | |
21 | - if (type === 'week') { | |
22 | - let day = now.getDay(); | |
23 | - now.setHours(0); | |
24 | - now.setMinutes(0); | |
25 | - now.setSeconds(0); | |
26 | - | |
27 | - if (day === 0) { | |
28 | - day = 6; | |
29 | - } else { | |
30 | - day -= 1; | |
31 | - } | |
32 | - | |
33 | - const beginTime = now.getTime() - day * oneDay; | |
34 | - | |
35 | - return [moment(beginTime), moment(beginTime + (7 * oneDay - 1000))]; | |
36 | - } | |
37 | - | |
38 | - if (type === 'month') { | |
39 | - const year = now.getFullYear(); | |
40 | - const month = now.getMonth(); | |
41 | - const nextDate = moment(now).add(1, 'months'); | |
42 | - const nextYear = nextDate.year(); | |
43 | - const nextMonth = nextDate.month(); | |
44 | - | |
45 | - return [ | |
46 | - moment(`${year}-${fixedZero(month + 1)}-01 00:00:00`), | |
47 | - moment(moment(`${nextYear}-${fixedZero(nextMonth + 1)}-01 00:00:00`).valueOf() - 1000), | |
48 | - ]; | |
49 | - } | |
50 | - | |
51 | - const year = now.getFullYear(); | |
52 | - return [moment(`${year}-01-01 00:00:00`), moment(`${year}-12-31 23:59:59`)]; | |
53 | -} | |
54 | - | |
55 | -export function getPlainNode(nodeList, parentPath = '') { | |
56 | - const arr = []; | |
57 | - nodeList.forEach(node => { | |
58 | - const item = node; | |
59 | - item.path = `${parentPath}/${item.path || ''}`.replace(/\/+/g, '/'); | |
60 | - item.exact = true; | |
61 | - if (item.children && !item.component) { | |
62 | - arr.push(...getPlainNode(item.children, item.path)); | |
63 | - } else { | |
64 | - if (item.children && item.component) { | |
65 | - item.exact = false; | |
66 | - } | |
67 | - arr.push(item); | |
68 | - } | |
69 | - }); | |
70 | - return arr; | |
71 | -} | |
72 | - | |
73 | -export function digitUppercase(n) { | |
74 | - return nzh.toMoney(n); | |
75 | -} | |
76 | - | |
77 | -function getRelation(str1, str2) { | |
78 | - if (str1 === str2) { | |
79 | - console.warn('Two path are equal!'); // eslint-disable-line | |
80 | - } | |
81 | - const arr1 = str1.split('/'); | |
82 | - const arr2 = str2.split('/'); | |
83 | - if (arr2.every((item, index) => item === arr1[index])) { | |
84 | - return 1; | |
85 | - } | |
86 | - if (arr1.every((item, index) => item === arr2[index])) { | |
87 | - return 2; | |
88 | - } | |
89 | - return 3; | |
90 | -} | |
91 | - | |
92 | -function getRenderArr(routes) { | |
93 | - let renderArr = []; | |
94 | - renderArr.push(routes[0]); | |
95 | - for (let i = 1; i < routes.length; i += 1) { | |
96 | - // 去重 | |
97 | - renderArr = renderArr.filter(item => getRelation(item, routes[i]) !== 1); | |
98 | - // 是否包含 | |
99 | - const isAdd = renderArr.every(item => getRelation(item, routes[i]) === 3); | |
100 | - if (isAdd) { | |
101 | - renderArr.push(routes[i]); | |
102 | - } | |
103 | - } | |
104 | - return renderArr; | |
105 | -} | |
106 | - | |
107 | -/** | |
108 | - * Get router routing configuration | |
109 | - * { path:{name,...param}}=>Array<{name,path ...param}> | |
110 | - * @param {string} path | |
111 | - * @param {routerData} routerData | |
112 | - */ | |
113 | -export function getRoutes(path, routerData) { | |
114 | - let routes = Object.keys(routerData).filter( | |
115 | - routePath => routePath.indexOf(path) === 0 && routePath !== path | |
116 | - ); | |
117 | - // Replace path to '' eg. path='user' /user/name => name | |
118 | - routes = routes.map(item => item.replace(path, '')); | |
119 | - // Get the route to be rendered to remove the deep rendering | |
120 | - const renderArr = getRenderArr(routes); | |
121 | - // Conversion and stitching parameters | |
122 | - const renderRoutes = renderArr.map(item => { | |
123 | - const exact = !routes.some(route => route !== item && getRelation(route, item) === 1); | |
124 | - return { | |
125 | - exact, | |
126 | - ...routerData[`${path}${item}`], | |
127 | - key: `${path}${item}`, | |
128 | - path: `${path}${item}`, | |
129 | - }; | |
130 | - }); | |
131 | - return renderRoutes; | |
132 | -} | |
133 | - | |
134 | -export function getPageQuery() { | |
135 | - return parse(window.location.href.split('?')[1]); | |
136 | -} | |
137 | - | |
138 | -export function getQueryPath(path = '', query = {}) { | |
139 | - const search = stringify(query); | |
140 | - if (search.length) { | |
141 | - return `${path}?${search}`; | |
142 | - } | |
143 | - return path; | |
144 | -} | |
145 | - | |
146 | -/* eslint no-useless-escape:0 */ | |
147 | -const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/; | |
148 | - | |
149 | -export function isUrl(path) { | |
150 | - return reg.test(path); | |
151 | -} | |
152 | - | |
153 | -export function formatWan(val) { | |
154 | - const v = val * 1; | |
155 | - if (!v || Number.isNaN(v)) return ''; | |
156 | - | |
157 | - let result = val; | |
158 | - if (val > 10000) { | |
159 | - result = Math.floor(val / 10000); | |
160 | - result = ( | |
161 | - <span> | |
162 | - {result} | |
163 | - <span | |
164 | - style={{ | |
165 | - position: 'relative', | |
166 | - top: -2, | |
167 | - fontSize: 14, | |
168 | - fontStyle: 'normal', | |
169 | - marginLeft: 2, | |
170 | - }} | |
171 | - > | |
172 | - 万 | |
173 | - </span> | |
174 | - </span> | |
175 | - ); | |
176 | - } | |
177 | - return result; | |
178 | -} | |
179 | - | |
180 | -// 给官方演示站点用,用于关闭真实开发环境不需要使用的特性 | |
181 | -export function isAntdPro() { | |
182 | - return window.location.hostname === 'preview.pro.ant.design'; | |
183 | -} |
请
注册
或
登录
后发表评论