xfgczlglpt_pad_app/src/utils/http.ts

370 lines
11 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 useUserStore from '../store/user'
import { getrefreshtoken } from '@/apis/longin'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { goToPage, checkConfigFileExists, readConfigFile, createDefaultConfig } from '@/utils/util'
interface Response {
code: number
data: object
msg: string
}
// let appVersion = ''
// plus.runtime.getProperty(plus.runtime.appid, (info) => {
// appVersion = info.version
// })
// let newhttp = '' //请求ip
// let newpro = '' //请求端口
let newhttp = import.meta.env.VITE_APP_BASE_URL
let newpro = import.meta.env.VITE_APP_BASE_URLpro
let newapi = import.meta.env.VITE_APP_BASE_PRE //请求的api开头
let htpurl = '' //正式的加htp的
// #ifdef APP-PLUS
const configFileName = 'app_config.json'
//const configFilePath = `${plus.io.PRIVATE_DOC}/${configFileName}`; // 私有目录
// 或
const configFilePath = `${plus.io.PUBLIC_DOWNLOADS}/${configFileName}` // 公共目录
async function handleConfigFile() {
try {
const exists = await checkConfigFileExists(configFilePath, configFileName)
if (exists) {
const config = await readConfigFile(configFilePath, configFileName)
console.log('读取配置:', config)
newhttp = config.url
newpro = config.pro
const userStore = useUserStore()
userStore.seturlip(newhttp)
userStore.seturlpro(newpro)
userStore.setallurl(newhttp + ':' + newpro + newapi)
return config
} else {
newhttp = import.meta.env.VITE_APP_BASE_URL
newpro = import.meta.env.VITE_APP_BASE_URLpro
const userStore = useUserStore()
userStore.seturlip(newhttp)
userStore.seturlpro(newpro)
userStore.setallurl(newhttp + ':' + newpro + newapi)
const defaultConfig = await createDefaultConfig(configFilePath, configFileName, { url: newhttp, pro: newpro, Version: 'appVersion' })
console.log('生成默认配置:', defaultConfig)
return defaultConfig
}
} catch (err) {
newhttp = import.meta.env.VITE_APP_BASE_URL
newpro = import.meta.env.VITE_APP_BASE_URLpro
console.error('操作失败:', err)
throw err
}
}
// 调用示例
// handleConfigFile().then((config) => {
// // 使用配置数据
// //debugger
// })
// #endif
const requestObj = {
isLock: false,
methodstr: 'POST',
http({ url = '', data = {}, isPost = '0', isSinglePost = false, isToken = true, timeout = 20000 }) {
const _this = this
const userStore = useUserStore()
return new Promise(function (resolve, reject) {
if (isSinglePost && _this.isLock) {
reject({ message: '加载中' })
}
// debugger
_this.isLock = true
//debugger
// console.log('lsdfcs', userStore)
const header = {
'content-type': 'application/json',
// 'content-type': 'application/x-www-form-urlencoded',
// Authorization: ''
Bearerauth: ''
}
// if (isPost == '3') {
// header['content-type'] = 'application/x-www-form-urlencoded'
// }
if (getToken() && isToken) {
// header['Authorization'] = 'Bearer ' + userStore.token
header['Bearerauth'] = 'Bearer ' + getToken()
}
let htconfig = { url: url, data: data, isPost: isPost, isSinglePost: isSinglePost, isToken: isToken, timeout: timeout, header: header }
// #ifdef H5
// debugger
url = import.meta.env.VITE_APP_BASE_PRE + url
// #endif
// debugger
// #ifndef H5
// url = import.meta.env.VITE_APP_BASE_URL + ':' + import.meta.env.VITE_APP_BASE_URLpro + import.meta.env.VITE_APP_BASE_PRE + url
// url = import.meta.env.VITE_APP_BASE_URL + ':' + import.meta.env.VITE_APP_BASE_URLpro + newapi + url
// if (!userStore.allurl) {
// newhttp = import.meta.env.VITE_APP_BASE_URL
// newpro = import.meta.env.VITE_APP_BASE_URLpro
// userStore.seturlip(newhttp)
// userStore.seturlpro(newpro)
// userStore.setallurl(newhttp + ':' + newpro + newapi)
// }
userStore.seturlip(newhttp)
userStore.seturlpro(newpro)
userStore.setallurl(newhttp + ':' + newpro + newapi)
url = userStore.allurl + url
console.log('11111', url)
// #endif
// debugger
switch (isPost) {
case '0':
_this.methodstr = 'POST'
break
case '1':
_this.methodstr = 'GET'
break
case '2':
_this.methodstr = 'put'
break
default:
_this.methodstr = 'DELETE'
// 当 expression 不匹配任何 case 时执行的代码
}
// uni.showLoading({
// title: '加载中...',
// duration: 15000 // 可根据实用场景设置时间
// })
uni.request({
url,
header,
data,
// method: isPost ? 'POST' : 'GET',
method: _this.methodstr,
timeout: timeout,
success(res) {
// debugger
// uni.hideLoading()
// console.log('55dfdsfsd5', res.data)
res.data.code = res.data.code == 'ok' ? 200 : res.data.code
const data = res.data as Response
if (res.statusCode === 200) {
if (data.code == 200) {
// 成功
resolve(res.data)
} else if (data.code == 401) {
// uni.reLaunch({
// url: '/pages/login/login'
// })
} else if (data.code == 601) {
// userStore.setrefreshtoken()
// uni.showToast({ title: data.msg, icon: 'none' })
// setTimeout(() => {
// goToPage({
// url: 'pages/login/login',
// mode: 'navigateTo'
// })
// }, 1000)
return handleTokenRefresh(htconfig)
.then((result) => resolve(result))
.catch((error) => reject(error))
} else {
uni.showToast({ title: data.msg, icon: 'none' })
reject(res.data)
}
} else {
uni.showToast({ title: '响应错误', icon: 'none' })
reject({ message: '响应错误' })
}
},
fail(err) {
// uni.hideLoading()
console.log('fail', err)
uni.showToast({ title: '网络错误', icon: 'none' })
reject({ message: '网络错误' })
},
complete() {
// uni.hideLoading()
_this.isLock = false
}
})
})
}
}
// 请求队列与刷新状态管理
let requestQueue: any = []
let isRefreshing = false
let tokenRefreshPromise: any = null
/**
* 处理Token刷新和请求重试的核心函数
* @param {Object} config - 原始请求配置
* @returns {Promise} - 返回处理结果
*/
const handleTokenRefresh = (config: any) => {
const userStore = useUserStore()
return new Promise((resolve, reject) => {
// 将当前请求添加到队列
requestQueue.push({
resolve,
reject,
config
})
// 如果已经在刷新token则不再重复刷新
if (tokenRefreshPromise) {
return
}
// 如果没有在刷新token则开始刷新
if (!isRefreshing) {
isRefreshing = true
const rtoken = userStore.refreshtoken
if (!rtoken) {
// 没有刷新token直接跳转登录
resetQueueAndRefreshState(new Error('未找到刷新token'))
showLoginConfirm()
reject(new Error('未找到刷新token'))
return
}
// 创建token刷新Promise并保存引用
tokenRefreshPromise = getrefreshtoken(rtoken)
.then((response: any) => {
// const { data = {} } = response;
// const { accessToken, refreshToken: newRefreshToken } = data;
// debugger
let accessToken = response.data
if (!accessToken) {
throw new Error('刷新token失败未获取到新token')
}
// 更新存储的token
// setToken(accessToken);
// uni.setStorageSync(appConfig.cache_key.RefreshToken, newRefreshToken);
setToken(accessToken)
// userInfo.value.token = response
// 处理队列中的所有请求
return processQueue(accessToken)
})
.catch((error) => {
console.log('token刷新失败', error)
// 通知队列中所有请求失败
resetQueueAndRefreshState(error || new Error('无效的会话,或者会话已过期,请重新登录'))
// 显示登录确认对话框
showLoginConfirm()
throw error // 继续传递错误
})
.finally(() => {
// 重置刷新状态和Promise引用
tokenRefreshPromise = null
isRefreshing = false
})
}
})
}
/**
* 处理队列中的所有请求
* @param {String} newToken - 新的访问令牌
* @returns {Promise} - 返回处理结果
*/
const processQueue = async (newToken) => {
const currentQueue = [...requestQueue] // 复制当前队列,防止处理过程中队列变化
requestQueue = [] // 清空队列
try {
// 确保token已完全保存后再处理请求
await new Promise((resolve) => setTimeout(resolve, 50))
// 依次处理队列中的请求
const results = await Promise.allSettled(
currentQueue.map(async ({ resolve, reject, config }) => {
console.log('222222222222', config)
try {
// 更新请求头中的token
config.header['Bearerauth'] = 'Bearer ' + newToken
// 重新发起请求
const result = await requestObj.http({
...config,
retryCount: (config.retryCount || 0) + 1
})
// 使用setTimeout确保异步操作完成
setTimeout(() => resolve(result), 0)
return result
} catch (error) {
console.error('重试请求失败:', error)
reject(error)
throw error
}
})
)
return results
} catch (error) {
console.error('队列处理失败:', error)
throw error
} finally {
isRefreshing = false
}
}
/**
* 重置队列和刷新状态
* @param {Error} error - 错误信息
*/
const resetQueueAndRefreshState = (error: any) => {
// 通知队列中所有请求失败
requestQueue.forEach(({ reject }) => {
reject(error)
})
// 重置队列和刷新状态
requestQueue = []
isRefreshing = false
tokenRefreshPromise = null
}
/**
* 显示登录确认对话框
*/
const showLoginConfirm = () => {
// this.$modal.confirm('确定要退出系统吗?').then(() => {
// this.userStore.userlogOut();
// });
// showConfirmh('未登录或登录状态过期,您可以继续留在该页面,或者重新登录?').then((res: any) => {
// if (res.confirm) {
// uni.navigateTo({
// url: '/pages/login'
// })
// }
// })
uni.showModal({
title: '系统提示',
content: '登录状态过期,您可以继续留在该页面,或者重新登录?',
cancelText: '取消',
confirmText: '确定',
success: function (res) {
if (res.confirm) {
uni.reLaunch({
url: '/pages/login/login'
})
}
}
})
}
export const request = requestObj