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
|