正在显示
13 个修改的文件
包含
115 行增加
和
512 行删除
1 | 1 | { |
2 | - "name": "@umi-block/userlogin", | |
2 | + "name": "@umi-block/user-login", | |
3 | 3 | "version": "0.0.1", |
4 | 4 | "description": "UserLogin", |
5 | 5 | "main": "src/index.js", |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | "antd": "^3.10.9", |
16 | 16 | "dva": "^2.4.0", |
17 | 17 | "moment": "^2.22.2", |
18 | + "qs": "^6.6.0", | |
18 | 19 | "react": "^16.6.3", |
19 | 20 | "umi-request": "^1.0.0" |
20 | 21 | }, | ... | ... |
1 | -// 代码中会兼容本地 service mock 以及部署站点的静态数据 | |
1 | +function getFakeCaptcha(req, res) { | |
2 | + return res.json('captcha-xxx'); | |
3 | +} | |
4 | + | |
2 | 5 | export default { |
3 | - // 支持值为 Object 和 Array | |
4 | - 'GET /api/currentUser': { | |
5 | - name: 'Serati Ma', | |
6 | - avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png', | |
7 | - userid: '00000001', | |
8 | - email: 'antdesign@alipay.com', | |
9 | - signature: '海纳百川,有容乃大', | |
10 | - title: '交互专家', | |
11 | - group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED', | |
12 | - tags: [ | |
13 | - { | |
14 | - key: '0', | |
15 | - label: '很有想法的', | |
16 | - }, | |
17 | - { | |
18 | - key: '1', | |
19 | - label: '专注设计', | |
20 | - }, | |
21 | - { | |
22 | - key: '2', | |
23 | - label: '辣~', | |
24 | - }, | |
25 | - { | |
26 | - key: '3', | |
27 | - label: '大长腿', | |
28 | - }, | |
29 | - { | |
30 | - key: '4', | |
31 | - label: '川妹子', | |
32 | - }, | |
33 | - { | |
34 | - key: '5', | |
35 | - label: '海纳百川', | |
36 | - }, | |
37 | - ], | |
38 | - notifyCount: 12, | |
39 | - unreadCount: 11, | |
40 | - country: 'China', | |
41 | - geographic: { | |
42 | - province: { | |
43 | - label: '浙江省', | |
44 | - key: '330000', | |
45 | - }, | |
46 | - city: { | |
47 | - label: '杭州市', | |
48 | - key: '330100', | |
49 | - }, | |
50 | - }, | |
51 | - address: '西湖区工专路 77 号', | |
52 | - phone: '0752-268888888', | |
53 | - }, | |
54 | - // GET POST 可省略 | |
55 | - 'GET /api/users': [ | |
56 | - { | |
57 | - key: '1', | |
58 | - name: 'John Brown', | |
59 | - age: 32, | |
60 | - address: 'New York No. 1 Lake Park', | |
61 | - }, | |
62 | - { | |
63 | - key: '2', | |
64 | - name: 'Jim Green', | |
65 | - age: 42, | |
66 | - address: 'London No. 1 Lake Park', | |
67 | - }, | |
68 | - { | |
69 | - key: '3', | |
70 | - name: 'Joe Black', | |
71 | - age: 32, | |
72 | - address: 'Sidney No. 1 Lake Park', | |
73 | - }, | |
74 | - ], | |
75 | - 'POST /api/login/account': (req, res) => { | |
6 | + 'POST /api/BLOCK_NAME/account': (req, res) => { | |
76 | 7 | const { password, userName, type } = req.body; |
77 | 8 | if (password === 'ant.design' && userName === 'admin') { |
78 | 9 | res.send({ |
... | ... | @@ -96,43 +27,5 @@ export default { |
96 | 27 | currentAuthority: 'guest', |
97 | 28 | }); |
98 | 29 | }, |
99 | - 'POST /api/register': (req, res) => { | |
100 | - res.send({ status: 'ok', currentAuthority: 'user' }); | |
101 | - }, | |
102 | - 'GET /api/500': (req, res) => { | |
103 | - res.status(500).send({ | |
104 | - timestamp: 1513932555104, | |
105 | - status: 500, | |
106 | - error: 'error', | |
107 | - message: 'error', | |
108 | - path: '/base/category/list', | |
109 | - }); | |
110 | - }, | |
111 | - 'GET /api/404': (req, res) => { | |
112 | - res.status(404).send({ | |
113 | - timestamp: 1513932643431, | |
114 | - status: 404, | |
115 | - error: 'Not Found', | |
116 | - message: 'No message available', | |
117 | - path: '/base/category/list/2121212', | |
118 | - }); | |
119 | - }, | |
120 | - 'GET /api/403': (req, res) => { | |
121 | - res.status(403).send({ | |
122 | - timestamp: 1513932555104, | |
123 | - status: 403, | |
124 | - error: 'Unauthorized', | |
125 | - message: 'Unauthorized', | |
126 | - path: '/base/category/list', | |
127 | - }); | |
128 | - }, | |
129 | - 'GET /api/401': (req, res) => { | |
130 | - res.status(401).send({ | |
131 | - timestamp: 1513932555104, | |
132 | - status: 401, | |
133 | - error: 'Unauthorized', | |
134 | - message: 'Unauthorized', | |
135 | - path: '/base/category/list', | |
136 | - }); | |
137 | - }, | |
30 | + 'GET /api/BLOCK_NAME/captcha': getFakeCaptcha, | |
138 | 31 | }; | ... | ... |
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,14 +4,13 @@ import { formatMessage, FormattedMessage } from 'umi/locale'; |
4 | 4 | import Link from 'umi/link'; |
5 | 5 | import { Checkbox, Alert, Icon } from 'antd'; |
6 | 6 | import { Login } from 'ant-design-pro'; |
7 | -import UserLayout from './components/UserLayout'; | |
8 | 7 | import styles from './style.less'; |
9 | 8 | |
10 | 9 | const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login; |
11 | 10 | |
12 | -@connect(({ login, loading }) => ({ | |
13 | - login, | |
14 | - submitting: loading.effects['login/login'], | |
11 | +@connect(({ BLOCK_NAME_CAMEL_CASE, loading }) => ({ | |
12 | + BLOCK_NAME_CAMEL_CASE, | |
13 | + submitting: loading.effects['BLOCK_NAME_CAMEL_CASE/login'], | |
15 | 14 | })) |
16 | 15 | class LoginPage extends Component { |
17 | 16 | state = { |
... | ... | @@ -31,7 +30,7 @@ class LoginPage extends Component { |
31 | 30 | } else { |
32 | 31 | const { dispatch } = this.props; |
33 | 32 | dispatch({ |
34 | - type: 'login/getCaptcha', | |
33 | + type: 'BLOCK_NAME_CAMEL_CASE/getCaptcha', | |
35 | 34 | payload: values.mobile, |
36 | 35 | }) |
37 | 36 | .then(resolve) |
... | ... | @@ -45,7 +44,7 @@ class LoginPage extends Component { |
45 | 44 | if (!err) { |
46 | 45 | const { dispatch } = this.props; |
47 | 46 | dispatch({ |
48 | - type: 'login/login', | |
47 | + type: 'BLOCK_NAME_CAMEL_CASE/login', | |
49 | 48 | payload: { |
50 | 49 | ...values, |
51 | 50 | type, |
... | ... | @@ -65,105 +64,104 @@ class LoginPage extends Component { |
65 | 64 | ); |
66 | 65 | |
67 | 66 | render() { |
68 | - const { login, submitting } = this.props; | |
67 | + const { BLOCK_NAME_CAMEL_CASE, submitting } = this.props; | |
68 | + const { status, type: loginType } = BLOCK_NAME_CAMEL_CASE; | |
69 | 69 | const { type, autoLogin } = this.state; |
70 | 70 | return ( |
71 | - <UserLayout> | |
72 | - <div className={styles.main}> | |
73 | - <Login | |
74 | - defaultActiveKey={type} | |
75 | - onTabChange={this.onTabChange} | |
76 | - onSubmit={this.handleSubmit} | |
77 | - ref={form => { | |
78 | - this.loginForm = form; | |
79 | - }} | |
80 | - > | |
81 | - <Tab key="account" tab={formatMessage({ id: 'app.login.tab-login-credentials' })}> | |
82 | - {login.status === 'error' && | |
83 | - login.type === 'account' && | |
84 | - !submitting && | |
85 | - this.renderMessage(formatMessage({ id: 'app.login.message-invalid-credentials' }))} | |
86 | - <UserName | |
87 | - name="userName" | |
88 | - placeholder={`${formatMessage({ id: 'app.login.userName' })}: admin or user`} | |
89 | - rules={[ | |
90 | - { | |
91 | - required: true, | |
92 | - message: formatMessage({ id: 'validation.userName.required' }), | |
93 | - }, | |
94 | - ]} | |
95 | - /> | |
96 | - <Password | |
97 | - name="password" | |
98 | - placeholder={`${formatMessage({ id: 'app.login.password' })}: ant.design`} | |
99 | - rules={[ | |
100 | - { | |
101 | - required: true, | |
102 | - message: formatMessage({ id: 'validation.password.required' }), | |
103 | - }, | |
104 | - ]} | |
105 | - onPressEnter={() => this.loginForm.validateFields(this.handleSubmit)} | |
106 | - /> | |
107 | - </Tab> | |
108 | - <Tab key="mobile" tab={formatMessage({ id: 'app.login.tab-login-mobile' })}> | |
109 | - {login.status === 'error' && | |
110 | - login.type === 'mobile' && | |
111 | - !submitting && | |
112 | - this.renderMessage( | |
113 | - formatMessage({ id: 'app.login.message-invalid-verification-code' }) | |
114 | - )} | |
115 | - <Mobile | |
116 | - name="mobile" | |
117 | - placeholder={formatMessage({ id: 'form.phone-number.placeholder' })} | |
118 | - rules={[ | |
119 | - { | |
120 | - required: true, | |
121 | - message: formatMessage({ id: 'validation.phone-number.required' }), | |
122 | - }, | |
123 | - { | |
124 | - pattern: /^1\d{10}$/, | |
125 | - message: formatMessage({ id: 'validation.phone-number.wrong-format' }), | |
126 | - }, | |
127 | - ]} | |
128 | - /> | |
129 | - <Captcha | |
130 | - name="captcha" | |
131 | - placeholder={formatMessage({ id: 'form.verification-code.placeholder' })} | |
132 | - countDown={120} | |
133 | - onGetCaptcha={this.onGetCaptcha} | |
134 | - getCaptchaButtonText={formatMessage({ id: 'form.get-captcha' })} | |
135 | - getCaptchaSecondText={formatMessage({ id: 'form.captcha.second' })} | |
136 | - rules={[ | |
137 | - { | |
138 | - required: true, | |
139 | - message: formatMessage({ id: 'validation.verification-code.required' }), | |
140 | - }, | |
141 | - ]} | |
142 | - /> | |
143 | - </Tab> | |
144 | - <div> | |
145 | - <Checkbox checked={autoLogin} onChange={this.changeAutoLogin}> | |
146 | - <FormattedMessage id="app.login.remember-me" /> | |
147 | - </Checkbox> | |
148 | - <a style={{ float: 'right' }} href=""> | |
149 | - <FormattedMessage id="app.login.forgot-password" /> | |
150 | - </a> | |
151 | - </div> | |
152 | - <Submit loading={submitting}> | |
153 | - <FormattedMessage id="app.login.login" /> | |
154 | - </Submit> | |
155 | - <div className={styles.other}> | |
156 | - <FormattedMessage id="app.login.sign-in-with" /> | |
157 | - <Icon type="alipay-circle" className={styles.icon} theme="outlined" /> | |
158 | - <Icon type="taobao-circle" className={styles.icon} theme="outlined" /> | |
159 | - <Icon type="weibo-circle" className={styles.icon} theme="outlined" /> | |
160 | - <Link className={styles.register} to="/user/register"> | |
161 | - <FormattedMessage id="app.login.signup" /> | |
162 | - </Link> | |
163 | - </div> | |
164 | - </Login> | |
165 | - </div> | |
166 | - </UserLayout> | |
71 | + <div className={styles.main}> | |
72 | + <Login | |
73 | + defaultActiveKey={type} | |
74 | + onTabChange={this.onTabChange} | |
75 | + onSubmit={this.handleSubmit} | |
76 | + ref={form => { | |
77 | + this.loginForm = form; | |
78 | + }} | |
79 | + > | |
80 | + <Tab key="account" tab={formatMessage({ id: 'app.login.tab-login-credentials' })}> | |
81 | + {status === 'error' && | |
82 | + loginType === 'account' && | |
83 | + !submitting && | |
84 | + this.renderMessage(formatMessage({ id: 'app.login.message-invalid-credentials' }))} | |
85 | + <UserName | |
86 | + name="userName" | |
87 | + placeholder={`${formatMessage({ id: 'app.login.userName' })}: admin or user`} | |
88 | + rules={[ | |
89 | + { | |
90 | + required: true, | |
91 | + message: formatMessage({ id: 'validation.userName.required' }), | |
92 | + }, | |
93 | + ]} | |
94 | + /> | |
95 | + <Password | |
96 | + name="password" | |
97 | + placeholder={`${formatMessage({ id: 'app.login.password' })}: ant.design`} | |
98 | + rules={[ | |
99 | + { | |
100 | + required: true, | |
101 | + message: formatMessage({ id: 'validation.password.required' }), | |
102 | + }, | |
103 | + ]} | |
104 | + onPressEnter={() => this.loginForm.validateFields(this.handleSubmit)} | |
105 | + /> | |
106 | + </Tab> | |
107 | + <Tab key="mobile" tab={formatMessage({ id: 'app.login.tab-login-mobile' })}> | |
108 | + {status === 'error' && | |
109 | + loginType === 'mobile' && | |
110 | + !submitting && | |
111 | + this.renderMessage( | |
112 | + formatMessage({ id: 'app.login.message-invalid-verification-code' }) | |
113 | + )} | |
114 | + <Mobile | |
115 | + name="mobile" | |
116 | + placeholder={formatMessage({ id: 'form.phone-number.placeholder' })} | |
117 | + rules={[ | |
118 | + { | |
119 | + required: true, | |
120 | + message: formatMessage({ id: 'validation.phone-number.required' }), | |
121 | + }, | |
122 | + { | |
123 | + pattern: /^1\d{10}$/, | |
124 | + message: formatMessage({ id: 'validation.phone-number.wrong-format' }), | |
125 | + }, | |
126 | + ]} | |
127 | + /> | |
128 | + <Captcha | |
129 | + name="captcha" | |
130 | + placeholder={formatMessage({ id: 'form.verification-code.placeholder' })} | |
131 | + countDown={120} | |
132 | + onGetCaptcha={this.onGetCaptcha} | |
133 | + getCaptchaButtonText={formatMessage({ id: 'form.get-captcha' })} | |
134 | + getCaptchaSecondText={formatMessage({ id: 'form.captcha.second' })} | |
135 | + rules={[ | |
136 | + { | |
137 | + required: true, | |
138 | + message: formatMessage({ id: 'validation.verification-code.required' }), | |
139 | + }, | |
140 | + ]} | |
141 | + /> | |
142 | + </Tab> | |
143 | + <div> | |
144 | + <Checkbox checked={autoLogin} onChange={this.changeAutoLogin}> | |
145 | + <FormattedMessage id="app.login.remember-me" /> | |
146 | + </Checkbox> | |
147 | + <a style={{ float: 'right' }} href=""> | |
148 | + <FormattedMessage id="app.login.forgot-password" /> | |
149 | + </a> | |
150 | + </div> | |
151 | + <Submit loading={submitting}> | |
152 | + <FormattedMessage id="app.login.login" /> | |
153 | + </Submit> | |
154 | + <div className={styles.other}> | |
155 | + <FormattedMessage id="app.login.sign-in-with" /> | |
156 | + <Icon type="alipay-circle" className={styles.icon} theme="outlined" /> | |
157 | + <Icon type="taobao-circle" className={styles.icon} theme="outlined" /> | |
158 | + <Icon type="weibo-circle" className={styles.icon} theme="outlined" /> | |
159 | + <Link className={styles.register} to="/user/register"> | |
160 | + <FormattedMessage id="app.login.signup" /> | |
161 | + </Link> | |
162 | + </div> | |
163 | + </Login> | |
164 | + </div> | |
167 | 165 | ); |
168 | 166 | } |
169 | 167 | } | ... | ... |
1 | 1 | import request from 'umi-request'; |
2 | 2 | |
3 | 3 | export async function fakeAccountLogin(params) { |
4 | - return request('/api/login/account', { | |
4 | + return request('/api/BLOCK_NAME/account', { | |
5 | 5 | method: 'POST', |
6 | 6 | body: params, |
7 | 7 | }); |
8 | 8 | } |
9 | 9 | |
10 | 10 | export async function getFakeCaptcha(mobile) { |
11 | - return request(`/api/captcha?mobile=${mobile}`); | |
11 | + return request(`/api/BLOCK_NAME/captcha?mobile=${mobile}`); | |
12 | 12 | } | ... | ... |
请
注册
或
登录
后发表评论