对接注册和退出登录

This commit is contained in:
linxd
2025-07-17 11:38:51 +08:00
parent baedd70f53
commit 46c9a0f679
18 changed files with 524 additions and 196 deletions

View File

@ -1,13 +1,18 @@
export default {
dev: {
// '/api/wfap/v1/audit/bill/find/by/procid': {
// target: 'http://10.242.37.148:8891/',//审批单 dev环境自动审批暂时用不到
// changeOrigin: true,
// pathRewrite: { '^': '' },
// },
'/api/v1': {
target: 'http://10.0.0.10:18030',// 茂
// target: 'http://10.0.0.14:18030',// 李
changeOrigin: true,
pathRewrite: { '^/api/v1': '/v1' },
},
'/api': {
// target: 'http://10.0.0.125:18012',//测试环境
target: 'http://10.0.0.10:18013',//连接天宫的ng
// target: 'http://10.242.37.148:18022',//
target: 'http://10.0.0.10:18013',//
// target: 'http://10.0.0.125:18012',// 测试
// target: 'http://10.0.0.14:18012',// 李
// target: 'http://10.0.0.14:18030',// 李
// target: 'http://10.0.0.46:18013',// 袁
changeOrigin: true,
pathRewrite: { '^/api': '' },
},

View File

@ -70,9 +70,11 @@
"array-move": "3.0.1",
"axios": "0.21.1",
"classnames": "2.3.1",
"dayjs": "^1.11.13",
"dva": "2.4.1",
"echarts": "^5.2.2",
"echarts-for-react": "^3.0.2",
"jsencrypt": "^3.3.2",
"lodash": "4.17.21",
"moment": "^2.29.4",
"omit.js": "2.0.2",

10
pnpm-lock.yaml generated
View File

@ -50,6 +50,9 @@ dependencies:
classnames:
specifier: 2.3.1
version: 2.3.1
dayjs:
specifier: ^1.11.13
version: 1.11.13
dva:
specifier: 2.4.1
version: 2.4.1(react-dom@16.14.0)(react@16.14.0)
@ -59,6 +62,9 @@ dependencies:
echarts-for-react:
specifier: ^3.0.2
version: 3.0.2(echarts@5.6.0)(react@16.14.0)
jsencrypt:
specifier: ^3.3.2
version: 3.3.2
lodash:
specifier: 4.17.21
version: 4.17.21
@ -10263,6 +10269,10 @@ packages:
- utf-8-validate
dev: true
/jsencrypt@3.3.2:
resolution: {integrity: sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A==}
dev: false
/jsesc@2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'}

View File

@ -1,18 +1,74 @@
import React from 'react';
import React, { useEffect } from 'react';
//导入logo图片
import LogoImg from '@/assets/img/logo.png';
// 引入样式文件
import './Header.less';
//导入菜单组件
import HeaderMenu from './HeaderMenu';
const Header: React.FC = (props) => {
import { connect, history } from 'umi';
import type { UserModelState } from '@/models/user';
import type { ConnectProps, Dispatch } from 'umi';
import { Button, Dropdown, message, Modal } from 'antd';
import { DownOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
interface PageProps extends ConnectProps {
user: UserModelState; // dva model状态
dispatch: Dispatch; // dva dispatch方法
}
const Header: React.FC<PageProps> = ({ user, dispatch }) => {
useEffect(() => {
if (user.token) {
dispatch({
type: 'user/fetchUserInfo',
});
}
}, [user.token]);
const handleMenuClick = (e: any) => {
if (e.key === 'logout') {
Modal.confirm({
title: '确定退出登录吗?',
icon: <ExclamationCircleOutlined />,
content: '退出登录后,您将需要重新登录',
onOk() {
dispatch({
type: 'user/logout',
}).then(() => {
sessionStorage.clear();
message.success('退出登录成功');
history.push('/index');
});
},
onCancel() {
return;
},
});
}
};
return (
<div className="header-container">
<div className="header">
<img className="logo" src={LogoImg} alt="logo" />
<HeaderMenu />
{user.userInfo?.fullName && (
<Dropdown
trigger={['hover']}
menu={{
items: [
{
key: 'logout',
label: '退出登录',
},
],
onClick: handleMenuClick,
}}
>
<Button type="link">
{`${user.userInfo?.fullName}`}
<DownOutlined />
</Button>
</Dropdown>
)}
</div>
</div>
);
};
export default Header;
export default connect(({ user }: { user: UserModelState }) => ({ user }))(Header);

View File

@ -4,6 +4,7 @@ import help from './en-US/help';
import policy from './en-US/policy';
import register from './en-US/register';
import home from './en-US/home';
import login from './en-US/login';
export default {
'menu.首页': 'Home',
@ -39,19 +40,6 @@ export default {
"加载更多":"Load More",
"登录/注册":"Login/Register",
// Login page
"login.title": "E-Bidding Platform",
"login.tab.supplier": "Supplier",
"login.tab.expert": "Expert",
"login.tab.agent": "Bidding Agent",
"login.username.placeholder": "Please enter username",
"login.password.placeholder": "Please enter password",
"login.remember": "Remember password",
"login.forgot": "Forgot password?",
"login.button": "Login",
"login.register.tip": "Don't have an account?",
"login.register.action": "Register Now",
"login.back.home": "Back to Home",
// Help Center module
...help,
@ -70,4 +58,7 @@ export default {
// Home module
...home,
// Login page
...login,
};

View File

@ -0,0 +1,16 @@
export default {
// Login page
"login.title": "E-Bidding Platform",
"login.tab.supplier": "Supplier",
"login.tab.expert": "Expert",
"login.tab.agent": "Bidding Agent",
"login.username.placeholder": "Please enter username",
"login.password.placeholder": "Please enter password",
"login.remember": "Remember me",
"login.forgot": "Forgot password?",
"login.button": "Login",
"login.register.tip": "Don't have an account?",
"login.register.action": "Register now",
"login.back.home": "Back to home",
"login.captcha.placeholder": "Please enter verification code",
};

View File

@ -4,6 +4,7 @@ import help from './zh-CN/help';
import policy from './zh-CN/policy';
import register from './zh-CN/register';
import home from './zh-CN/home';
import login from './zh-CN/login';
export default {
'menu.首页': '首页',
@ -39,19 +40,6 @@ export default {
"加载更多":"加载更多",
"登录/注册":"登录/注册",
// 登录页文案
"login.title": "电子招投标平台",
"login.tab.supplier": "供应商",
"login.tab.expert": "专家",
"login.tab.agent": "招标代理",
"login.username.placeholder": "请输入用户名",
"login.password.placeholder": "请输入密码",
"login.remember": "记住密码",
"login.forgot": "忘记密码?",
"login.button": "登录",
"login.register.tip": "还没有账号?",
"login.register.action": "立即注册",
"login.back.home": "返回首页",
// 帮助中心模块
...help,
@ -70,4 +58,7 @@ export default {
// Home module
...home,
// Login page
...login,
};

View File

@ -0,0 +1,16 @@
export default {
// 登录页文案
"login.title": "中远海运",
"login.tab.supplier": "供应商",
"login.tab.expert": "专家",
"login.tab.agent": "招标代理",
"login.username.placeholder": "请输入用户名",
"login.password.placeholder": "请输入密码",
"login.remember": "记住密码",
"login.forgot": "忘记密码?",
"login.button": "登录",
"login.register.tip": "还没有账号?",
"login.register.action": "立即注册",
"login.back.home": "返回首页",
"login.captcha.placeholder": "请输入验证码",
};

4
src/models/index.ts Normal file
View File

@ -0,0 +1,4 @@
import user from './user';
export default {
user,
};

103
src/models/user.ts Normal file
View File

@ -0,0 +1,103 @@
import type { Effect, Reducer } from 'umi';
import { getUserinfo, Logout } from '@/servers/api/login';
export type SupplierUser = {
email?: string;
mobile?: string;
name?: string;
sex?: string;
status?: number;
userId?: string;
userName?: string;
};
export type User = {
userId: string;
userName: string;
userType: string;
};
export type UserInfo = {
userId: string;
fullName: string;
loginName: string;
userType: string;
authorityList: { roleId: string, roleName: string, roleCode: string, roleScope: string }[];
};
export type UserModelState = {
supplierUser?: SupplierUser;
user?: User;
token?: string;
userInfo?: UserInfo;
};
export type UserModelType = {
namespace: 'user';
state: UserModelState;
effects: {
fetchUserInfo: Effect;
logout: Effect;
};
reducers: {
saveLoginUser: Reducer<UserModelState>;
saveUserInfo: Reducer<UserModelState>;
clearUserInfo: Reducer;
};
};
const UserModel: UserModelType = {
namespace: 'user',
state: {
supplierUser: {}, // 登录返回的供应商用户信息
user: undefined, // 登录返回的用户信息
token: sessionStorage.getItem('token') || '', // 登录返回的token
userInfo: undefined, // 请求userInfo返回的用户信息
},
effects: {
*fetchUserInfo(_, { call, put }) {
const response = yield call(getUserinfo);
yield put({
type: 'saveUserInfo',
payload: response,
});
},
*logout(_, { call, put }) {
yield call(Logout);
yield put({
type: 'clearUserInfo'
});
},
},
reducers: {
clearUserInfo(state) {
return {
...state,
userInfo: undefined,
token: '',
supplierUser: {},
user: {},
};
},
saveLoginUser(state, action) {
return {
...state,
supplierUser: action.payload.supplierUser || {},
user: action.payload.user || {},
token: action.payload.token || '',
};
},
saveUserInfo(state, action) {
return {
...state,
userInfo: action.payload || {},
};
},
}
};
export default UserModel;

View File

@ -31,70 +31,43 @@
}
.noticeList {
padding: 10px 0;
.noticeTitle {
font-size: 22px;
display: flex;
gap: 20px;
align-items: center;
.noticeName {
font-size: 18px;
font-weight: 600;
color: @main-color;
padding: 10px 7px;
color: @main-danger-color;
width: 50px;
line-height: 20px;
text-align: center;
}
.noticeItem {
background-color: #fff;
padding: 24px;
border-radius: 16px;
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.05);
height: 249px;
.title {
margin: 14px 0;
font-size: 20px;
font-weight: 600;
// 超过两行显示省略号
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
height: 63px;
}
.content{
font-size: 16px;
color: @main-text-color-2;
// 超过两行显示省略号
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.button{
color: @main-color;
font-size: 16px;
margin-top: 14px;
cursor: pointer;
}
.header {
margin-right: 20px;
flex: 1;
width: 0;
.cardTitle {
display: flex;
justify-content: space-between;
align-items: center;
.time {
font-size: 14px;
.cardTitleText {
font-size: 18px;
font-weight: 600;
color: @main-color;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
.cardTitleTime {
color: @main-text-color-2;
}
.type {
display: inline-block;
background-color: @main-color;
color: #fff;
font-size: 12px;
padding: 4px 8px;
border-radius: 20px;
&.primary {
background-color: rgba(59, 130, 246, 0.1);
color: #3b82f6;
}
&.danger {
background-color: rgba(255, 77, 77, 0.1);
color: #ff4d4d;
}
}
.cardContent {
color: @main-text-color-2;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin-bottom: 0;
}
}
}

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { Card, Row, Col, Tabs, Table, Button, Space } from 'antd';
import { useIntl, Link, history } from 'umi';
import { useIntl, Link, history, connect } from 'umi';
import './index.less';
import IconFont from '@/components/IconFont/IconFont';
import Search from '../announce/Search';
@ -12,7 +12,8 @@ import { getAboutUs } from '@/servers/api/about';
// 获取通知公告
import { getNoticeList } from '@/servers/api/notice';
import { filterHtmlTag } from '@/utils/utils';
const IndexPage: React.FC = () => {
const IndexPage: React.FC<any> = ({ user }) => {
const token = user.token;
const intl = useIntl();
const [noticeLoading, setNoticeLoading] = useState(false);
// 友情链接
@ -186,7 +187,29 @@ const IndexPage: React.FC = () => {
return (
<div>
<img className="banner" src={require('@/assets/img/banner.jpg')} alt="" />
{/* 通知列表 */}
<div className="noticeList layout-content-main">
<div className="noticeName"></div>
{noticeList.map((item) => (
<div className="noticeItem" key={item.id}>
<div className="cardTitle">
<span
className="cardTitleText"
onClick={() => {
history.push({
pathname: '/announce/announceInfo',
search: '?id=' + item.id,
});
}}
>
{item.title}
</span>
<span className="cardTitleTime">{item.publishTime}</span>
</div>
<p className="cardContent" dangerouslySetInnerHTML={{ __html: item.content }} />
</div>
))}
</div>
<div className="loginType">
<div className="layout-content-main">
<Row gutter={20}>
@ -242,49 +265,6 @@ const IndexPage: React.FC = () => {
</div>
</div>
{/* 通知列表 */}
<div className="noticeList">
<div className="layout-content-main">
<div className="noticeTitle">
</div>
<Row gutter={32}>
{noticeList.map((item) => (
<Col span={6} key={item.id}>
<div className="noticeItem" >
<div className='header'>
<span className='time'>{item.publishTime}</span>
<span className={`type ${item.columnType === 'notice' ? 'primary' : 'danger'}`}>{item.columnType === 'notice' ? '公告' : '通知'}</span>
</div>
<div className='title'>{item[intl.formatMessage({ id: 'notice.data.title' }) as keyof typeof item]}</div>
<div className='content'>{filterHtmlTag(item[intl.formatMessage({ id: 'notice.data.content' }) as keyof typeof item] || '')}</div>
<div className="button" onClick={() => {
history.push({
pathname: '/announce/announceInfo',
search: '?id=' + item.id,
});
}}>{intl.formatMessage({ id: 'notice.detail' })}&gt;</div>
{/* <div className="cardTitle">
<span
className="cardTitleText"
onClick={() => {
history.push({
pathname: '/announce/announceInfo',
search: '?id=' + item.id,
});
}}
>
{item.title}
</span>
<span className="cardTitleTime">{item.time}</span>
</div> */}
{/* <p className="cardContent">{item.content}</p> */}
</div>
</Col>
))}
</Row>
</div>
</div>
<div className="layout-content-main announce">
<Row gutter={40}>
<Col span={5}>
@ -393,4 +373,6 @@ const IndexPage: React.FC = () => {
);
};
export default IndexPage;
export default connect(({ user }: any) => ({
user,
}))(IndexPage);

View File

@ -1,26 +1,57 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Form, Input, Button, Checkbox, Tabs, message } from 'antd';
import { UserOutlined, LockOutlined, EyeInvisibleOutlined, EyeTwoTone, HomeOutlined } from '@ant-design/icons';
import { history, useIntl } from 'umi';
import {
UserOutlined,
LockOutlined,
EyeInvisibleOutlined,
EyeTwoTone,
HomeOutlined,
} from '@ant-design/icons';
import { history, useIntl, connect } from 'umi';
import type { ConnectProps, Dispatch } from 'umi';
import './login.less';
import { getCaptcha, supplierLogin, getUserinfo, findMenuList } from '@/servers/api/login';
import { encryptWithRsa } from '@/utils/encryptWithRsa';
import type { UserModelState } from '@/models/user';
const { TabPane } = Tabs;
const LoginPage: React.FC = () => {
interface PageProps extends ConnectProps {
user: UserModelState; // dva model状态
dispatch: Dispatch; // dva dispatch方法
}
const LoginPage: React.FC<PageProps> = ({ user, dispatch }) => {
const [activeKey, setActiveKey] = useState('supplier');
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const intl = useIntl();
const onFinish = (values: any) => {
const [captchaImg, setCaptchaImg] = useState('');
const [captchaKey, setCaptchaKey] = useState('');
const onFinish = async (values: any) => {
setLoading(true);
console.log('登录信息:', values);
// 这里添加登录逻辑
setTimeout(() => {
setLoading(false);
try {
const params = {
...values,
password: encryptWithRsa(values.password, false),
encryptValue: encryptWithRsa(values.identifying),
};
const loginRes = await supplierLogin(params);
if (loginRes.code === 200) {
sessionStorage.setItem('token', loginRes.data.token);
//存入供应商用户id
sessionStorage.setItem('userId', loginRes.data.supplierUser.userId);
sessionStorage.setItem('currentUser', JSON.stringify(loginRes.data));
dispatch({
type: 'user/saveLoginUser',
payload: loginRes.data,
})
message.success('登录成功');
history.push('/index');
}, 1000);
} else {
message.error(loginRes.message || '登录失败');
}
} finally {
setLoading(false);
}
};
const handleTabChange = (key: string) => {
@ -52,42 +83,55 @@ const LoginPage: React.FC = () => {
return (
<div className="register-link">
{intl.formatMessage({ id: 'login.register.tip' })}
<a onClick={handleRegister}>
{intl.formatMessage({ id: 'login.register.action' })}
</a>
<a onClick={handleRegister}>{intl.formatMessage({ id: 'login.register.action' })}</a>
</div>
);
};
// 获取验证码
const fetchCaptcha = async () => {
const res = await getCaptcha();
if (res.code === 200) {
setCaptchaImg(res.data.base64Image);
setCaptchaKey(res.data.code);
}
};
useEffect(() => {
fetchCaptcha();
}, [activeKey]);
return (
<div className='login-page'>
<div className='login-container'>
<div className='back-home'>
<div className="login-page">
<div className="login-container">
<div className="back-home">
<a onClick={() => history.push('/index')}>
<HomeOutlined /> {intl.formatMessage({ id: 'login.back.home' })}
</a>
</div>
<div className='login-title'>{intl.formatMessage({ id: 'login.title' })}</div>
<div className="login-title">{intl.formatMessage({ id: 'login.title' })}</div>
<div className="login-tab-container">
{/* <div className="login-tab-container">
<Tabs activeKey={activeKey} onChange={handleTabChange} className='login-tabs'>
<TabPane tab={intl.formatMessage({ id: 'login.tab.supplier' })} key="supplier" />
<TabPane tab={intl.formatMessage({ id: 'login.tab.expert' })} key="expert" />
<TabPane tab={intl.formatMessage({ id: 'login.tab.agent' })} key="agent" />
</Tabs>
</div>
</div> */}
<Form
form={form}
name="login"
className='login-form'
className="login-form"
initialValues={{ remember: false }}
onFinish={onFinish}
>
<Form.Item
name="username"
rules={[{ required: true, message: intl.formatMessage({ id: 'login.username.placeholder' }) + '!' }]}
name="account"
rules={[
{
required: true,
message: intl.formatMessage({ id: 'login.username.placeholder' }) + '!',
},
]}
>
<Input
prefix={<UserOutlined className="site-form-item-icon" />}
@ -98,18 +142,48 @@ const LoginPage: React.FC = () => {
<Form.Item
name="password"
rules={[{ required: true, message: intl.formatMessage({ id: 'login.password.placeholder' }) + '!' }]}
rules={[
{
required: true,
message: intl.formatMessage({ id: 'login.password.placeholder' }) + '!',
},
]}
>
<Input.Password
prefix={<LockOutlined className="site-form-item-icon" />}
placeholder={intl.formatMessage({ id: 'login.password.placeholder' })}
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
iconRender={(visible) => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
size="large"
/>
</Form.Item>
<Form.Item
name="identifying"
rules={[
{
required: true,
message: intl.formatMessage({ id: 'login.captcha.placeholder' }) + '!',
},
]}
>
<Input
placeholder={intl.formatMessage({ id: 'login.captcha.placeholder' })}
size="large"
maxLength={6}
autoComplete="off"
prefix={null}
suffix={
<img
src={`data:image/png;base64,${captchaImg}`}
alt="验证码"
style={{ cursor: 'pointer', height: 32, verticalAlign: 'middle' }}
onClick={fetchCaptcha}
/>
}
/>
</Form.Item>
<Form.Item>
<div className='login-options'>
<div className="login-options">
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox>{intl.formatMessage({ id: 'login.remember' })}</Checkbox>
</Form.Item>
@ -120,7 +194,13 @@ const LoginPage: React.FC = () => {
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login-form-button" loading={loading} size="large">
<Button
type="primary"
htmlType="submit"
className="login-form-button"
loading={loading}
size="large"
>
{intl.formatMessage({ id: 'login.button' })}
</Button>
{renderRegisterLink()}
@ -131,4 +211,4 @@ const LoginPage: React.FC = () => {
);
};
export default LoginPage;
export default connect(({ user }: { user: UserModelState }) => ({ user }))(LoginPage);

73
src/servers/api/login.ts Normal file
View File

@ -0,0 +1,73 @@
import request from '@/utils/request';
/**
* 验证码
*/
export async function getCaptcha() {
return request('/v1/login/getCaptcha', {
method: 'GET'
});
}
/**
* 招标代理
*/
export async function accountLogin (data: API.LoginSupplier) {
return request('/v1/login/accountLogin', {
method: 'POST',
data
});
}
/**
* 专家
*/
export async function expertLogin (data: API.LoginSupplier) {
return request('/v1/login/expertLogin', {
method: 'POST',
data
});
}
/**
* 供应商
*/
export async function supplierLogin (data: API.LoginSupplier) {
return request('/v1/login/accountLogin/supplier', {
method: 'POST',
data
});
}
/**
* 用户信息
*/
export async function getUserinfo() {
return request('/v1/userinfo/get', {
method: 'GET'
});
}
/**
* 退出
*/
export async function Logout() {
return request('/v1/login/logout', {
method: 'POST'
});
}
/**
* 路由
*/
export async function findMenuList(data: any) {
return request('/v1/menu/findMenuList', {
method: 'POST',
data
});
}
/**
* 部门
*/
export async function queryUserOrgAll() {
return request('/org/queryUserOrgAll', {
method: 'GET'
});
}

View File

@ -368,4 +368,11 @@ declare namespace API {
thumbnail: string;
url: string;
}
//登录
interface LoginSupplier {
account: string;
password: string;
identifying: string;
encryptValue: string;
}
}

View File

@ -0,0 +1,21 @@
import JSEncrypt from 'jsencrypt';
import dayjs from 'dayjs';
const PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvLBkALIYR/x9Rv5TiXQGWAXTzraN/He80r9gQovSQ5oTP8qllL9+Oc1LdTijPFRsddHWg37umvFliwhmukU1NT+o2loGcKpyMHFkc/UPNjQLvd+YFR4nYhgP8l+dmRNOtQWawOt5dbksRKTghMjA+FKT2+itMsawSs1+Ic+zoIwIDAQAB
-----END PUBLIC KEY-----`;
export function encryptWithRsa(value: string, type: boolean = true, publicKey: string = PUBLIC_KEY): string {
const nowStr = dayjs().format('YYYY-MM-DD HH:mm:ss');
const content = type? `${value}_${nowStr}`: value;
const encryptor = new JSEncrypt();
encryptor.setPublicKey(publicKey);
const encrypted = encryptor.encrypt(content);
if (!encrypted) {
throw new Error('RSA 加密失败');
}
return encrypted;
}

View File

@ -57,24 +57,20 @@ const request = extend({
credentials: 'include' // 默认请求是否带上cookie
});
// request拦截器, 改变url 或 options.
request.interceptors.request.use(async (url, options) => {
if (
options.method === 'post' ||
options.method === 'put' ||
options.method === 'delete' ||
options.method === 'get'
) {
//如果是获取token的url则不加token
// headers = {
// Authorization: getUserToken() == null ? null : getUserToken(),
// JwtToken: getSessionUserData() == null ? null : getSessionUserData().userId,
// ...options.headers
// }
// options.headers = headers;
}
request.interceptors.request.use((url: string, options: any) => {
// 获取 token
const token = sessionStorage.getItem('token');
const userId = sessionStorage.getItem('userId');
return {
url,
options: { ...options },
options: {
...options,
headers: {
...(options.headers || {}),
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(userId ? { Mall3Check: `${userId}` } : {}),
},
},
};
});
//response拦截

View File

@ -1,13 +1,15 @@
import React from 'react';
import { Redirect } from 'umi';
import { message } from 'antd';
import { connect, Redirect, history } from 'umi';
import { message, Modal } from 'antd';
// 权限校验
export default (props: any) => {
if (localStorage.getItem('token')) {
return <div>{props.children}</div>;
const AuthWrapper = ({ user, children }: any) => {
if (user.token) {
return <div>{children}</div>;
} else {
// 提示后跳转
message.error('请先登录');
return <Redirect to="/login" />;
}
};
export default connect(({ user }: any) => ({
user,
}))(AuthWrapper);