feat:添加30分钟token过期后重新获取新token逻辑

master
黄伟杰 5 days ago
parent 9003a038cf
commit e2af9d1719

@ -23,7 +23,8 @@
},
/* */
"modules" : {
"Camera" : {}
"Camera" : {},
"Push" : {}
},
/* */
"distribute" : {
@ -55,7 +56,8 @@
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
"ad" : {},
"push" : {}
},
"icons" : {
"android" : {

@ -39,7 +39,7 @@ const useUserStore = defineStore("user", {
return new Promise((resolve, reject) => {
login(username, password, code, uuid,tenantName, captchaVerification,rememberMe)
.then((res: any) => {
setToken(res.data.accessToken);
setToken(res.data);
this.token = res.data.accessToken;
this.permissionInfoLoaded = false;
clearPermissionInfoCache();
@ -74,7 +74,7 @@ const useUserStore = defineStore("user", {
initAllDict().catch(() => {});
resolve(res);
})
.catch((error) => {
.catch((error: any) => {
this.permissionInfoLoaded = false;
reject(error);
});

@ -1,13 +1,31 @@
const TokenKey = 'App-Token'
const RefreshTokenKey = 'App-Refresh-Token'
export function getToken():string {
export function getToken(): string {
return uni.getStorageSync(TokenKey)
}
export function setToken(token:string) {
return uni.setStorageSync(TokenKey, token)
export function getRefreshToken(): string {
return uni.getStorageSync(RefreshTokenKey)
}
interface TokenInfo {
accessToken: string
refreshToken?: string
}
export function setToken(token: string | TokenInfo) {
if (typeof token === 'string') {
return uni.setStorageSync(TokenKey, token)
}
uni.setStorageSync(TokenKey, token.accessToken)
if (token.refreshToken) {
uni.setStorageSync(RefreshTokenKey, token.refreshToken)
}
}
export function removeToken() {
return uni.removeStorageSync(TokenKey)
uni.removeStorageSync(TokenKey)
uni.removeStorageSync(RefreshTokenKey)
}

@ -1,11 +1,18 @@
import config from '@/config'
import { getToken, removeToken } from '@/utils/auth'
import { getToken, getRefreshToken, removeToken, setToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { toast, showConfirm, tansParams } from '@/utils/common'
import { toast, tansParams } from '@/utils/common'
import { RequestConfig, ResponseData } from '@/types/request'
import modal from '@/plugins/modal'
let timeout = 300000
let isRefreshToken = false
let isRelogin = false
let requestList: Array<{
config: RequestConfig
resolve: (value: ResponseData<any>) => void
reject: (reason?: any) => void
}> = []
export const SERVER_BASE_URL_STORAGE_KEY = 'serverBaseUrl'
@ -13,92 +20,177 @@ export function getBaseUrl() {
return uni.getStorageSync(SERVER_BASE_URL_STORAGE_KEY) || config.baseUrl
}
const request = <T>(config: RequestConfig): Promise<ResponseData<T>> => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
config.header = config.header || {}
config.header['tenantId'] = '1'
function prepareConfig(config: RequestConfig): RequestConfig {
const requestConfig: RequestConfig = {
...config,
header: {
...(config.header || {})
}
}
const isToken = (requestConfig.headers || {}).isToken === false
requestConfig.header!['tenantId'] = '1'
if (getToken() && !isToken) {
config.header['Authorization'] = 'Bearer ' + getToken()
requestConfig.header!['Authorization'] = 'Bearer ' + getToken()
}
// POST/PUT 请求明确设置 Content-Type 为 application/json
if ((config.method === 'POST' || config.method === 'PUT') && config.data) {
config.header['Content-Type'] = 'application/json'
const method = (requestConfig.method || 'GET').toUpperCase()
if ((method === 'POST' || method === 'PUT') && requestConfig.data) {
requestConfig.header!['Content-Type'] = 'application/json'
}
// get请求映射params参数
if (config.params) {
let url = config.url + '?' + tansParams(config.params)
if (requestConfig.params) {
let url = requestConfig.url + '?' + tansParams(requestConfig.params)
url = url.slice(0, -1)
config.url = url
requestConfig.url = url
}
return new Promise((resolve, reject) => {
const shouldShowLoading = config.showLoading !== false
if (shouldShowLoading) {
modal.loading(config.loadingText || '加载中')
}
return requestConfig
}
function handleRequestError(error: any) {
let { message } = error
if (message === 'Network Error') {
message = '后端接口连接异常'
} else if (message && message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message && message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
toast(message)
}
function handleAuthorized() {
if (!isRelogin) {
isRelogin = true
removeToken()
uni.reLaunch({
url: '/pages/login',
complete: () => {
isRelogin = false
}
})
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
}
function refreshToken() {
const refreshTokenValue = getRefreshToken()
return new Promise<any>((resolve, reject) => {
uni.request({
method: config.method || 'GET',
timeout: config.timeout || timeout,
url: (config.baseUrl || getBaseUrl()) + config.url,
data: config.data,
header: config.header,
method: 'POST',
timeout,
url: getBaseUrl() + '/admin-api/system/auth/refresh-token?refreshToken=' + encodeURIComponent(refreshTokenValue),
header: {
tenantId: '1'
},
dataType: 'json'
}).then(response => {
/* let [error, res] = response
if (error) {
toast('后端接口连接异常')
reject('后端接口连接异常')
return
} */
const res = response
const data: ResponseData<T> = res.data as ResponseData<T>
const data = (response as any).data
const code = data.code || 200
// @ts-ignore
const msg: string = errorCode[code] || data.msg || errorCode['default']
if (code === 401) {
// showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
// if (res.confirm) {
// useUserStore().logOut().then(res => {
// uni.reLaunch({ url: '/pages/login' })
// })
// }
// })
reject('无效的会话,或者会话已过期,请重新登录。')
removeToken()
uni.reLaunch({ url: '/pages/login' })
return
} else if (code === 500) {
toast(msg)
// 将完整的 data 对象 reject便于调用方拿到后端错误信息
reject(data)
return
} else if (code !== 200) {
toast(msg)
reject(code)
if (code === 200 || code === 0) {
resolve(data.data)
return
}
resolve(data)
reject(data)
})
.catch(error => {
let { message } = error
if (message === 'Network Error') {
message = '后端接口连接异常'
} else if (message.includes('timeout')) {
message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常'
}
toast(message)
reject(error)
})
.finally(() => {
if (shouldShowLoading) {
modal.closeLoading()
}
})
})
}
function retryRequestList() {
requestList.forEach(item => {
sendRequest(item.config).then(item.resolve).catch(item.reject)
})
requestList = []
}
function rejectRequestList(error: any) {
requestList.forEach(item => {
item.reject(error)
})
requestList = []
}
async function handleRefreshToken<T>(config: RequestConfig): Promise<ResponseData<T>> {
if (!getRefreshToken()) {
return handleAuthorized()
}
if (!isRefreshToken) {
isRefreshToken = true
try {
const tokenData = await refreshToken()
setToken(tokenData)
isRefreshToken = false
retryRequestList()
return sendRequest<T>(config)
} catch (error) {
rejectRequestList(error)
return handleAuthorized()
} finally {
isRefreshToken = false
}
}
return new Promise((resolve, reject) => {
requestList.push({
config,
resolve: resolve as (value: ResponseData<any>) => void,
reject
})
})
}
async function sendRequest<T>(config: RequestConfig): Promise<ResponseData<T>> {
const requestConfig = prepareConfig(config)
let response: any
try {
response = await uni.request({
method: (requestConfig.method || 'GET').toUpperCase() as any,
timeout: requestConfig.timeout || timeout,
url: (requestConfig.baseUrl || getBaseUrl()) + requestConfig.url,
data: requestConfig.data,
header: requestConfig.header,
dataType: 'json'
})
} catch (error) {
handleRequestError(error)
throw error
}
const data: ResponseData<T> = response.data as ResponseData<T>
const code = data.code || 200
// @ts-ignore
const msg: string = errorCode[code] || data.msg || errorCode['default']
if (code === 401) {
return handleRefreshToken<T>(config)
} else if (code === 500) {
toast(msg)
throw data
} else if (code !== 200 && code !== 0) {
toast(msg)
throw code
}
return data
}
const request = <T>(config: RequestConfig): Promise<ResponseData<T>> => {
const shouldShowLoading = config.showLoading !== false
if (shouldShowLoading) {
modal.loading(config.loadingText || '加载中...')
}
return sendRequest<T>(config)
.finally(() => {
if (shouldShowLoading) {
modal.closeLoading()
}
})
}
export function postAction(url: string, data?: any, isToken: boolean = true) {
return request({ data, url, method: 'POST', headers: { isToken }, })
}

Loading…
Cancel
Save