chore: initial import
This commit is contained in:
210
utils/request.js
Normal file
210
utils/request.js
Normal file
@@ -0,0 +1,210 @@
|
||||
import { config } from '../config.js'
|
||||
import { clearLoginSession, getAuthToken } from './app-state'
|
||||
import { getCurrentLanguage } from './i18n'
|
||||
|
||||
const API_BASE_URL = config.baseURL
|
||||
const FILE_BASE_URL = config.filePrefix
|
||||
const FIXED_PROVIDER_TYPE = 'WechatMiniProgram'
|
||||
|
||||
function getRequestText(key = '') {
|
||||
const language = getCurrentLanguage()
|
||||
const isEn = language === 'en'
|
||||
const map = {
|
||||
requestFailed: isEn ? 'Request failed' : '请求失败',
|
||||
loginExpired: isEn ? 'Login expired. Please sign in again' : '登录已过期,请重新登录',
|
||||
tooManyRequests: isEn ? 'Too many requests. Please try again later' : '操作太频繁了,请稍后再试',
|
||||
networkFailed: isEn ? 'Network request failed' : '网络请求失败'
|
||||
}
|
||||
return map[key] || ''
|
||||
}
|
||||
|
||||
function normalizeUrl(url = '') {
|
||||
if (/^https?:\/\//i.test(url)) {
|
||||
return url
|
||||
}
|
||||
if (!url) {
|
||||
return API_BASE_URL
|
||||
}
|
||||
if (url.startsWith('/')) {
|
||||
return `${API_BASE_URL}${url}`
|
||||
}
|
||||
return `${API_BASE_URL}/${url}`
|
||||
}
|
||||
|
||||
function isPlainRequestObject(value) {
|
||||
return !!value && typeof value === 'object' && !Array.isArray(value)
|
||||
}
|
||||
|
||||
function appendFixedProviderType(payload) {
|
||||
if (isPlainRequestObject(payload)) {
|
||||
return {
|
||||
...payload,
|
||||
ProviderType: FIXED_PROVIDER_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
ProviderType: FIXED_PROVIDER_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
function hasBusinessCode(payload) {
|
||||
return !!payload && typeof payload === 'object' && Object.prototype.hasOwnProperty.call(payload, 'code')
|
||||
}
|
||||
|
||||
function isBusinessSuccess(payload) {
|
||||
if (!hasBusinessCode(payload)) {
|
||||
return true
|
||||
}
|
||||
|
||||
const code = String(payload.code)
|
||||
return code === '200' || code === '0'
|
||||
}
|
||||
|
||||
function normalizeBusinessError(payload, fallback = {}) {
|
||||
const message = (payload && (payload.msg || payload.message)) || fallback.errMsg || getRequestText('requestFailed')
|
||||
return {
|
||||
...fallback,
|
||||
...(payload && typeof payload === 'object' ? payload : {}),
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentRoute() {
|
||||
const pages = getCurrentPages()
|
||||
if (!Array.isArray(pages) || !pages.length) {
|
||||
return ''
|
||||
}
|
||||
const currentPage = pages[pages.length - 1] || {}
|
||||
return currentPage.route || ''
|
||||
}
|
||||
|
||||
function shouldSkipUnauthorizedRedirect() {
|
||||
const route = getCurrentRoute()
|
||||
return route === 'pkgAccount/login/login' || route === 'pages/login/index' || route === 'pages/login/login'
|
||||
}
|
||||
|
||||
function handleUnauthorized(responseData) {
|
||||
clearLoginSession()
|
||||
|
||||
if (shouldSkipUnauthorizedRedirect()) {
|
||||
return
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
title: getRequestText('loginExpired'),
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pkgAccount/login/login'
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
|
||||
export function request(options = {}) {
|
||||
const {
|
||||
url = '',
|
||||
method = 'GET',
|
||||
data,
|
||||
params,
|
||||
header = {},
|
||||
hideErrorToast = false,
|
||||
withAuth = true
|
||||
} = options
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const token = withAuth ? getAuthToken() : ''
|
||||
const uppercaseMethod = String(method || 'GET').toUpperCase()
|
||||
const normalizedParams = appendFixedProviderType(params)
|
||||
const normalizedData = appendFixedProviderType(data)
|
||||
uni.request({
|
||||
url: normalizeUrl(url),
|
||||
method: uppercaseMethod,
|
||||
data: uppercaseMethod === 'GET'
|
||||
? (params !== undefined ? normalizedParams : normalizedData)
|
||||
: normalizedData,
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Requested-Language': getCurrentLanguage(),
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
...header
|
||||
},
|
||||
success: (res) => {
|
||||
const { statusCode, data: responseData } = res
|
||||
if ((statusCode === 401) || (responseData && Number(responseData.code) === 401)) {
|
||||
handleUnauthorized(responseData)
|
||||
reject(normalizeBusinessError(responseData, res))
|
||||
return
|
||||
}
|
||||
|
||||
if (statusCode === 429) {
|
||||
if (!hideErrorToast) {
|
||||
uni.showToast({
|
||||
title: getRequestText('tooManyRequests'),
|
||||
icon: 'none',
|
||||
duration: 2500
|
||||
})
|
||||
}
|
||||
reject({
|
||||
...normalizeBusinessError(responseData, res),
|
||||
message: getRequestText('tooManyRequests'),
|
||||
__toastShown: !hideErrorToast
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (statusCode >= 200 && statusCode < 300) {
|
||||
if (isBusinessSuccess(responseData)) {
|
||||
resolve(responseData)
|
||||
return
|
||||
}
|
||||
|
||||
const businessError = normalizeBusinessError(responseData, res)
|
||||
if (!hideErrorToast) {
|
||||
uni.showToast({
|
||||
title: businessError.message || getRequestText('requestFailed'),
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
reject({
|
||||
...businessError,
|
||||
__toastShown: !hideErrorToast
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const requestError = normalizeBusinessError(responseData, res)
|
||||
if (!hideErrorToast) {
|
||||
uni.showToast({
|
||||
title: requestError.message || getRequestText('requestFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
reject({
|
||||
...requestError,
|
||||
__toastShown: !hideErrorToast
|
||||
})
|
||||
},
|
||||
fail: (error) => {
|
||||
const requestError = normalizeBusinessError(null, error)
|
||||
if (!hideErrorToast) {
|
||||
uni.showToast({
|
||||
title: requestError.message || getRequestText('networkFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
reject({
|
||||
...requestError,
|
||||
__toastShown: !hideErrorToast
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export { API_BASE_URL, FILE_BASE_URL }
|
||||
export default request
|
||||
Reference in New Issue
Block a user