This commit is contained in:
parent
42f950f819
commit
e3bd397248
@ -287,6 +287,12 @@ const local: App.I18n.Schema = {
|
|||||||
superAdminVisible: 'Super Admin Visible',
|
superAdminVisible: 'Super Admin Visible',
|
||||||
adminVisible: 'Admin Visible',
|
adminVisible: 'Admin Visible',
|
||||||
adminOrUserVisible: 'Admin and User Visible'
|
adminOrUserVisible: 'Admin and User Visible'
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
repeatedErrorOccurOnce: 'Repeated Request Error Occurs Once',
|
||||||
|
repeatedError: 'Repeated Request Error',
|
||||||
|
repeatedErrorMsg1: 'Custom Request Error 1',
|
||||||
|
repeatedErrorMsg2: 'Custom Request Error 2'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
|
@ -287,6 +287,12 @@ const local: App.I18n.Schema = {
|
|||||||
superAdminVisible: '超级管理员可见',
|
superAdminVisible: '超级管理员可见',
|
||||||
adminVisible: '管理员可见',
|
adminVisible: '管理员可见',
|
||||||
adminOrUserVisible: '管理员和用户可见'
|
adminOrUserVisible: '管理员和用户可见'
|
||||||
|
},
|
||||||
|
request: {
|
||||||
|
repeatedErrorOccurOnce: '重复请求错误只出现一次',
|
||||||
|
repeatedError: '重复请求错误',
|
||||||
|
repeatedErrorMsg1: '自定义请求错误 1',
|
||||||
|
repeatedErrorMsg2: '自定义请求错误 2'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
manage: {
|
manage: {
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
import type { AxiosResponse } from 'axios';
|
import type { AxiosResponse } from 'axios';
|
||||||
import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios';
|
import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios';
|
||||||
import { useAuthStore } from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
|
import { $t } from '@/locales';
|
||||||
import { localStg } from '@/utils/storage';
|
import { localStg } from '@/utils/storage';
|
||||||
import { getServiceBaseURL } from '@/utils/service';
|
import { getServiceBaseURL } from '@/utils/service';
|
||||||
import { $t } from '@/locales';
|
import { handleRefreshToken, showErrorMsg } from './shared';
|
||||||
import { handleRefreshToken } from './shared';
|
import type { RequestInstanceState } from './type';
|
||||||
|
|
||||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||||
const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||||
|
|
||||||
interface InstanceState {
|
export const request = createFlatRequest<App.Service.Response, RequestInstanceState>(
|
||||||
/** whether the request is refreshing token */
|
|
||||||
isRefreshingToken: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const request = createFlatRequest<App.Service.Response, InstanceState>(
|
|
||||||
{
|
{
|
||||||
baseURL,
|
baseURL,
|
||||||
headers: {
|
headers: {
|
||||||
@ -35,7 +31,7 @@ export const request = createFlatRequest<App.Service.Response, InstanceState>(
|
|||||||
isBackendSuccess(response) {
|
isBackendSuccess(response) {
|
||||||
// when the backend response code is "0000"(default), it means the request is success
|
// when the backend response code is "0000"(default), it means the request is success
|
||||||
// to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file
|
// to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file
|
||||||
return response.data.code === import.meta.env.VITE_SERVICE_SUCCESS_CODE;
|
return String(response.data.code) === import.meta.env.VITE_SERVICE_SUCCESS_CODE;
|
||||||
},
|
},
|
||||||
async onBackendFail(response, instance) {
|
async onBackendFail(response, instance) {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
@ -47,6 +43,8 @@ export const request = createFlatRequest<App.Service.Response, InstanceState>(
|
|||||||
function logoutAndCleanup() {
|
function logoutAndCleanup() {
|
||||||
handleLogout();
|
handleLogout();
|
||||||
window.removeEventListener('beforeunload', handleLogout);
|
window.removeEventListener('beforeunload', handleLogout);
|
||||||
|
|
||||||
|
request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== response.data.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
// when the backend response code is in `logoutCodes`, it means the user will be logged out and redirected to login page
|
||||||
@ -58,13 +56,15 @@ export const request = createFlatRequest<App.Service.Response, InstanceState>(
|
|||||||
|
|
||||||
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
// when the backend response code is in `modalLogoutCodes`, it means the user will be logged out by displaying a modal
|
||||||
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
|
||||||
if (modalLogoutCodes.includes(response.data.code)) {
|
if (modalLogoutCodes.includes(response.data.code) && !request.state.errMsgStack?.includes(response.data.msg)) {
|
||||||
|
request.state.errMsgStack = [...(request.state.errMsgStack || []), response.data.msg];
|
||||||
|
|
||||||
// prevent the user from refreshing the page
|
// prevent the user from refreshing the page
|
||||||
window.addEventListener('beforeunload', handleLogout);
|
window.addEventListener('beforeunload', handleLogout);
|
||||||
|
|
||||||
window.$dialog?.error({
|
window.$dialog?.error({
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
content: response.data.msg,
|
content: response.data.code,
|
||||||
positiveText: $t('common.confirm'),
|
positiveText: $t('common.confirm'),
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
onPositiveClick() {
|
onPositiveClick() {
|
||||||
@ -122,7 +122,7 @@ export const request = createFlatRequest<App.Service.Response, InstanceState>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.$message?.error?.(message);
|
showErrorMsg(request.state, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import type { AxiosRequestConfig } from 'axios';
|
|||||||
import { useAuthStore } from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
import { localStg } from '@/utils/storage';
|
import { localStg } from '@/utils/storage';
|
||||||
import { fetchRefreshToken } from '../api';
|
import { fetchRefreshToken } from '../api';
|
||||||
|
import type { RequestInstanceState } from './type';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh token
|
* refresh token
|
||||||
@ -29,3 +30,25 @@ export async function handleRefreshToken(axiosConfig: AxiosRequestConfig) {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function showErrorMsg(state: RequestInstanceState, message: string) {
|
||||||
|
if (!state.errMsgStack?.length) {
|
||||||
|
state.errMsgStack = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const isExist = state.errMsgStack.includes(message);
|
||||||
|
|
||||||
|
if (!isExist) {
|
||||||
|
state.errMsgStack.push(message);
|
||||||
|
|
||||||
|
window.$message?.error(message, {
|
||||||
|
onLeave: () => {
|
||||||
|
state.errMsgStack = state.errMsgStack.filter(msg => msg !== message);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
state.errMsgStack = [];
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
src/service/request/type.ts
Normal file
6
src/service/request/type.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export interface RequestInstanceState {
|
||||||
|
/** whether the request is refreshing token */
|
||||||
|
isRefreshingToken: boolean;
|
||||||
|
/** the request error message stack */
|
||||||
|
errMsgStack: string[];
|
||||||
|
}
|
6
src/typings/app.d.ts
vendored
6
src/typings/app.d.ts
vendored
@ -472,6 +472,12 @@ declare namespace App {
|
|||||||
adminVisible: string;
|
adminVisible: string;
|
||||||
adminOrUserVisible: string;
|
adminOrUserVisible: string;
|
||||||
};
|
};
|
||||||
|
request: {
|
||||||
|
repeatedErrorOccurOnce: string;
|
||||||
|
repeatedError: string;
|
||||||
|
repeatedErrorMsg1: string;
|
||||||
|
repeatedErrorMsg2: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
manage: {
|
manage: {
|
||||||
common: {
|
common: {
|
||||||
|
@ -13,6 +13,25 @@ async function logoutWithModal() {
|
|||||||
async function refreshToken() {
|
async function refreshToken() {
|
||||||
await fetchCustomBackendError('9999', $t('request.tokenExpired'));
|
await fetchCustomBackendError('9999', $t('request.tokenExpired'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleRepeatedMessageError() {
|
||||||
|
await Promise.all([
|
||||||
|
fetchCustomBackendError('2222', $t('page.function.request.repeatedErrorMsg1')),
|
||||||
|
fetchCustomBackendError('2222', $t('page.function.request.repeatedErrorMsg1')),
|
||||||
|
fetchCustomBackendError('2222', $t('page.function.request.repeatedErrorMsg1')),
|
||||||
|
fetchCustomBackendError('3333', $t('page.function.request.repeatedErrorMsg2')),
|
||||||
|
fetchCustomBackendError('3333', $t('page.function.request.repeatedErrorMsg2')),
|
||||||
|
fetchCustomBackendError('3333', $t('page.function.request.repeatedErrorMsg2'))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleRepeatedModalError() {
|
||||||
|
await Promise.all([
|
||||||
|
fetchCustomBackendError('7777', $t('request.logoutWithModalMsg')),
|
||||||
|
fetchCustomBackendError('7777', $t('request.logoutWithModalMsg')),
|
||||||
|
fetchCustomBackendError('7777', $t('request.logoutWithModalMsg'))
|
||||||
|
]);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -26,6 +45,18 @@ async function refreshToken() {
|
|||||||
<NCard :title="$t('request.refreshToken')" :bordered="false" size="small" segmented class="card-wrapper">
|
<NCard :title="$t('request.refreshToken')" :bordered="false" size="small" segmented class="card-wrapper">
|
||||||
<NButton @click="refreshToken">{{ $t('common.trigger') }}</NButton>
|
<NButton @click="refreshToken">{{ $t('common.trigger') }}</NButton>
|
||||||
</NCard>
|
</NCard>
|
||||||
|
<NCard
|
||||||
|
:title="$t('page.function.request.repeatedErrorOccurOnce')"
|
||||||
|
:bordered="false"
|
||||||
|
size="small"
|
||||||
|
segmented
|
||||||
|
class="card-wrapper"
|
||||||
|
>
|
||||||
|
<NButton @click="handleRepeatedMessageError">{{ $t('page.function.request.repeatedError') }}(Message)</NButton>
|
||||||
|
<NButton class="ml-12px" @click="handleRepeatedModalError">
|
||||||
|
{{ $t('page.function.request.repeatedError') }}(Modal)
|
||||||
|
</NButton>
|
||||||
|
</NCard>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user