| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- import { API_BASE, TOKEN_KEY, REFRESH_TOKEN_KEY, USER_INFO_KEY } from '@/config/api'
- let clearingAuth = false
- function appendTimestampQuery(url) {
- const base = String(url || '')
- const ts = Date.now()
- if (!base) return `${base}?_t=${ts}`
- // 已有 _t 时覆盖为最新值,避免 query 反复堆叠
- if (/[?&]_t=/.test(base)) {
- return base.replace(/([?&]_t=)\d+/, `$1${ts}`)
- }
- return `${base}${base.includes('?') ? '&' : '?'}_t=${ts}`
- }
- function createUnauthorizedError(rawUrl = '') {
- const loginApiPattern = /\/mini\/auth\/login(?:$|\?)/
- const message = loginApiPattern.test(String(rawUrl))
- ? '用户名或密码错误,请重新输入'
- : '登录状态已失效,请重新登录'
- const error = new Error(message)
- error.name = 'UnauthorizedError'
- return error
- }
- async function onHttpUnauthorized() {
- if (clearingAuth) return
- clearingAuth = true
- // 先同步清理本地登录态,避免 store 动态导入失败时仍被识别为已登录
- uni.removeStorageSync(TOKEN_KEY)
- uni.removeStorageSync(REFRESH_TOKEN_KEY)
- uni.removeStorageSync(USER_INFO_KEY)
- try {
- const { useUserStore } = await import('@/stores/user')
- useUserStore().clearLoginInfo()
- } catch (error) {
- // ignore
- }
- const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : []
- const currentRoute = pages.length ? pages[pages.length - 1].route : ''
- if (currentRoute === 'pages/login/login') {
- clearingAuth = false
- return
- }
- uni.showToast({ title: '登录已失效,请重新登录', icon: 'none' })
- uni.reLaunch({
- url: '/pages/login/login',
- fail: () => {
- // 某些端在请求回调中 reLaunch 可能失败,使用 redirectTo 兜底
- uni.redirectTo({ url: '/pages/login/login' })
- },
- complete: () => {
- setTimeout(() => {
- clearingAuth = false
- }, 800)
- }
- })
- }
- function isBizUnauthorized(data) {
- if (!data || typeof data !== 'object') return false
- return data.code === 401
- }
- export function request(options) {
- if (clearingAuth) {
- return Promise.reject(createUnauthorizedError(options?.url))
- }
- const rawToken = uni.getStorageSync(TOKEN_KEY)
- const token = typeof rawToken === 'string' ? rawToken.trim() : ''
- const rawUrl = options.url || ''
- const normalizedUrl = rawUrl.startsWith('http')
- ? rawUrl
- : `${API_BASE}${rawUrl.startsWith('/') ? rawUrl : `/${rawUrl}`}`
- const url = appendTimestampQuery(normalizedUrl)
- return new Promise((resolve, reject) => {
- uni.request({
- ...options,
- url,
- header: {
- 'Content-Type': 'application/json',
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
- ...(options.header || {})
- },
- success: (res) => {
- if (res.statusCode === 401 || isBizUnauthorized(res.data)) {
- onHttpUnauthorized()
- reject(createUnauthorizedError(rawUrl))
- return
- }
- resolve(res)
- },
- fail: (err) => reject(err)
- })
- })
- }
- export function parseResponseJson(res) {
- const d = res.data
- if (d == null) return d
- if (typeof d === 'string') {
- try {
- return JSON.parse(d)
- } catch (error) {
- return d
- }
- }
- return d
- }
|