Files
MrleeAdmin/frontend/app/utils/request.js
T

201 lines
5.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import config from '@/config/index.js'
function buildUrl(url, baseURL = config.baseURL) {
const normalizedBaseURL = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL
const path = url.startsWith('/') ? url : `/${url}`
return `${normalizedBaseURL}${path}`
}
function getNetworkErrorMessage(error) {
const errorMessage = String(error?.errMsg || '')
if (errorMessage.toLowerCase().includes('timeout')) {
return '请求超时,请稍后重试'
}
return '无法连接服务器,请检查网络后重试'
}
function getHeaders(headers = {}, includeJsonContentType = true) {
const token = uni.getStorageSync(config.tokenKey)
const result = {
...(includeJsonContentType ? { 'Content-Type': 'application/json' } : {}),
[config.channelHeaderKey]: config.channel,
...headers
}
if (token) {
result[config.tokenHeaderKey] = String(token).startsWith('Bearer ') ? token : `Bearer ${token}`
}
return result
}
async function refreshAccessToken() {
const refreshToken = uni.getStorageSync('scanapp_refresh_token')
if (!refreshToken) return ''
const response = await uniRequest('/auth/refresh', 'POST', { refresh_token: refreshToken }, {
baseURL: config.apiBaseURL,
showError: false
})
const accessToken = response?.access_token
if (!accessToken) return ''
uni.setStorageSync(config.tokenKey, accessToken)
if (response.refresh_token) uni.setStorageSync('scanapp_refresh_token', response.refresh_token)
return accessToken
}
function uniRequest(url, method, data = {}, options = {}) {
return new Promise((resolve, reject) => {
const requestUrl = buildUrl(url, options.baseURL || config.baseURL)
uni.request({
url: requestUrl,
method,
data,
header: getHeaders(options.headers),
timeout: options.timeout || 15000,
success: (res) => {
let body = res.data || {}
if (typeof body === 'string') {
try { body = JSON.parse(body) } catch { body = { msg: body } }
}
if (Number(body.code) === 0) {
resolve(body.data)
return
}
reject(new Error(body.msg || '请求失败'))
},
fail: () => reject(new Error('网络请求失败'))
})
})
}
function request(url, method, data = {}, options = {}) {
const baseURL = options.baseURL || config.baseURL
return new Promise((resolve, reject) => {
const requestUrl = buildUrl(url, baseURL)
uni.request({
url: requestUrl,
method,
data,
header: getHeaders(options.headers),
timeout: options.timeout || 15000,
success: async (res) => {
let body = res.data || {}
if (typeof body === 'string') {
try {
body = JSON.parse(body)
} catch (error) {
body = { msg: body }
}
}
if (Number(body.code) === 401 && !options._retry) {
try {
const token = await refreshAccessToken()
if (token) {
resolve(request(url, method, data, { ...options, _retry: true }))
return
}
} catch (error) {
console.error('[scanapp] 刷新登录令牌失败', error)
}
}
if (Number(body.code) === 0) {
resolve(options.returnFullResponse ? body : body.data)
return
}
const message = body.msg || `请求失败(HTTP ${res.statusCode || 0},code ${body.code ?? 'unknown'})`
console.error('[scanapp] 请求失败', {
url: requestUrl,
statusCode: res.statusCode,
code: body.code,
message,
body
})
if (options.showError !== false) {
uni.showToast({ title: message, icon: 'none' })
}
reject(new Error(message))
},
fail: (error) => {
const message = getNetworkErrorMessage(error)
console.error('[scanapp] 网络请求失败', {
url: requestUrl,
rawMessage: error?.errMsg,
message,
error
})
if (options.showError !== false) {
uni.showToast({ title: message, icon: 'none' })
}
reject(new Error(message))
}
})
})
}
export function uploadFile(url, filePath, formData = {}, options = {}) {
const baseURL = options.baseURL || config.baseURL
return new Promise((resolve, reject) => {
const requestUrl = buildUrl(url, baseURL)
const token = uni.getStorageSync(config.tokenKey)
const header = getHeaders(options.headers, false)
if (token) {
header[config.tokenHeaderKey] = String(token).startsWith('Bearer ') ? token : `Bearer ${token}`
}
uni.uploadFile({
url: requestUrl,
filePath,
name: options.name || 'file',
formData,
header,
timeout: options.timeout || 30000,
success: (res) => {
let body = res.data || {}
if (typeof body === 'string') {
try {
body = JSON.parse(body)
} catch (error) {
body = { msg: body }
}
}
if (Number(body.code) === 0) {
resolve(options.returnFullResponse ? body : body.data)
return
}
const message = body.msg || `上传失败(HTTP ${res.statusCode || 0},code ${body.code ?? 'unknown'})`
if (options.showError !== false) {
uni.showToast({ title: message, icon: 'none' })
}
reject(new Error(message))
},
fail: (error) => {
const message = getNetworkErrorMessage(error)
if (options.showError !== false) {
uni.showToast({ title: message, icon: 'none' })
}
reject(new Error(message))
}
})
})
}
export default {
get(url, data = {}, options = {}) {
return request(url, 'GET', data, options)
},
post(url, data = {}, options = {}) {
return request(url, 'POST', data, options)
},
put(url, data = {}, options = {}) {
return request(url, 'PUT', data, options)
},
delete(url, data = {}, options = {}) {
return request(url, 'DELETE', data, options)
}
}