Files
xiaozhi-esp32-server/main/manager-mobile/src/http/request/alova.ts
T

152 lines
4.4 KiB
TypeScript
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 type { uniappRequestAdapter } from '@alova/adapter-uniapp'
import type { IResponse } from './types'
import type { Language } from '@/store/lang'
import AdapterUniapp from '@alova/adapter-uniapp'
import { createAlova } from 'alova'
import { createServerTokenAuthentication } from 'alova/client'
import VueHook from 'alova/vue'
import { getEnvBaseUrl } from '@/utils'
import { toast } from '@/utils/toast'
import { ContentTypeEnum, ResultEnum, ShowMessage } from './enum'
// 语言映射, 用于设置 Accept-language 头
const langMap: Record<Language, string> = {
zh_CN: 'zh-CN',
en: 'en',
zh_TW: 'zh-TW',
de: 'de',
vi: 'vi',
pt_BR: 'pt-BR',
}
/**
* 创建请求实例
*/
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({
baseURL: getEnvBaseUrl(),
...AdapterUniapp(),
timeout: 5000,
statesHook: VueHook,
beforeRequest: onAuthRequired((method) => {
// h5动态获取最新的 baseURL,确保使用用户设置的服务器地址
const currentBaseUrl = getEnvBaseUrl()
if (currentBaseUrl !== method.baseURL) {
method.baseURL = currentBaseUrl
}
// 检查混合内容错误(HTTPS页面请求HTTP接口)
const currentProtocol = typeof window !== 'undefined' && window.location.protocol
const requestProtocol = method.baseURL?.split(':')[0]
const currentLang = langMap[uni.getStorageSync('app_language') as Language || 'zh_CN']
if (currentProtocol === 'https:' && requestProtocol === 'http') {
const errorMessage = '无法配置http协议地址,请检查接口地址'
throw new Error(errorMessage)
}
// 设置默认 Content-Type
method.config.headers = {
'Content-Type': ContentTypeEnum.JSON,
'Accept': 'application/json, text/plain, */*',
'Accept-language': currentLang,
...method.config.headers,
}
const { config } = method
const ignoreAuth = config.meta?.ignoreAuth
console.log('ignoreAuth===>', ignoreAuth)
// 处理认证信息
if (!ignoreAuth) {
const authInfo = JSON.parse(uni.getStorageSync('token') || '{}')
if (!authInfo.token) {
// 跳转到登录页
uni.reLaunch({ url: '/pages/login/index' })
throw new Error('[请求错误]:未登录')
}
// 添加 Authorization 头
method.config.headers.Authorization = `Bearer ${authInfo.token}`
}
// 处理动态域名
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}`)
}
if (config.meta?.isExposeError) {
return Promise.reject(msg)
}
if (config.meta?.toast !== false) {
toast.warning(msg)
}
throw new Error(`请求错误[${code}]${msg}`)
}
// 处理成功响应,返回业务数据
return data
}),
})
export const http = alovaInstance