Merge pull request 'feat: 退出登录和token失效的处理' (#38) from dev-zw into dev
|
@ -163,4 +163,5 @@ export default defineConfig({
|
|||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
// plugins: ['umi-plugin-keep-alive'],
|
||||
});
|
||||
|
|
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.4 KiB |
|
@ -133,22 +133,7 @@ export const layout: RunTimeLayoutConfig = ({ initialState }) => {
|
|||
// 增加一个 loading 的状态
|
||||
childrenRender: (children) => {
|
||||
// if (initialState?.loading) return <PageLoading />;
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
{/* <SettingDrawer
|
||||
disableUrlParams
|
||||
enableDarkTheme
|
||||
settings={initialState?.settings}
|
||||
onSettingChange={(settings) => {
|
||||
setInitialState((preInitialState) => ({
|
||||
...preInitialState,
|
||||
settings,
|
||||
}));
|
||||
}}
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
return <>{children}</>;
|
||||
},
|
||||
...initialState?.settings,
|
||||
};
|
||||
|
|
|
@ -17,13 +17,8 @@ const HeaderDropdown: React.FC<HeaderDropdownProps> = ({ overlayClassName: cls,
|
|||
},
|
||||
};
|
||||
});
|
||||
return (
|
||||
<Dropdown
|
||||
overlayClassName={classNames(className, cls)}
|
||||
getPopupContainer={(target) => target.parentElement || document.body}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
|
||||
return <Dropdown overlayClassName={classNames(className, cls)} {...restProps} />;
|
||||
};
|
||||
|
||||
export default HeaderDropdown;
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { clearSessionToken } from '@/access';
|
||||
import { PageEnum } from '@/enums/pagesEnums';
|
||||
import { setRemoteMenu } from '@/services/session';
|
||||
import { logout } from '@/services/system/auth';
|
||||
import { gotoLoginPage } from '@/utils/ui';
|
||||
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { setAlpha } from '@ant-design/pro-components';
|
||||
import { useEmotionCss } from '@ant-design/use-emotion-css';
|
||||
import { history, useModel } from '@umijs/max';
|
||||
import { Avatar, Spin } from 'antd';
|
||||
import { stringify } from 'querystring';
|
||||
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||
import React, { useCallback } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
|
@ -23,7 +22,7 @@ const Name = () => {
|
|||
|
||||
const nameClassName = useEmotionCss(({ token }) => {
|
||||
return {
|
||||
width: '70px',
|
||||
// width: '70px',
|
||||
height: '48px',
|
||||
overflow: 'hidden',
|
||||
lineHeight: '48px',
|
||||
|
@ -64,19 +63,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
|
|||
await logout();
|
||||
clearSessionToken();
|
||||
setRemoteMenu(null);
|
||||
const { search, pathname } = window.location;
|
||||
const urlParams = new URL(window.location.href).searchParams;
|
||||
/** 此方法会跳转到 redirect 参数所在的位置 */
|
||||
const redirect = urlParams.get('redirect');
|
||||
// Note: There may be security issues, please note
|
||||
if (window.location.pathname !== PageEnum.LOGIN && !redirect) {
|
||||
history.replace({
|
||||
pathname: PageEnum.LOGIN,
|
||||
search: stringify({
|
||||
redirect: pathname + search,
|
||||
}),
|
||||
});
|
||||
}
|
||||
gotoLoginPage();
|
||||
};
|
||||
const actionClassName = useEmotionCss(({ token }) => {
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||
import { useEmotionCss } from '@ant-design/use-emotion-css';
|
||||
import { SelectLang, useModel } from '@umijs/max';
|
||||
import { useModel } from '@umijs/max';
|
||||
import React from 'react';
|
||||
import Avatar from './AvatarDropdown';
|
||||
|
||||
|
@ -17,21 +16,21 @@ const GlobalHeaderRight: React.FC = () => {
|
|||
};
|
||||
});
|
||||
|
||||
const actionClassName = useEmotionCss(({ token }) => {
|
||||
return {
|
||||
display: 'flex',
|
||||
float: 'right',
|
||||
height: '48px',
|
||||
marginLeft: 'auto',
|
||||
overflow: 'hidden',
|
||||
cursor: 'pointer',
|
||||
padding: '0 12px',
|
||||
borderRadius: token.borderRadius,
|
||||
'&:hover': {
|
||||
backgroundColor: token.colorBgTextHover,
|
||||
},
|
||||
};
|
||||
});
|
||||
// const actionClassName = useEmotionCss(({ token }) => {
|
||||
// return {
|
||||
// display: 'flex',
|
||||
// float: 'right',
|
||||
// height: '48px',
|
||||
// marginLeft: 'auto',
|
||||
// overflow: 'hidden',
|
||||
// cursor: 'pointer',
|
||||
// padding: '0 12px',
|
||||
// borderRadius: token.borderRadius,
|
||||
// '&:hover': {
|
||||
// backgroundColor: token.colorBgTextHover,
|
||||
// },
|
||||
// };
|
||||
// });
|
||||
|
||||
const { initialState } = useModel('@@initialState');
|
||||
|
||||
|
@ -41,15 +40,15 @@ const GlobalHeaderRight: React.FC = () => {
|
|||
|
||||
return (
|
||||
<div className={className}>
|
||||
<span
|
||||
{/* <span
|
||||
className={actionClassName}
|
||||
onClick={() => {
|
||||
window.open('https://pro.ant.design/docs/getting-started');
|
||||
}}
|
||||
>
|
||||
<QuestionCircleOutlined />
|
||||
</span>
|
||||
<Avatar menu={true} />
|
||||
</span> */}
|
||||
<Avatar menu={false} />
|
||||
{/* <SelectLang className={actionClassName} /> */}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -144,8 +144,15 @@ function AddExperimentModal({
|
|||
label="实验描述"
|
||||
name="description"
|
||||
rules={[{ required: true, message: '请输入实验描述' }]}
|
||||
style={{ marginBottom: '48px' }}
|
||||
>
|
||||
<Input placeholder="请输入实验描述" maxLength={128} showCount allowClear />
|
||||
<Input.TextArea
|
||||
placeholder="请输入实验描述"
|
||||
maxLength={128}
|
||||
autoSize={{ minRows: 2, maxRows: 5 }}
|
||||
showCount
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="选择流水线"
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
import type { RequestConfig } from '@umijs/max';
|
||||
import { message } from 'antd';
|
||||
import { clearSessionToken, getAccessToken, getRefreshToken, getTokenExpireTime } from './access';
|
||||
|
||||
const checkRegion = 5 * 60 * 1000;
|
||||
import { setRemoteMenu } from './services/session';
|
||||
import { gotoLoginPage } from './utils/ui';
|
||||
|
||||
/**
|
||||
* Umi Max 网络请求配置
|
||||
|
@ -25,10 +25,8 @@ export const requestConfig: RequestConfig = {
|
|||
if (expireTime) {
|
||||
const left = Number(expireTime) - new Date().getTime();
|
||||
const refreshToken = getRefreshToken();
|
||||
if (left < checkRegion && refreshToken) {
|
||||
if (left < 0) {
|
||||
clearSessionToken();
|
||||
}
|
||||
if (left < 0 && refreshToken) {
|
||||
clearSessionToken();
|
||||
} else {
|
||||
const accessToken = getAccessToken();
|
||||
if (accessToken) {
|
||||
|
@ -45,15 +43,19 @@ export const requestConfig: RequestConfig = {
|
|||
responseInterceptors: [
|
||||
(response: any) => {
|
||||
const { status, data } = response;
|
||||
// console.log('response', response);
|
||||
if (status >= 200 && status < 300 && data && (data instanceof Blob || data.code === 200)) {
|
||||
return response;
|
||||
} else {
|
||||
if (data && data.msg) {
|
||||
message.error(data.msg);
|
||||
if (status >= 200 && status < 300) {
|
||||
if (data && (data instanceof Blob || data.code === 200)) {
|
||||
return response;
|
||||
} else if (data && data.code === 401) {
|
||||
clearSessionToken();
|
||||
setRemoteMenu(null);
|
||||
gotoLoginPage(false);
|
||||
} else {
|
||||
message.error('请求失败');
|
||||
message.error(data?.msg ?? '请求失败');
|
||||
return Promise.reject(response);
|
||||
}
|
||||
} else {
|
||||
message.error('请求失败');
|
||||
return Promise.reject(response);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { createIcon } from '@/utils/IconUtil';
|
||||
import { MenuDataItem } from '@ant-design/pro-components';
|
||||
import { request } from '@umijs/max';
|
||||
import React, { lazy } from 'react';
|
||||
import { createFromIconfontCN } from '@ant-design/icons';
|
||||
|
||||
let remoteMenu: any = null;
|
||||
|
||||
export function getRemoteMenu() {
|
||||
|
@ -101,7 +100,7 @@ export function convertCompatRouters(childrens: API.RoutersMenuItem[]): any[] {
|
|||
return {
|
||||
path: item.path,
|
||||
// icon:'icon-a-057_fenlei',
|
||||
icon: 'icon-'+item.meta.icon,
|
||||
icon: 'icon-' + item.meta.icon,
|
||||
// icon: item.meta.icon,
|
||||
name: item.meta.title,
|
||||
routes: item.children ? convertCompatRouters(item.children) : undefined,
|
||||
|
|
|
@ -28,8 +28,8 @@ export async function login(body: API.LoginParams, options?: Record<string, any>
|
|||
|
||||
/** 退出登录接口 POST /api/login/outLogin */
|
||||
export async function logout() {
|
||||
return request<Record<string, any>>('/api/logout', {
|
||||
method: 'delete',
|
||||
return request<Record<string, any>>('/api/auth/logout', {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
* @Date: 2024-04-19 14:42:51
|
||||
* @Description: UI 公共方法
|
||||
*/
|
||||
import { PageEnum } from '@/enums/pagesEnums';
|
||||
import themes from '@/styles/theme.less';
|
||||
import { history } from '@umijs/max';
|
||||
import { Modal, type ModalFuncProps, type UploadFile } from 'antd';
|
||||
|
||||
// 自定义 Confirm 弹框
|
||||
|
@ -43,3 +45,17 @@ export const getFileListFromEvent = (e: any) => {
|
|||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
// 去登录页面
|
||||
export const gotoLoginPage = (toHome: boolean = true) => {
|
||||
const { search, pathname } = window.location;
|
||||
const urlParams = new URLSearchParams();
|
||||
urlParams.append('redirect', pathname + search);
|
||||
const newSearch = toHome ? '' : urlParams.toString();
|
||||
if (window.location.pathname !== PageEnum.LOGIN) {
|
||||
history.replace({
|
||||
pathname: PageEnum.LOGIN,
|
||||
search: newSearch,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|