Commit 312df31cf00709b19f1d098a8423b8b46e3be29a

Authored by sanmu
1 parent 73fd7ef2

feat: add login

.umirc.ts
@@ -12,11 +12,11 @@ export default defineConfig({ @@ -12,11 +12,11 @@ export default defineConfig({
12 title: '订单管理系统', 12 title: '订单管理系统',
13 }, 13 },
14 proxy: { 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 changeOrigin: true, 18 changeOrigin: true,
19 - // pathRewrite: { '^/api': '' }, 19 + pathRewrite: { '^/api': '' },
20 }, 20 },
21 }, 21 },
22 routes: [ 22 routes: [
README.md
@@ -29,4 +29,6 @@ @@ -29,4 +29,6 @@
29 29
30 # 校验没生效 30 # 校验没生效
31 31
32 -chmod +x .husky/commit-msg chmod +x .husky/pre-commit 32 +chmod +x .husky/commit-msg
  33 +
  34 +chmod +x .husky/pre-commit
src/app.ts
1 // 运行时配置 1 // 运行时配置
2 2
3 -import { RequestConfig } from '@umijs/max'; 3 +import { RequestConfig, history } from '@umijs/max';
4 4
5 import '@inspir/assembly-css/dist/special.css'; 5 import '@inspir/assembly-css/dist/special.css';
6 import { message } from 'antd'; 6 import { message } from 'antd';
@@ -34,10 +34,11 @@ export const request: RequestConfig = { @@ -34,10 +34,11 @@ export const request: RequestConfig = {
34 if (response && response.status) { 34 if (response && response.status) {
35 // 401重定向 35 // 401重定向
36 if (response.status === 401) { 36 if (response.status === 401) {
37 - if (!location.pathname.includes(loginPath)) { 37 + if (!location.pathname.includes('login')) {
38 localStorage.removeItem('token'); 38 localStorage.removeItem('token');
  39 + localStorage.removeItem('userInfo');
39 message.error('token失效,请重新登录!'); 40 message.error('token失效,请重新登录!');
40 - // history.push(loginPath); 41 + history.push('/login');
41 return null; 42 return null;
42 } 43 }
43 } 44 }
@@ -74,7 +75,7 @@ export const request: RequestConfig = { @@ -74,7 +75,7 @@ export const request: RequestConfig = {
74 } 75 }
75 76
76 return { 77 return {
77 - url, 78 + url: '/api' + url,
78 options: { 79 options: {
79 ...options, 80 ...options,
80 signal, 81 signal,
@@ -93,6 +94,7 @@ export const request: RequestConfig = { @@ -93,6 +94,7 @@ export const request: RequestConfig = {
93 if (data.result !== RESPONSE_CODE.SUCCESS) { 94 if (data.result !== RESPONSE_CODE.SUCCESS) {
94 message.error(data.message); 95 message.error(data.message);
95 } 96 }
  97 +
96 // do something 98 // do something
97 return response; 99 return response;
98 }, 100 },
src/models/user.ts
@@ -2,7 +2,28 @@ import { useState } from 'react'; @@ -2,7 +2,28 @@ import { useState } from 'react';
2 2
3 // src/models/userModel.ts 3 // src/models/userModel.ts
4 export default function Page() { 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 import { 7 import {
3 LoginForm, 8 LoginForm,
4 ProConfigProvider, 9 ProConfigProvider,
5 - ProFormCaptcha,  
6 - ProFormCheckbox,  
7 ProFormText, 10 ProFormText,
8 } from '@ant-design/pro-components'; 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 export default () => { 16 export default () => {
  17 + const { setUserLocalInfo } = useModel('user');
16 const { token } = theme.useToken(); 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 return ( 30 return (
20 <ProConfigProvider hashed={false}> 31 <ProConfigProvider hashed={false}>
21 <div 32 <div
@@ -25,114 +36,69 @@ export default () =&gt; { @@ -25,114 +36,69 @@ export default () =&gt; {
25 <div className="flex items-center justify-center"> 36 <div className="flex items-center justify-center">
26 <LoginForm 37 <LoginForm
27 title="订单管理" 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 </LoginForm> 102 </LoginForm>
137 </div> 103 </div>
138 </div> 104 </div>