mirror of
https://gitee.com/dapppp/ruoyi-plus-vben5.git
synced 2025-12-30 09:42:25 +00:00
refactor: 登录超时逻辑
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
import { requestClient } from './request';
|
||||
|
||||
/**
|
||||
@@ -26,3 +32,35 @@ export function commonExport(url: string, data: Record<string, any>) {
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义一个401专用异常 用于可能会用到的区分场景?
|
||||
*/
|
||||
export class UnauthorizedException extends Error {}
|
||||
|
||||
/**
|
||||
* 是否已经处在登出过程中了 一个标志位
|
||||
* 主要是防止一个页面会请求多个api 都401 会导致登出执行多次
|
||||
*/
|
||||
let isLogoutProcessing = false;
|
||||
|
||||
/**
|
||||
* 登出逻辑 两个地方用到 提取出来
|
||||
* @throws UnauthorizedException 抛出特定的异常
|
||||
*/
|
||||
export function handleUnauthorizedLogout() {
|
||||
const timeoutMsg = $t('http.loginTimeout');
|
||||
|
||||
// 已经在登出过程中 不再执行
|
||||
if (isLogoutProcessing) {
|
||||
throw new UnauthorizedException(timeoutMsg);
|
||||
}
|
||||
isLogoutProcessing = true;
|
||||
const userStore = useAuthStore();
|
||||
userStore.logout().finally(() => {
|
||||
message.error(timeoutMsg);
|
||||
isLogoutProcessing = false;
|
||||
});
|
||||
// 不再执行下面逻辑
|
||||
throw new UnauthorizedException(timeoutMsg);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import type { HttpResponse } from '@vben/request';
|
||||
|
||||
import { BUSINESS_SUCCESS_CODE, UNAUTHORIZED_CODE } from '@vben/constants';
|
||||
import { useAppConfig } from '@vben/hooks';
|
||||
import { $t } from '@vben/locales';
|
||||
import { preferences } from '@vben/preferences';
|
||||
@@ -28,22 +29,13 @@ import {
|
||||
} from '#/utils/encryption/crypto';
|
||||
import * as encryptUtil from '#/utils/encryption/jsencrypt';
|
||||
|
||||
import { handleUnauthorizedLogout } from './helper';
|
||||
|
||||
const { apiURL, clientId, enableEncrypt } = useAppConfig(
|
||||
import.meta.env,
|
||||
import.meta.env.PROD,
|
||||
);
|
||||
|
||||
/**
|
||||
* 是否已经处在登出过程中了 一个标志位
|
||||
* 主要是防止一个页面会请求多个api 都401 会导致登出执行多次
|
||||
*/
|
||||
let isLogoutProcessing = false;
|
||||
|
||||
/**
|
||||
* 定义一个401专用异常 用于可能会用到的区分场景?
|
||||
*/
|
||||
export class UnauthorizedException extends Error {}
|
||||
|
||||
function createRequestClient(baseURL: string) {
|
||||
const client = new RequestClient({
|
||||
// 后端地址
|
||||
@@ -173,21 +165,38 @@ function createRequestClient(baseURL: string) {
|
||||
// 不进行任何处理,直接返回
|
||||
// 用于页面代码可能需要直接获取code,data,message这些信息时开启
|
||||
if (!isTransformResponse) {
|
||||
/**
|
||||
* 需要判断下载二进制的情况 正常是返回二进制 报错会返回json
|
||||
* 当type为blob且content-type为application/json时 则判断已经下载出错
|
||||
*/
|
||||
if (
|
||||
response.config.responseType === 'blob' &&
|
||||
response.headers['content-type']?.includes?.('application/json')
|
||||
) {
|
||||
// 这时候的data为blob类型
|
||||
const blob = response.data as unknown as Blob;
|
||||
// 拿到字符串转json对象
|
||||
response.data = JSON.parse(await blob.text());
|
||||
// 然后按正常逻辑执行下面的代码(判断业务状态码)
|
||||
// json数据的判断
|
||||
if (response.headers['content-type']?.includes?.('application/json')) {
|
||||
/**
|
||||
* 需要判断是否登录超时/401
|
||||
* 执行登出操作
|
||||
*/
|
||||
const resp = response.data as unknown as HttpResponse;
|
||||
// 抛出异常 不再执行
|
||||
if (
|
||||
typeof resp === 'object' &&
|
||||
Reflect.has(resp, 'code') &&
|
||||
resp.code === UNAUTHORIZED_CODE
|
||||
) {
|
||||
handleUnauthorizedLogout();
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要判断下载二进制的情况 正常是返回二进制 报错会返回json
|
||||
* 当type为blob且content-type为application/json时 则判断已经下载出错
|
||||
*/
|
||||
if (response.config.responseType === 'blob') {
|
||||
// 这时候的data为blob类型
|
||||
const blob = response.data as unknown as Blob;
|
||||
// 拿到字符串转json对象
|
||||
response.data = JSON.parse(await blob.text());
|
||||
// 然后按正常逻辑执行下面的代码(判断业务状态码)
|
||||
} else {
|
||||
// 其他类型数据 直接返回
|
||||
return response.data;
|
||||
}
|
||||
} else {
|
||||
// 其他情况 直接返回
|
||||
// 非json数据 直接返回 不做校验
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
@@ -200,8 +209,10 @@ function createRequestClient(baseURL: string) {
|
||||
// 后端并没有采用严格的{code, msg, data}模式
|
||||
const { code, data, msg, ...other } = axiosResponseData;
|
||||
|
||||
// 业务状态码为200则请求成功
|
||||
const hasSuccess = Reflect.has(axiosResponseData, 'code') && code === 200;
|
||||
// 业务状态码为200 则请求成功
|
||||
const hasSuccess =
|
||||
Reflect.has(axiosResponseData, 'code') &&
|
||||
code === BUSINESS_SUCCESS_CODE;
|
||||
if (hasSuccess) {
|
||||
let successMsg = msg;
|
||||
|
||||
@@ -230,20 +241,10 @@ function createRequestClient(baseURL: string) {
|
||||
// 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
|
||||
let timeoutMsg = '';
|
||||
switch (code) {
|
||||
case 401: {
|
||||
// 已经在登出过程中 不再执行
|
||||
if (isLogoutProcessing) {
|
||||
throw new UnauthorizedException(timeoutMsg);
|
||||
}
|
||||
isLogoutProcessing = true;
|
||||
const _msg = $t('http.loginTimeout');
|
||||
const userStore = useAuthStore();
|
||||
userStore.logout().finally(() => {
|
||||
message.error(_msg);
|
||||
isLogoutProcessing = false;
|
||||
});
|
||||
// 不再执行下面逻辑
|
||||
throw new UnauthorizedException(_msg);
|
||||
// 登录超时
|
||||
case UNAUTHORIZED_CODE: {
|
||||
handleUnauthorizedLogout();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (msg) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UnauthorizedException } from '#/api/request';
|
||||
import { UnauthorizedException } from '#/api/helper';
|
||||
import { dictDataInfo } from '#/api/system/dict/dict-data';
|
||||
import { useDictStore } from '#/store/dict';
|
||||
|
||||
|
||||
@@ -26,3 +26,13 @@ export const SUPPORT_LANGUAGES: LanguageOption[] = [
|
||||
* 默认租户ID
|
||||
*/
|
||||
export const DEFAULT_TENANT_ID = '000000';
|
||||
|
||||
/**
|
||||
* 业务成功 状态码
|
||||
*/
|
||||
export const BUSINESS_SUCCESS_CODE = 200;
|
||||
|
||||
/**
|
||||
* 未授权 状态码(登录超时)
|
||||
*/
|
||||
export const UNAUTHORIZED_CODE = 401;
|
||||
|
||||
Reference in New Issue
Block a user