Browse Source

feat: 退出登录和token失效的处理

pull/38/head
cp3hnu 1 year ago
parent
commit
e76ab23cf0
10 changed files with 68 additions and 78 deletions
  1. +1
    -0
      react-ui/config/config.ts
  2. +1
    -16
      react-ui/src/app.tsx
  3. +2
    -7
      react-ui/src/components/HeaderDropdown/index.tsx
  4. +3
    -16
      react-ui/src/components/RightContent/AvatarDropdown.tsx
  5. +19
    -20
      react-ui/src/components/RightContent/index.tsx
  6. +7
    -1
      react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx
  7. +15
    -13
      react-ui/src/requestConfig.ts
  8. +2
    -3
      react-ui/src/services/session.ts
  9. +2
    -2
      react-ui/src/services/system/auth.ts
  10. +16
    -0
      react-ui/src/utils/ui.tsx

+ 1
- 0
react-ui/config/config.ts View File

@@ -163,4 +163,5 @@ export default defineConfig({
},
javascriptEnabled: true,
},
// plugins: ['umi-plugin-keep-alive'],
});

+ 1
- 16
react-ui/src/app.tsx View File

@@ -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,
};


+ 2
- 7
react-ui/src/components/HeaderDropdown/index.tsx View File

@@ -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;

+ 3
- 16
react-ui/src/components/RightContent/AvatarDropdown.tsx View File

@@ -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 {


+ 19
- 20
react-ui/src/components/RightContent/index.tsx View File

@@ -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>
);


+ 7
- 1
react-ui/src/pages/Experiment/experimentText/addExperimentModal.tsx View File

@@ -145,7 +145,13 @@ function AddExperimentModal({
name="description"
rules={[{ required: true, message: '请输入实验描述' }]}
>
<Input placeholder="请输入实验描述" maxLength={128} showCount allowClear />
<Input.TextArea
placeholder="请输入实验描述"
maxLength={128}
autoSize={{ minRows: 2, maxRows: 5 }}
showCount
allowClear
/>
</Form.Item>
<Form.Item
label="选择流水线"


+ 15
- 13
react-ui/src/requestConfig.ts View File

@@ -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);
}
},


+ 2
- 3
react-ui/src/services/session.ts View File

@@ -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,


+ 2
- 2
react-ui/src/services/system/auth.ts View File

@@ -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',
});
}



+ 16
- 0
react-ui/src/utils/ui.tsx View File

@@ -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,
});
}
};

Loading…
Cancel
Save