2025-08-08 13:02:39 +08:00
|
|
|
|
import type { uniappRequestAdapter } from '@alova/adapter-uniapp'
|
|
|
|
|
|
import type { IResponse } from './types'
|
|
|
|
|
|
import AdapterUniapp from '@alova/adapter-uniapp'
|
|
|
|
|
|
import { createAlova } from 'alova'
|
|
|
|
|
|
import { createServerTokenAuthentication } from 'alova/client'
|
|
|
|
|
|
import VueHook from 'alova/vue'
|
2025-08-11 15:07:21 +08:00
|
|
|
|
import { getEnvBaseUrl } from '@/utils'
|
2025-08-08 13:02:39 +08:00
|
|
|
|
import { toast } from '@/utils/toast'
|
|
|
|
|
|
import { ContentTypeEnum, ResultEnum, ShowMessage } from './enum'
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建请求实例
|
|
|
|
|
|
*/
|
|
|
|
|
|
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication<
|
|
|
|
|
|
typeof VueHook,
|
|
|
|
|
|
typeof uniappRequestAdapter
|
|
|
|
|
|
>({
|
|
|
|
|
|
refreshTokenOnError: {
|
|
|
|
|
|
isExpired: (error) => {
|
|
|
|
|
|
return error.response?.status === ResultEnum.Unauthorized
|
|
|
|
|
|
},
|
|
|
|
|
|
handler: async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// await authLogin();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (error) {
|
|
|
|
|
|
// 切换到登录页
|
|
|
|
|
|
await uni.reLaunch({ url: '/pages/login/index' })
|
|
|
|
|
|
throw error
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* alova 请求实例
|
|
|
|
|
|
*/
|
|
|
|
|
|
const alovaInstance = createAlova({
|
2025-08-11 15:07:21 +08:00
|
|
|
|
baseURL: getEnvBaseUrl(),
|
2025-08-08 13:02:39 +08:00
|
|
|
|
...AdapterUniapp(),
|
|
|
|
|
|
timeout: 5000,
|
|
|
|
|
|
statesHook: VueHook,
|
|
|
|
|
|
|
|
|
|
|
|
beforeRequest: onAuthRequired((method) => {
|
2026-03-11 17:10:18 +08:00
|
|
|
|
// h5动态获取最新的 baseURL,确保使用用户设置的服务器地址
|
|
|
|
|
|
const currentBaseUrl = getEnvBaseUrl()
|
|
|
|
|
|
if (currentBaseUrl !== method.baseURL) {
|
|
|
|
|
|
method.baseURL = currentBaseUrl
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 16:14:04 +08:00
|
|
|
|
// 检查混合内容错误(HTTPS页面请求HTTP接口)
|
|
|
|
|
|
const currentProtocol = typeof window !== 'undefined' && window.location.protocol
|
|
|
|
|
|
const requestProtocol = method.baseURL?.split(':')[0]
|
|
|
|
|
|
if (currentProtocol === 'https:' && requestProtocol === 'http') {
|
|
|
|
|
|
const errorMessage = '无法配置http协议地址,请检查接口地址'
|
|
|
|
|
|
throw new Error(errorMessage)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-08 13:02:39 +08:00
|
|
|
|
// 设置默认 Content-Type
|
|
|
|
|
|
method.config.headers = {
|
|
|
|
|
|
'Content-Type': ContentTypeEnum.JSON,
|
|
|
|
|
|
'Accept': 'application/json, text/plain, */*',
|
|
|
|
|
|
...method.config.headers,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { config } = method
|
|
|
|
|
|
const ignoreAuth = config.meta?.ignoreAuth
|
|
|
|
|
|
console.log('ignoreAuth===>', ignoreAuth)
|
|
|
|
|
|
|
|
|
|
|
|
// 处理认证信息
|
|
|
|
|
|
if (!ignoreAuth) {
|
2026-03-10 16:14:04 +08:00
|
|
|
|
const authInfo = JSON.parse(uni.getStorageSync('token') || '{}')
|
|
|
|
|
|
if (!authInfo.token) {
|
2025-08-08 13:02:39 +08:00
|
|
|
|
// 跳转到登录页
|
|
|
|
|
|
uni.reLaunch({ url: '/pages/login/index' })
|
|
|
|
|
|
throw new Error('[请求错误]:未登录')
|
|
|
|
|
|
}
|
|
|
|
|
|
// 添加 Authorization 头
|
2026-03-10 16:14:04 +08:00
|
|
|
|
method.config.headers.Authorization = `Bearer ${authInfo.token}`
|
2025-08-08 13:02:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理动态域名
|
|
|
|
|
|
if (config.meta?.domain) {
|
|
|
|
|
|
method.baseURL = config.meta.domain
|
|
|
|
|
|
console.log('当前域名', method.baseURL)
|
|
|
|
|
|
}
|
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
|
|
responded: onResponseRefreshToken((response, method) => {
|
|
|
|
|
|
const { config } = method
|
|
|
|
|
|
const { requestType } = config
|
|
|
|
|
|
const {
|
|
|
|
|
|
statusCode,
|
|
|
|
|
|
data: rawData,
|
|
|
|
|
|
errMsg,
|
|
|
|
|
|
} = response as UniNamespace.RequestSuccessCallbackResult
|
|
|
|
|
|
|
|
|
|
|
|
console.log(response)
|
|
|
|
|
|
|
|
|
|
|
|
// 处理特殊请求类型(上传/下载)
|
|
|
|
|
|
if (requestType === 'upload' || requestType === 'download') {
|
|
|
|
|
|
return response
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理 HTTP 状态码错误
|
|
|
|
|
|
if (statusCode !== 200) {
|
|
|
|
|
|
const errorMessage = ShowMessage(statusCode) || `HTTP请求错误[${statusCode}]`
|
|
|
|
|
|
console.error('errorMessage===>', errorMessage)
|
|
|
|
|
|
toast.error(errorMessage)
|
|
|
|
|
|
throw new Error(`${errorMessage}:${errMsg}`)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理业务逻辑错误
|
|
|
|
|
|
const { code, msg, data } = rawData as IResponse
|
|
|
|
|
|
if (code !== ResultEnum.Success) {
|
|
|
|
|
|
// 检查是否为token失效
|
|
|
|
|
|
if (code === ResultEnum.Unauthorized) {
|
|
|
|
|
|
// 清除token并跳转到登录页
|
|
|
|
|
|
uni.removeStorageSync('token')
|
|
|
|
|
|
uni.reLaunch({ url: '/pages/login/index' })
|
|
|
|
|
|
throw new Error(`请求错误[${code}]:${msg}`)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-04 16:33:22 +08:00
|
|
|
|
if (config.meta?.isExposeError) {
|
|
|
|
|
|
return Promise.reject(msg)
|
|
|
|
|
|
}
|
2026-03-06 09:40:04 +08:00
|
|
|
|
|
2025-08-08 13:02:39 +08:00
|
|
|
|
if (config.meta?.toast !== false) {
|
|
|
|
|
|
toast.warning(msg)
|
|
|
|
|
|
}
|
|
|
|
|
|
throw new Error(`请求错误[${code}]:${msg}`)
|
|
|
|
|
|
}
|
|
|
|
|
|
// 处理成功响应,返回业务数据
|
|
|
|
|
|
return data
|
|
|
|
|
|
}),
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
export const http = alovaInstance
|