Files
uniapp-im-shop/utils/request.js

192 lines
4.9 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 { 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