import config from '@/config' import { getToken, getRefreshToken, removeToken, setToken } from '@/utils/auth' import errorCode from '@/utils/errorCode' 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) => void reject: (reason?: any) => void }> = [] export const SERVER_BASE_URL_STORAGE_KEY = 'serverBaseUrl' export function getBaseUrl() { return uni.getStorageSync(SERVER_BASE_URL_STORAGE_KEY) || config.baseUrl } 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) { requestConfig.header!['Authorization'] = 'Bearer ' + getToken() } const method = (requestConfig.method || 'GET').toUpperCase() if ((method === 'POST' || method === 'PUT') && requestConfig.data) { requestConfig.header!['Content-Type'] = 'application/json' } if (requestConfig.params) { let url = requestConfig.url + '?' + tansParams(requestConfig.params) url = url.slice(0, -1) requestConfig.url = url } 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((resolve, reject) => { uni.request({ method: 'POST', timeout, url: getBaseUrl() + '/admin-api/system/auth/refresh-token?refreshToken=' + encodeURIComponent(refreshTokenValue), header: { tenantId: '1' }, dataType: 'json' }).then(response => { const data = (response as any).data const code = data.code || 200 if (code === 200 || code === 0) { resolve(data.data) return } reject(data) }) .catch(error => { reject(error) }) }) } 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(config: RequestConfig): Promise> { if (!getRefreshToken()) { return handleAuthorized() } if (!isRefreshToken) { isRefreshToken = true try { const tokenData = await refreshToken() setToken(tokenData) isRefreshToken = false retryRequestList() return sendRequest(config) } catch (error) { rejectRequestList(error) return handleAuthorized() } finally { isRefreshToken = false } } return new Promise((resolve, reject) => { requestList.push({ config, resolve: resolve as (value: ResponseData) => void, reject }) }) } async function sendRequest(config: RequestConfig): Promise> { 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 = response.data as ResponseData const code = data.code || 200 // @ts-ignore const msg: string = errorCode[code] || data.msg || errorCode['default'] if (code === 401) { return handleRefreshToken(config) } else if (code === 500) { toast(msg) throw data } else if (code !== 200 && code !== 0) { toast(msg) throw code } return data } const request = (config: RequestConfig): Promise> => { const shouldShowLoading = config.showLoading !== false if (shouldShowLoading) { modal.loading(config.loadingText || '加载中...') } return sendRequest(config) .finally(() => { if (shouldShowLoading) { modal.closeLoading() } }) } export function postAction(url: string, data?: any, isToken: boolean = true) { return request({ data, url, method: 'POST', headers: { isToken }, }) } export function getAction(url: string, params?: any, isToken: boolean = true) { return request({ params, url, method: 'GET', headers: { isToken }, }) } export function putAction(url: string, data?: any, isToken: boolean = true) { return request({ data, url, method: 'PUT', headers: { isToken }, }) } export function deleteAction(url: string, data?: any, isToken: boolean = true) { return request({ data, url, method: 'DELETE', headers: { isToken }, }) } export default request