xfgczlglpt_pad_app/src/utils/http.ts

370 lines
11 KiB
TypeScript
Raw Normal View History

2026-01-16 15:38:08 +08:00
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 时执行的代码
}
2026-01-21 17:48:45 +08:00
// uni.showLoading({
// title: '加载中...',
// duration: 15000 // 可根据实用场景设置时间
// })
2026-01-16 15:38:08 +08:00
uni.request({
url,
header,
data,
// method: isPost ? 'POST' : 'GET',
method: _this.methodstr,
timeout: timeout,
success(res) {
// debugger
2026-01-21 17:48:45 +08:00
// uni.hideLoading()
2026-01-16 15:38:08 +08:00
// 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) {
2026-01-21 17:48:45 +08:00
// uni.hideLoading()
2026-01-16 15:38:08 +08:00
console.log('fail', err)
uni.showToast({ title: '网络错误', icon: 'none' })
reject({ message: '网络错误' })
},
complete() {
2026-01-21 17:48:45 +08:00
// uni.hideLoading()
2026-01-16 15:38:08 +08:00
_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