Commit 312df31cf00709b19f1d098a8423b8b46e3be29a
1 parent
73fd7ef2
feat: add login
Showing
5 changed files
with
116 additions
and
125 deletions
.umirc.ts
... | ... | @@ -12,11 +12,11 @@ export default defineConfig({ |
12 | 12 | title: '订单管理系统', |
13 | 13 | }, |
14 | 14 | proxy: { |
15 | - '/service/': { | |
16 | - target: 'http://localhost:8085/', | |
17 | - // target: 'http://39.108.227.113:8085/', | |
15 | + '/api/': { | |
16 | + // target: 'http://localhost:8085/', | |
17 | + target: 'http://39.108.227.113:8085/', | |
18 | 18 | changeOrigin: true, |
19 | - // pathRewrite: { '^/api': '' }, | |
19 | + pathRewrite: { '^/api': '' }, | |
20 | 20 | }, |
21 | 21 | }, |
22 | 22 | routes: [ | ... | ... |
README.md
src/app.ts
1 | 1 | // 运行时配置 |
2 | 2 | |
3 | -import { RequestConfig } from '@umijs/max'; | |
3 | +import { RequestConfig, history } from '@umijs/max'; | |
4 | 4 | |
5 | 5 | import '@inspir/assembly-css/dist/special.css'; |
6 | 6 | import { message } from 'antd'; |
... | ... | @@ -34,10 +34,11 @@ export const request: RequestConfig = { |
34 | 34 | if (response && response.status) { |
35 | 35 | // 401重定向 |
36 | 36 | if (response.status === 401) { |
37 | - if (!location.pathname.includes(loginPath)) { | |
37 | + if (!location.pathname.includes('login')) { | |
38 | 38 | localStorage.removeItem('token'); |
39 | + localStorage.removeItem('userInfo'); | |
39 | 40 | message.error('token失效,请重新登录!'); |
40 | - // history.push(loginPath); | |
41 | + history.push('/login'); | |
41 | 42 | return null; |
42 | 43 | } |
43 | 44 | } |
... | ... | @@ -74,7 +75,7 @@ export const request: RequestConfig = { |
74 | 75 | } |
75 | 76 | |
76 | 77 | return { |
77 | - url, | |
78 | + url: '/api' + url, | |
78 | 79 | options: { |
79 | 80 | ...options, |
80 | 81 | signal, |
... | ... | @@ -93,6 +94,7 @@ export const request: RequestConfig = { |
93 | 94 | if (data.result !== RESPONSE_CODE.SUCCESS) { |
94 | 95 | message.error(data.message); |
95 | 96 | } |
97 | + | |
96 | 98 | // do something |
97 | 99 | return response; |
98 | 100 | }, | ... | ... |
src/models/user.ts
... | ... | @@ -2,7 +2,28 @@ import { useState } from 'react'; |
2 | 2 | |
3 | 3 | // src/models/userModel.ts |
4 | 4 | export default function Page() { |
5 | - const { token, setToken } = useState(''); | |
5 | + const [token, setToken] = useState(''); | |
6 | + const [userInfo, setUserInfo] = useState({}); | |
6 | 7 | |
7 | - return { token, setToken }; | |
8 | + const setUserToken = (token: string) => { | |
9 | + localStorage.setItem('token', token); | |
10 | + setToken(token); | |
11 | + }; | |
12 | + | |
13 | + const setUserLocalInfo = (token: string, userInfo: any) => { | |
14 | + localStorage.setItem('token', token); | |
15 | + setToken(token); | |
16 | + | |
17 | + localStorage.setItem('userInfo', JSON.stringify(userInfo)); | |
18 | + setUserInfo(userInfo); | |
19 | + }; | |
20 | + | |
21 | + return { | |
22 | + token, | |
23 | + setToken, | |
24 | + userInfo, | |
25 | + setUserInfo, | |
26 | + setUserToken, | |
27 | + setUserLocalInfo, | |
28 | + }; | |
8 | 29 | } | ... | ... |
src/pages/Login/index.tsx
1 | -import { LockOutlined, MobileOutlined, UserOutlined } from '@ant-design/icons'; | |
1 | +import { RESPONSE_CODE } from '@/constants/enum'; | |
2 | +import { | |
3 | + postOrderErpAuthLoginByPwd, | |
4 | + postOrderErpCaptchaGetImgCaptchaCode, | |
5 | +} from '@/services'; | |
6 | +import { LockOutlined, UserOutlined } from '@ant-design/icons'; | |
2 | 7 | import { |
3 | 8 | LoginForm, |
4 | 9 | ProConfigProvider, |
5 | - ProFormCaptcha, | |
6 | - ProFormCheckbox, | |
7 | 10 | ProFormText, |
8 | 11 | } from '@ant-design/pro-components'; |
9 | -import { history } from '@umijs/max'; | |
10 | -import { Tabs, message, theme } from 'antd'; | |
11 | -import { useState } from 'react'; | |
12 | - | |
13 | -type LoginType = 'phone' | 'account'; | |
12 | +import { history, useModel } from '@umijs/max'; | |
13 | +import { theme } from 'antd'; | |
14 | +import { useEffect, useState } from 'react'; | |
14 | 15 | |
15 | 16 | export default () => { |
17 | + const { setUserLocalInfo } = useModel('user'); | |
16 | 18 | const { token } = theme.useToken(); |
17 | - const [loginType, setLoginType] = useState<LoginType>('phone'); | |
19 | + const [code, setCode] = useState(''); | |
20 | + const [uuid, setUuid] = useState(''); | |
18 | 21 | |
22 | + const fetchCode = async () => { | |
23 | + const res = await postOrderErpCaptchaGetImgCaptchaCode(); | |
24 | + setCode(res.data.img); | |
25 | + setUuid(res.data.uuid); | |
26 | + }; | |
27 | + useEffect(() => { | |
28 | + fetchCode(); | |
29 | + }, []); | |
19 | 30 | return ( |
20 | 31 | <ProConfigProvider hashed={false}> |
21 | 32 | <div |
... | ... | @@ -25,114 +36,69 @@ export default () => { |
25 | 36 | <div className="flex items-center justify-center"> |
26 | 37 | <LoginForm |
27 | 38 | title="订单管理" |
28 | - onFinish={async () => { | |
29 | - history.push('/order'); | |
39 | + onFinish={async (values) => { | |
40 | + const res = await postOrderErpAuthLoginByPwd({ | |
41 | + data: { ...values, imgCaptchaUuid: uuid }, | |
42 | + }); | |
43 | + | |
44 | + setUserLocalInfo(res.data.token, res.data?.user); | |
45 | + if (res.result === RESPONSE_CODE.SUCCESS) { | |
46 | + history.push('/order'); | |
47 | + } | |
30 | 48 | }} |
31 | 49 | > |
32 | - <Tabs | |
33 | - centered | |
34 | - activeKey={loginType} | |
35 | - onChange={(activeKey) => setLoginType(activeKey as LoginType)} | |
36 | - > | |
37 | - <Tabs.TabPane key={'account'} tab={'账号密码登录'} /> | |
38 | - <Tabs.TabPane key={'phone'} tab={'手机号登录'} /> | |
39 | - </Tabs> | |
40 | - {loginType === 'account' && ( | |
41 | - <> | |
42 | - <ProFormText | |
43 | - name="username" | |
44 | - fieldProps={{ | |
45 | - size: 'large', | |
46 | - prefix: <UserOutlined className={'prefixIcon'} />, | |
47 | - }} | |
48 | - placeholder={'用户名'} | |
49 | - rules={[ | |
50 | - { | |
51 | - required: true, | |
52 | - message: '请输入用户名!', | |
53 | - }, | |
54 | - ]} | |
55 | - /> | |
56 | - <ProFormText.Password | |
57 | - name="password" | |
58 | - fieldProps={{ | |
59 | - size: 'large', | |
60 | - prefix: <LockOutlined className={'prefixIcon'} />, | |
61 | - }} | |
62 | - placeholder={'密码'} | |
63 | - rules={[ | |
64 | - { | |
65 | - required: true, | |
66 | - message: '请输入密码!', | |
67 | - }, | |
68 | - ]} | |
69 | - /> | |
70 | - </> | |
71 | - )} | |
72 | - {loginType === 'phone' && ( | |
73 | - <> | |
74 | - <ProFormText | |
75 | - fieldProps={{ | |
76 | - size: 'large', | |
77 | - prefix: <MobileOutlined className={'prefixIcon'} />, | |
78 | - }} | |
79 | - name="mobile" | |
80 | - placeholder={'手机号'} | |
81 | - rules={[ | |
82 | - { | |
83 | - required: true, | |
84 | - message: '请输入手机号!', | |
85 | - }, | |
86 | - { | |
87 | - pattern: /^1\d{10}$/, | |
88 | - message: '手机号格式错误!', | |
89 | - }, | |
90 | - ]} | |
91 | - /> | |
92 | - <ProFormCaptcha | |
93 | - fieldProps={{ | |
94 | - size: 'large', | |
95 | - prefix: <LockOutlined className={'prefixIcon'} />, | |
96 | - }} | |
97 | - captchaProps={{ | |
98 | - size: 'large', | |
99 | - }} | |
100 | - placeholder={'请输入验证码'} | |
101 | - captchaTextRender={(timing, count) => { | |
102 | - if (timing) { | |
103 | - return `${count} ${'获取验证码'}`; | |
104 | - } | |
105 | - return '获取验证码'; | |
106 | - }} | |
107 | - name="captcha" | |
108 | - rules={[ | |
109 | - { | |
110 | - required: true, | |
111 | - message: '请输入验证码!', | |
112 | - }, | |
113 | - ]} | |
114 | - onGetCaptcha={async () => { | |
115 | - message.success('获取验证码成功!验证码为:1234'); | |
116 | - }} | |
117 | - /> | |
118 | - </> | |
119 | - )} | |
120 | - <div | |
121 | - style={{ | |
122 | - marginBlockEnd: 24, | |
50 | + <div className="my-8"></div> | |
51 | + <ProFormText | |
52 | + name="userName" | |
53 | + fieldProps={{ | |
54 | + size: 'large', | |
55 | + prefix: <UserOutlined className={'prefixIcon'} />, | |
56 | + }} | |
57 | + placeholder={'用户名'} | |
58 | + rules={[ | |
59 | + { | |
60 | + required: true, | |
61 | + message: '请输入用户名!', | |
62 | + }, | |
63 | + ]} | |
64 | + /> | |
65 | + <ProFormText.Password | |
66 | + name="password" | |
67 | + fieldProps={{ | |
68 | + size: 'large', | |
69 | + prefix: <LockOutlined className={'prefixIcon'} />, | |
70 | + }} | |
71 | + placeholder={'密码'} | |
72 | + rules={[ | |
73 | + { | |
74 | + required: true, | |
75 | + message: '请输入密码!', | |
76 | + }, | |
77 | + ]} | |
78 | + /> | |
79 | + <ProFormText | |
80 | + name="imgCaptchaCode" | |
81 | + fieldProps={{ | |
82 | + size: 'large', | |
83 | + }} | |
84 | + placeholder={'验证码'} | |
85 | + rules={[ | |
86 | + { | |
87 | + required: true, | |
88 | + message: '请输入验证码!', | |
89 | + }, | |
90 | + ]} | |
91 | + /> | |
92 | + <img | |
93 | + src={code} | |
94 | + className="mb-4 cursor-pointer" | |
95 | + onClick={() => { | |
96 | + fetchCode(); | |
123 | 97 | }} |
124 | - > | |
125 | - <ProFormCheckbox noStyle name="autoLogin"> | |
126 | - 自动登录 | |
127 | - </ProFormCheckbox> | |
128 | - {/* <a | |
129 | - style={{ | |
130 | - float: 'right', | |
131 | - }} | |
132 | - > | |
133 | - 忘记密码 | |
134 | - </a> */} | |
135 | - </div> | |
98 | + /> | |
99 | + {/* <ProFormCheckbox noStyle name="autoLogin"> | |
100 | + 自动登录 | |
101 | + </ProFormCheckbox> */} | |
136 | 102 | </LoginForm> |
137 | 103 | </div> |
138 | 104 | </div> | ... | ... |