- request.js
import env from '@/env.js';
import store from '@/store/index.js';
import { getTimestamp, generateAppKey } from '@/util/common.js';
let isRefreshing = false;
let subscribers = [];
function onAccessTokenFetched(newToken) {
subscribers.forEach((callback) => callback(newToken));
subscribers = [];
}
function addSubscriber(callback) {
subscribers.push(callback);
}
//获取token
export const fetchToken = async () => {
const appid = env.appId;
const secret = env.appSecret;
const companycode = env.companyCode;
const timestamp = getTimestamp();
const appkey = generateAppKey(appid, timestamp, secret);
try {
const { data, statusCode } = await new Promise((resolve, reject) => {
uni.request({
url: `${env.WebApiBase}/accessToken/getToken`,
method: 'GET',
timeout: 10000,
header: {
'Content-Type': 'application/json',
},
data: {
appid,
appkey,
timestamp,
companycode,
},
complete: (response) => {
const { statusCode, data } = response;
if (statusCode === 200) {
resolve({ data, statusCode });
} else {
reject(new Error(`请求失败,状态码:${statusCode}`));
}
},
fail: (error) => {
reject(new Error(`网络请求失败: ${error.errMsg}`));
},
});
});
if (data.Success) {
store.dispatch('saveToken', data.GateWayToken);
return data.GateWayToken;
} else {
throw new Error(`获取 Token 失败: ${data.Message || '未知错误'}`);
}
} catch (error) {
if (error.message.includes('timeout')) {
uni.showToast({ title: '请求超时,请检查网络连接', icon: 'none' });
} else if (error.message.includes('网络请求失败')) {
uni.showToast({ title: '网络错误,请稍后重试', icon: 'none' });
} else {
uni.showToast({ title: error.message, icon: 'none' });
}
console.error('获取 Token 失败:', error);
throw error;
}
};
const request = async (options = {}, retryCount = 0) => {
if (!store.getters.getToken && !isRefreshing) {
await store.dispatch('fetchAndSaveToken');
}
// 将data对象转为查询字符串
let queryParams = '';
// 首先,将 param 转换为 JSON 字符串
if (options.data.param) {
options.data.param = JSON.stringify(options.data.param);
}
if (options.data) {
queryParams = Object.keys(options.data)
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(options.data[key])}`)
.join('&');
}
// 确保只有在 options.url 不包含 WebApiBase 时才添加它
const finalUrl = options.url.startsWith(env.WebApiBase)
? options.url
: `${env.WebApiBase}${options.url}${queryParams ? (options.url.includes('?') ? '&' : '?') + queryParams : ''}`;
// 更新 options 对象
options.url = finalUrl;
options.header = {
'Content-Type': 'application/json;charset=UTF-8',
GateWayToken: store.getters.getToken,
...options.header,
};
options.dataType = 'json';
options.responseType = 'text';
return new Promise((resolve, reject) => {
options.complete = async (response) => {
// 确保 response 对象不为空
if (!response) {
reject(new Error('响应为空'));
return;
}
const { statusCode, data } = response || {};
if (statusCode === 200) {
// 检查业务逻辑中的401错误
if (data.StatusCode === '401' && data.Message.includes('登录已超时')) {
if (retryCount < 1) {
handleTokenRefresh(async (newToken) => {
options.header['GateWayToken'] = newToken;
resolve(await request(options, retryCount + 1));
});
} else {
handleUnauthorized();
// reject(new Error('Token刷新失败,多次尝试无效'));
}
} else if (data.Success) {
resolve(data.datalist);
} else {
if(data.Message == '暂无数据'){
resolve([]);
}else{
reject(data);
}
}
} else {
reject(data);
}
};
uni.request(options);
});
};
const handleTokenRefresh = (retryRequest) => {
addSubscriber(retryRequest);
if (!isRefreshing) {
isRefreshing = true;
store.dispatch('fetchAndSaveToken')
.then((newToken) => {
onAccessTokenFetched(newToken);
})
.catch(() => {
// console.error('Token刷新失败:', error);
handleUnauthorized();
// throw new Error('Token刷新失败,多次尝试无效');
})
.finally(() => {
isRefreshing = false;
});
}
};
const handleUnauthorized = () => {
store.commit('resetState');
};
export default {
request,
get: (url, data, options) => request({ url, data, method: 'GET', ...options }),
post: (url, data, options) => request({ url, data, method: 'POST', ...options }),
put: (url, data, options) => request({ url, data, method: 'PUT', ...options }),
delete: (url, data, options) => request({ url, data, method: 'DELETE', ...options }),
};