192 lines
4.9 KiB
JavaScript
192 lines
4.9 KiB
JavaScript
import { useUserStore } from '../stores/user'
|
||
import { navigateBack } from './router'
|
||
import { getToken } from './storage'
|
||
|
||
const BASE_URL = import.meta.env.VITE_SYSTEM_URL
|
||
|
||
// 防止多个 401 同时触发登出和跳转
|
||
let isHandling401 = false
|
||
|
||
/**
|
||
* 网络请求封装
|
||
* @param {Object} options 请求参数
|
||
* @returns {Promise}
|
||
*/
|
||
const request = options => {
|
||
// 默认配置
|
||
const defaultOptions = {
|
||
url: '',
|
||
method: 'GET',
|
||
data: {},
|
||
header: {
|
||
deviceId: uni.getDeviceInfo().deviceId,
|
||
'Content-Type': 'application/json' // 默认请求内容类型
|
||
}
|
||
}
|
||
|
||
// 合并配置
|
||
const config = { ...defaultOptions, ...options }
|
||
|
||
// 请求拦截:添加token等通用header
|
||
if (getToken()) {
|
||
config.header['Authorization'] = 'Bearer ' + getToken()
|
||
}
|
||
|
||
// 显示加载状态(可选)
|
||
if (options.loading !== false) {
|
||
uni.showLoading({
|
||
title: '加载中...',
|
||
mask: true
|
||
})
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
uni.request({
|
||
url: BASE_URL + config.url,
|
||
method: config.method,
|
||
data: config.data,
|
||
timeout: 10000, // 请求超时时间
|
||
header: config.header,
|
||
success: response => {
|
||
// 响应拦截:根据状态码处理
|
||
if (response.statusCode === 200) {
|
||
// 这里可以根据后端数据格式调整
|
||
// 例如:if (response.data.code === 0) {...}
|
||
if (response.data.code === 200) {
|
||
resolve(response.data)
|
||
} else {
|
||
// 注意:这里也要 reject,否则调用方无法感知失败
|
||
const err = handleError(
|
||
response.data.code,
|
||
response.data,
|
||
options?.isErrorBack
|
||
)
|
||
reject(err || response.data)
|
||
// handleError(response.data.code, response.data)
|
||
}
|
||
} else {
|
||
// 状态码错误处理
|
||
// handleError(response.statusCode, response.data)
|
||
// reject(response)
|
||
const err = handleError(
|
||
response.statusCode,
|
||
response.data,
|
||
options?.isErrorBack
|
||
)
|
||
reject(err || response)
|
||
}
|
||
},
|
||
fail: error => {
|
||
// 网络错误处理
|
||
uni.showToast({
|
||
title: '网络异常,请检查网络连接',
|
||
icon: 'none',
|
||
duration: 2000,
|
||
mask: true
|
||
})
|
||
reject(error)
|
||
},
|
||
complete: () => {
|
||
// 隐藏加载状态
|
||
if (options.loading !== false) {
|
||
uni.hideLoading()
|
||
}
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 错误处理函数
|
||
* @param {Number} statusCode HTTP状态码
|
||
* @param {Object} data 响应数据
|
||
* @param {Boolean} isErrorBack 是否返回上一页
|
||
*/
|
||
const handleError = (statusCode, data, isErrorBack) => {
|
||
// 如果是 401 且正在处理中,直接返回(避免重复处理)
|
||
if (statusCode === 401) {
|
||
if (isHandling401) {
|
||
return new Error('Unauthorized')
|
||
}
|
||
isHandling401 = true
|
||
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '登录已过期,请重新登录',
|
||
showCancel: false,
|
||
success: async () => {
|
||
await useUserStore().clearAllUserInfo()
|
||
// 可选:跳转登录页
|
||
uni.reLaunch({ url: '/pages/login/login' })
|
||
console.log('登录已过期,====')
|
||
},
|
||
complete: () => {
|
||
// 重置标志,允许下次 401 处理(比如用户重新登录后再次过期)
|
||
isHandling401 = false
|
||
}
|
||
})
|
||
return new Error('Unauthorized')
|
||
}
|
||
|
||
switch (statusCode) {
|
||
// case 401:
|
||
// console.log('登录已过期,====')
|
||
// uni.showModal({
|
||
// title: '提示',
|
||
// content: '登录已过期,请重新登录',
|
||
// showCancel: false,
|
||
// success: () => {
|
||
// useUserStore().logout()
|
||
// // uni.navigateTo({
|
||
// // url: '/pages/login/index'
|
||
// // })
|
||
// }
|
||
// })
|
||
// break
|
||
case 403:
|
||
uni.showToast({
|
||
title: '没有权限访问',
|
||
icon: 'none',
|
||
duration: 2000,
|
||
mask: true
|
||
})
|
||
break
|
||
case 404:
|
||
uni.showToast({
|
||
title: '请求资源不存在',
|
||
icon: 'none',
|
||
duration: 2000,
|
||
mask: true
|
||
})
|
||
break
|
||
case 500:
|
||
uni.showModal({
|
||
title: `${statusCode}提示`,
|
||
content: data.msg || '服务器内部错误',
|
||
showCancel: false,
|
||
confirmText: '确定'
|
||
})
|
||
if (isErrorBack) {
|
||
navigateBack()
|
||
}
|
||
// uni.showToast({
|
||
// title: data.msg || '服务器内部错误',
|
||
// icon: 'none',
|
||
// duration: 2000,
|
||
// mask: true
|
||
// })
|
||
break
|
||
default:
|
||
uni.showToast({
|
||
title: data.msg || '请求失败,请重试',
|
||
icon: 'none',
|
||
duration: 2000,
|
||
mask: true
|
||
})
|
||
}
|
||
|
||
return new Error(`Request failed with code: ${statusCode}`)
|
||
}
|
||
|
||
export default request
|