OfficeSystem/utils/request/index.js
2025-11-19 10:34:14 +08:00

161 lines
6.0 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 '@/store/user'
/**
* 初始化请求拦截器
* 使用 Pinia store 管理用户状态和 token
*/
let isRedirectingToLogin = false
export const Request = () => {
// 初始化请求配置
uni.$uv.http.setConfig((config) => {
/* config 为默认全局配置*/
config.baseURL = 'http://192.168.1.4:4001'; /* 根域名 */
// config.baseURL = 'https://pm.ccttiot.com/prod-api'; /* 根域名 */
return config
})
// 请求拦截
uni.$uv.http.interceptors.request.use(async (config) => { // 可使用async await 做异步操作
// 检测网络状态
try {
const networkInfo = await new Promise((resolve, reject) => {
uni.getNetworkType({
success: resolve,
fail: reject
})
})
// 如果没有网络连接,阻止请求并提示
if (networkInfo.networkType === 'none') {
uni.$uv.toast('网络连接不可用,请检查网络设置')
return Promise.reject({
errMsg: '网络连接不可用',
networkType: 'none'
})
}
} catch (error) {
console.error('获取网络状态失败:', error)
// 如果获取网络状态失败,也提示用户
uni.$uv.toast('无法检测网络状态,请检查网络连接')
return Promise.reject({
errMsg: '无法检测网络状态',
error
})
}
// 初始化请求拦截器时会执行此方法此时data为undefined赋予默认{}
config.data = config.data || {}
// 根据custom参数中配置的是否需要token添加对应的请求头
if(config?.custom?.auth) {
// 使用 Pinia store 获取 token
const userStore = useUserStore()
// 直接使用 state.tokenPinia getter 可以直接访问)
const token = userStore.token
if (token) {
// 使用标准的 Authorization header添加 Bearer 前缀
config.header.Authorization = `Bearer ${token}`
} else {
console.warn('请求拦截器token 为空,无法添加认证头')
}
}
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
})
// 响应拦截
uni.$uv.http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data
// 自定义参数
const custom = response.config?.custom
// 处理 token 过期等情况(根据实际业务调整)
if (data.code === 401 || data.code === 403) {
// token 过期或无效,清除登录状态
const userStore = useUserStore()
userStore.logout()
if (!isRedirectingToLogin) {
isRedirectingToLogin = true
uni.$uv.toast('登录已过期,请重新登录')
setTimeout(() => {
uni.reLaunch({ url: '/pages/login/index' })
isRedirectingToLogin = false
}, 200)
}
}
if (data.code !== 200) {
// 如果没有显式定义custom的toast参数为false的话默认对报错进行toast弹出提示
if (custom?.toast !== false) {
uni.$uv.toast(data.message || data.msg || '请求失败')
}
// 如果需要catch返回则进行reject
if (custom?.catch) {
return Promise.reject(data)
} else {
// 否则返回一个pending中的promise请求不会进入catch中
return new Promise(() => { })
}
}
// 如果响应数据有 data 字段,返回 data 字段的值
// 如果没有 data 字段,返回去除 code 和 msg 后的数据对象
if (data.data !== undefined) {
return data.data
} else {
// 创建一个新对象,排除 code 和 msg 字段
const { code, msg, message, ...rest } = data
return Object.keys(rest).length > 0 ? rest : data
}
}, async (response) => {
// 对响应错误做点什么 statusCode !== 200
// 网络错误或服务器错误处理
// 检测是否是网络错误
if (!response.statusCode || response.statusCode === 0) {
// 可能是网络连接问题,再次检测网络状态
try {
const networkInfo = await new Promise((resolve, reject) => {
uni.getNetworkType({
success: resolve,
fail: reject
})
})
if (networkInfo.networkType === 'none') {
uni.$uv.toast('网络连接不可用,请检查网络设置')
return Promise.reject({
errMsg: '网络连接不可用',
networkType: 'none'
})
}
} catch (error) {
uni.$uv.toast('网络连接异常,请检查网络设置')
}
uni.$uv.toast('网络连接异常,请稍后重试')
return Promise.reject(response)
}
if (response.statusCode === 401 || response.statusCode === 403) {
const userStore = useUserStore()
userStore.logout()
if (!isRedirectingToLogin) {
isRedirectingToLogin = true
uni.$uv.toast('登录已过期,请重新登录')
setTimeout(() => {
uni.reLaunch({ url: '/pages/login/index' })
isRedirectingToLogin = false
}, 200)
}
}
return Promise.reject(response)
})
}