import { apiUrl } from '@/config/global-config.js'
import { useUserStore } from '../stores'
import { usePageRoute } from "@/composable/usePageRoute.js"
const DEFAULT_CONFIG = {
timeout: 60000,
}
const refreshToken = async () => {
const userStore = useUserStore()
try {
const response = await uni.request({
url: apiUrl + '/auth/refresh',
method: 'POST',
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${userStore.token}`
}
})
if (response.data.code === 200) {
userStore.setToken(response.data.data.token)
return true
}
return false
} catch (error) {
return false
}
}
let isRefreshing = false
let refreshSubscribers = []
const onRefreshed = (token) => {
refreshSubscribers.forEach(callback => callback(token))
refreshSubscribers = []
}
const addSubscriber = (callback) => {
refreshSubscribers.push(callback)
}
const requestInterceptor = (config) => {
const userStore = useUserStore()
const token = userStore.token
const isMapApi = /apis\.map\.qq\.com/.test(config.url)
if (token && !isMapApi) {
config.header.Authorization = `Bearer ${token}`
}
return config
}
const responseInterceptor = async (response) => {
const userStore = useUserStore()
const code = response.data.code
const msg = response.data.msg
const data = response.data
switch (code) {
case 200:
return data
case 401: {
if (config.url.includes('/auth/refresh')) {
await handleLogout()
return Promise.reject(new Error('登录已失效'))
}
if (!isRefreshing) {
isRefreshing = true
try {
const refreshResult = await refreshToken()
if (refreshResult) {
const newToken = userStore.token
onRefreshed(newToken)
config.header.Authorization = `Bearer ${newToken}`
return request(config)
} else {
await handleLogout()
return Promise.reject(new Error('登录已失效'))
}
} finally {
isRefreshing = false
}
}
return new Promise((resolve) => {
addSubscriber((token) => {
config.header.Authorization = `Bearer ${token}`
resolve(request(config))
})
})
}
default:
uni.showToast({
icon: 'none',
title: msg || '请求错误',
duration: 2000
})
return Promise.reject(new Error(msg || '请求错误'))
}
}
const handleLogout = async () => {
const userStore = useUserStore()
const pageRoute = usePageRoute()
const fullPagePath = pageRoute.getCurrentFullPagePath()
uni.setStorageSync('fullPage', fullPagePath)
uni.$msgBox('登录已失效,请重新登录', 2000)
userStore.clearToken()
userStore.clearUser()
await uni.$delay(2000)
uni.reLaunch({ url: '/pages/login/login' })
}
const request = (options = {}) => {
const config = {
...DEFAULT_CONFIG,
...options,
header: {
'Content-Type': 'application/json',
...options.header
}
}
config.url = apiUrl + config.url
const interceptedConfig = requestInterceptor(config)
return new Promise((resolve, reject) => {
uni.request({
...interceptedConfig,
success: async (res) => {
try {
const result = await responseInterceptor(res)
resolve(result)
} catch (error) {
reject(error)
}
},
fail: (error) => {
uni.showToast({
icon: 'none',
title: '网络错误,请检查网络连接',
duration: 2000
})
reject(error)
},
complete: () => {
}
})
})
}
export const $get = (url, data, options = {}) => {
return request({
url,
data,
method: 'GET',
...options
})
}
export const $post = (url, data, options = {}) => {
return request({
url,
data,
method: 'POST',
...options
})
}
uni.$get = $get
uni.$post = $post