mahjong_group/common/system/request.js
2025-09-16 03:35:03 +08:00

212 lines
7.1 KiB
JavaScript
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 config from '@/common/env.js';
import md5 from 'js-md5';
import { getLocalStorage, setLocalStorage } from './cacheService';
import qs from 'qs';
import { clearUserStorage } from '@/common/server/user'
class request {
/**
* 生成唯一的nonce值
* @returns {String} nonce值
*/
static generateNonce() {
return md5(Date.now() + Math.random().toString(36).substring(2, 15));
}
/**
* 创建签名
* @param {Object} data 请求数据
* @param {String} host 主机名
* @returns {Object} 带签名的数据和参数字符串
* @private
*/
static _createSignature(data, host) {
// 添加时间戳
data.timestamp = Math.floor(Date.now() / 1000);
// 添加nonce随机字符串
data.nonce = request.generateNonce();
// 按照键名对参数进行排序
const sortedParams = {};
Object.keys(data).sort().forEach(key => {
sortedParams[key] = data[key];
});
// 组合参数为字符串
let signStr = '';
for (const key in sortedParams) {
if (typeof sortedParams[key] === 'object') {
signStr += key + '=' + JSON.stringify(sortedParams[key]) + '&';
} else {
signStr += key + '=' + sortedParams[key] + '&';
}
}
// 获取时间戳,组合为密钥
const timestamp = data.timestamp;
const appSecret = host + timestamp;
// 添加密钥并去除最后的&
signStr = signStr.substring(0, signStr.length - 1) + appSecret;
// 使用MD5生成签名
const sign = md5(signStr);
data.sign = sign;
return { data, signStr };
}
/**
* 构建请求URL
* @param {String} url 请求路径
* @returns {Object} 包含请求URL和主机名的对象
* @private
*/
static _buildRequestUrl(url) {
let requestUrl = '';
if (url.startsWith('http://') || url.startsWith('https://')) {
// 如果是完整的URL直接使用
requestUrl = url;
} else {
// 否则拼接基础URL和相对路径
// 确保基础URL以/结尾,而请求路径不以/开头
const apiBaseUrl = config.apiBaseUrl;
const baseUrlWithSlash = apiBaseUrl.endsWith('/') ? apiBaseUrl : apiBaseUrl + '/';
let routeMap = url;
const path = routeMap.startsWith('/') ? routeMap.substring(1) : routeMap;
requestUrl = baseUrlWithSlash + path;
}
// 使用正则表达式从URL中提取主机名
const hostRegex = /^(?:https?:\/\/)?([^\/]+)/i;
const matches = requestUrl.match(hostRegex);
const host = matches && matches[1] ? matches[1] : 'localhost';
return { requestUrl, host };
}
/**
* 发送请求
* @param {String} url 请求地址
* @param {Object} fromData 请求数据
* @param {String} method 请求方式
* @param {Boolean} showLoading 是否显示加载提示
* @returns {Promise} 返回请求Promise
*/
static request(url, fromData = {}, method = 'POST', showLoading = false) {
return new Promise((resolve, reject) => {
// 使用传入的method而不是重新声明
const requestMethod = method.toUpperCase();
let data = { ...fromData }; // 创建数据的深拷贝,避免修改原数据
// 构建请求URL和提取主机名
const { requestUrl, host } = request._buildRequestUrl(url);
// 显示加载提示
if (showLoading) {
uni.showLoading({
title: '正在加载中...',
mask: true
});
}
// 创建签名并准备请求数据和头信息
const { data: signedData } = request._createSignature(data, host);
data = signedData;
// 根据请求方法设置不同的headers
const header = {
'content-type': 'application/json'
};
const tokenInfo = uni.getStorageSync('tokenInfo');
if (tokenInfo != null && tokenInfo != "") {
header['Authorization'] = 'Bearer ' + tokenInfo.token;
}
const startDate = Date.now();
// 发起网络请求
uni.request({
url: requestUrl,
method: requestMethod,
header: header,
data: data,
timeout: 30000, // 设置30秒超时
success: res => {
const endDate = Date.now();
console.log(requestUrl, "请求消耗时间", endDate - startDate);
if (res.data.code == 14007) {
//登录失效
clearUserStorage();
}
resolve(res.data);
},
fail: e => {
console.error('网络请求失败:', e);
uni.showToast({
title: e.errMsg || '发送请求失败,请稍后再试!',
icon: 'none'
});
reject(e);
},
complete: () => {
if (showLoading) {
uni.hideLoading();
}
}
});
});
}
/**
* 发送GET请求
* @param {String} url 请求地址
* @param {Object} data 请求参数
* @param {Boolean} showLoading 是否显示加载提示
* @returns {Promise} 返回请求Promise
*/
static get(url, data = {}, showLoading = false) {
return request.request(url, data, 'GET', showLoading);
}
/**
* 发送POST请求
* @param {String} url 请求地址
* @param {Object} data 请求参数
* @param {Boolean} showLoading 是否显示加载提示
* @returns {Promise} 返回请求Promise
*/
static post(url, data = {}, showLoading = false) {
return request.request(url, data, 'POST', showLoading);
}
/**
* 发送get请求如果缓存存在则返回缓存数据否则发送请求并缓存数据
* @param {String} url 请求地址
* @param {Object} data 请求参数
* @param {Number} time 缓存时间,秒
* @param {Boolean} showLoading 是否显示加载提示
* @returns {Promise} 返回请求Promise
*/
static async getOrCache(url, data = {}, time = 300, showLoading = false) {
const cacheKey = 'cache_' + url + '_' + qs.stringify(data);
// console.log('getOrCache', cacheKey, '查询缓存');
const cacheData = getLocalStorage(cacheKey);
if (cacheData) {
console.log('getOrCache', cacheKey, '缓存命中');
return cacheData;
}
const res = await request.request(url, data, 'GET', showLoading);
setLocalStorage(cacheKey, res, time);
return res;
}
}
export default request;