Files
jnpf_app/utils/request.js

223 lines
8.0 KiB
JavaScript
Raw Permalink 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 define from './define'
import { useLocale } from '@/locale/useLocale';
const { getBackLocale } = useLocale();
let host = define.baseURL
const defaultOpt = { load: true }
// ------------- token刷新核心配置 -------------
const whiteList = ['/login', '/system/auth/refresh-token']
let requestQueue = []
let isRefreshingToken = false
const isRelogin = { show: false }
// 全局网络状态标记(防止多请求覆盖)
let GLOBAL_IS_NETWORK_ERROR = false;
// ========== 核心:全局拦截登录跳转 ==========
// 拦截所有跳登录页的操作,仅允许非断网场景跳转
function interceptLoginJump() {
// 拦截 reLaunch最常用的跳登录方式
const originalReLaunch = uni.reLaunch;
uni.reLaunch = function(options) {
// 如果是跳登录页 + 当前是网络错误 → 阻止跳转
if (options.url && options.url.includes('/pages/login/index') && GLOBAL_IS_NETWORK_ERROR) {
console.log('【拦截】断网时禁止跳登录页');
uni.showToast({
title: '网络已断开,请先连接网络',
icon: 'none',
duration: 3000
});
return; // 终止跳转
}
// 非登录页/非断网场景 → 正常跳转
originalReLaunch.call(uni, options);
};
// 拦截其他跳转方式(兜底)
const interceptors = ['navigateTo', 'redirectTo', 'switchTab'];
interceptors.forEach(method => {
const originalMethod = uni[method];
uni[method] = function(options) {
if (options.url && options.url.includes('/pages/login/index') && GLOBAL_IS_NETWORK_ERROR) {
return;
}
originalMethod.call(uni, options);
};
});
}
// 初始化拦截器(页面加载时执行一次)
interceptLoginJump();
// ------------- 核心request方法 -------------
function request(config) {
config.options = Object.assign(defaultOpt, config.options)
const token = uni.getStorageSync('token') || ''
const refreshToken = uni.getStorageSync('refreshToken') || ''
const tenantId = '1' || uni.getStorageSync('tenantId')
const systemCode = uni.getStorageSync('systemCode') || ''
const locale = getBackLocale()
// 构建请求头
let header = {
"accept": 'application/json, text/plain, */*',
"App-Code": systemCode,
"Content-Type": "application/json;charset=UTF-8",
"Jnpf-Origin": "app",
"Vue-Version": "3",
"Accept-Language": locale,
"tenant-id": tenantId,
...config.header
}
header['App-Code'] = encodeURIComponent(header['App-Code'])
if (token) header['Authorization'] = token
// let url = config.url.indexOf('http') > -1 ? config.url : host + config.url
let url = host + config.url
console.log(url,'url---')
// 显示加载中
if (config.options.load) {
uni.showLoading({ title: config.options.loadText || '正在加载' })
}
// 返回Promise
return new Promise((resolve, reject) => {
// 封装核心请求逻辑
const coreRequest = () => {
uni.request({
url: url,
data: config.data || {},
method: config.method || 'GET',
header: header,
timeout: define.timeout,
success: async (res) => {
uni.hideLoading();
GLOBAL_IS_NETWORK_ERROR = false; // 有响应 → 网络正常
if (res.statusCode === 200) {
if (res.data.code == 200 || res.data.code == 0) {
resolve(res.data)
} else if ([401, 600, 601, 602].includes(res.data.code)) {
// 白名单接口不处理
const isWhiteList = whiteList.some(v => config.url.includes(v))
if (isWhiteList) {
uni.showToast({ title: res.data.msg || '认证失败', icon: 'none' });
reject(res.data.msg);
return;
}
// 无刷新token → 提示手动登录(不自动跳转)
if (!refreshToken) {
uni.showModal({
title: '登录过期',
content: '您的登录已过期,请重新登录',
showCancelButton: false,
confirmText: '去登录'
}).then(res => {
if (res.confirm) {
clearAuthStorage();
uni.reLaunch({ url: '/pages/login/index' }); // 这里会走拦截器,仅网络正常时跳转
}
});
reject('登录过期无刷新Token');
return;
}
if (isRefreshingToken) {
requestQueue.push(() => coreRequest());
return;
}
isRefreshingToken = true;
try {
// 刷新token接口
const refreshUrl = `${host}/admin-api/system/auth/refresh-token?refreshToken=${encodeURIComponent(refreshToken)}`;
const refreshRes = await uni.request({
url: refreshUrl,
method: 'POST',
header: {
'tenant-id': tenantId,
'Content-Type': 'application/json'
},
data: {}
});
if (refreshRes.data && (refreshRes.data.code == 0 || refreshRes.data.code == 200)) {
// 刷新成功
const newTokenData = refreshRes.data.data;
uni.setStorageSync('token', newTokenData.accessToken);
uni.setStorageSync('refreshToken', newTokenData.refreshToken);
header['Authorization'] = newTokenData.accessToken;
coreRequest();
requestQueue.forEach(cb => cb());
requestQueue = [];
} else {
// 刷新失败 → 提示手动登录
uni.showModal({
title: '登录过期',
content: '刷新登录状态失败,请重新登录',
showCancelButton: false,
confirmText: '去登录'
}).then(res => {
if (res.confirm) {
clearAuthStorage();
uni.reLaunch({ url: '/pages/login/index' });
}
});
reject('刷新Token失败' + (refreshRes.data?.msg || '接口返回异常'));
}
} catch (err) {
// 刷新token异常 → 判定为网络错误
GLOBAL_IS_NETWORK_ERROR = true;
uni.showToast({ title: '网络异常,无法刷新登录状态', icon: 'none', duration: 3000 });
reject('网络异常:' + (err.errMsg || err.message));
} finally {
isRefreshingToken = false;
requestQueue = [];
}
} else {
// 普通业务错误
uni.showToast({ title: res.data.msg || '请求出错,请重试', icon: 'none' });
reject(res.data.msg);
}
} else {
// HTTP状态码错误
uni.showToast({ title: `请求失败[${res.statusCode}]`, icon: 'none' });
reject(res.errMsg);
}
},
fail: (err) => {
uni.hideLoading();
GLOBAL_IS_NETWORK_ERROR = true;
// 重置刷新状态,防止死锁
isRefreshingToken = false;
requestQueue = [];
// 仅提示网络错误,不跳转
uni.showToast({ title: '网络连接失败,请检查网络', icon: 'none', duration: 3000 });
reject({ isNetworkError: true, errMsg: err.errMsg });
}
})
}
coreRequest()
})
}
// ------------- 辅助函数 -------------
/**
* 清除登录缓存
*/
function clearAuthStorage() {
uni.removeStorageSync('token');
uni.removeStorageSync('refreshToken');
uni.removeStorageSync('cid');
uni.removeStorageSync('userInfo');
uni.removeStorageSync('permissionList');
uni.removeStorageSync('sysVersion');
uni.removeStorageSync('dynamicModelExtra');
}
export default request;