yfs/common/request.js
2025-04-17 15:17:48 +08:00

320 lines
9.2 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 EnvConfig from '@/common/env.js'
import md5 from 'js-md5'
class RequestManager {
/**
* 判断URL是否在白名单中
* @param {String} url 请求地址
* @returns {Boolean} 是否在白名单中
*/
static isUrlInWhitelist(url) {
// 白名单URL列表
const whitelistUrls = [
'login_record',
'api/warehouse_index',
'api/user',
'api/warehouse_send_record'
]
// 检查URL是否包含白名单中的任一项
return whitelistUrls.some(whiteItem => url.indexOf(whiteItem) > -1)
}
/**
* 生成唯一的nonce值
* @returns {String} nonce值
*/
static generateNonce() {
return md5(Date.now() + Math.random().toString(36).substring(2, 15));
}
/**
* 发送网络请求
* @param {Object} param 请求参数
* @param {String} param.url 请求地址
* @param {Object} param.data 请求数据
* @param {Function} param.success 成功回调
* @param {Function} param.fail 失败回调
* @param {Function} param.complete 完成回调
* @param {Boolean} param.Loading 是否显示加载提示
* @param {String} backpage 返回页面
* @param {String} backtype 返回类型
* @returns {Promise} 返回请求Promise
*/
static request(param, backpage, backtype) {
return new Promise((resolve, reject) => {
// 参数检查
if (!param || typeof param !== 'object') {
reject(new Error('请求参数错误'))
return
}
uni.getNetworkType({
success: function (res) {
if (res.networkType == 'none') {
uni.showToast({
title: '网络连接异常,请检查网络',
icon: 'none'
})
reject(new Error('网络连接异常'))
return
}
}
})
const url = param.url || ''
const method = param.method || 'POST'
const data = param.data || {}
const Loading = param.Loading || false
const token = uni.getStorageSync('token')
let client = ""
// #ifdef H5
client = "h5"
// #endif
// 获取API基础URL
const apiBaseUrl = EnvConfig.apiBaseUrl
// 拼接完整请求地址确保URL格式正确
let requestUrl = ''
if (url.startsWith('http://') || url.startsWith('https://')) {
// 如果是完整的URL直接使用
requestUrl = url
} else {
// 否则拼接基础URL和相对路径
// 确保基础URL以/结尾,而请求路径不以/开头
const baseUrlWithSlash = apiBaseUrl.endsWith('/') ? apiBaseUrl : apiBaseUrl + '/'
const path = url.startsWith('/') ? url.substring(1) : url
requestUrl = baseUrlWithSlash + path
}
console.log('请求URL:', requestUrl)
// 使用正则表达式从URL中提取主机名
const hostRegex = /^(?:https?:\/\/)?([^\/]+)/i
const matches = requestUrl.match(hostRegex)
const host = matches && matches[1] ? matches[1] : 'localhost'
let header = {}
// 添加签名和防重放攻击参数
// 1. 添加时间戳
data.timestamp = Math.floor(Date.now() / 1000)
// 2. 添加nonce随机字符串
data.nonce = RequestManager.generateNonce()
if (method.toUpperCase() == 'POST') {
// 按照键名对参数进行排序
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
console.log('签名字符串:', signStr)
// 使用MD5生成签名
const sign = md5(signStr)
data.sign = sign
header = {
'content-type': 'application/x-www-form-urlencoded',
client: client,
token: token,
adid: uni.getStorageSync('_ad_id'),
clickid: uni.getStorageSync('_click_id')
}
} else {
// GET请求添加签名
// 按照键名对参数进行排序
const sortedParams = {}
Object.keys(data).sort().forEach(key => {
sortedParams[key] = data[key]
})
// 组合参数为字符串
let signStr = ''
for (const key in sortedParams) {
signStr += key + '=' + sortedParams[key] + '&'
}
// 获取时间戳,组合为密钥
const timestamp = data.timestamp
const appSecret = host + timestamp
// 添加密钥并去除最后的&
signStr = signStr.substring(0, signStr.length - 1) + appSecret
console.log('签名字符串:', signStr)
// 使用MD5生成签名
const sign = md5(signStr)
// 添加签名到请求参数
data.sign = sign
header = {
'content-type': 'application/json',
token: token,
client: client,
}
}
// 显示加载提示
if (!Loading) {
uni.showLoading({
title: '加载中...'
})
}
// 发起网络请求
uni.request({
url: requestUrl,
method: method.toUpperCase(),
header: header,
data: data,
success: res => {
console.log("res.data.status", res.data.status)
if (res.data.status == 1) {
// 请求成功
resolve(res.data)
} else if (res.data.status == 2222) {
// 特殊状态码处理
resolve(res.data)
} else if (res.data.status == -9) {
let pages = getCurrentPages()
console.log(pages[pages.length - 1].route)
setTimeout(() => {
uni.showToast({
title: res.data.msg,
icon: 'none',
success() {
setTimeout(() => {
// #ifdef H5
uni.navigateTo({
url: '/pages/user/bangdingweb'
})
// #endif
// #ifdef MP-WEIXIN
uni.navigateTo({
url: '/pages/user/bangding'
})
// #endif
}, 1500)
}
})
}, 100)
reject(res.data)
} else if (res.data.status == 0) {
setTimeout(function () {
uni.showToast({
title: res.data.msg,
icon: 'none'
})
}, 100)
reject(res.data)
} else if (res.data.status < 0) {
var pages = getCurrentPages()
for (var a = 0; a < pages.length; a++) {
console.log(pages[a].route)
if (pages[a].route == 'pages/user/index') {
uni.setStorageSync('lgurl', pages[a].route)
uni.setStorageSync('lgurldata', JSON.stringify(pages[a].options))
}
}
console.log(requestUrl);
if (RequestManager.isUrlInWhitelist(requestUrl)) {
reject(res.data)
return;
}
setTimeout(() => {
uni.showToast({
title: '请先登录',
icon: 'none'
})
}, 100)
uni.redirectTo({
url: '/pages/user/login',
// animationType: 'pop-in',
// animationDuration: 500
})
reject(res.data)
} else {
reject(res.data)
}
typeof param.success == 'function' && param.success(res.data)
},
fail: e => {
console.error('网络请求失败:', e)
uni.showToast({
title: e.errMsg || '请求失败',
icon: 'none'
})
typeof param.fail == 'function' && param.fail(e)
reject(e)
},
complete: () => {
uni.hideLoading()
typeof param.complete == 'function' && param.complete()
}
})
})
}
/**
* 发送GET请求
* @param {String} url 请求地址
* @param {Object} data 请求参数
* @param {Boolean} showLoading 是否显示加载提示
* @returns {Promise} 返回请求Promise
*/
static get(url, data = {}, showLoading = true) {
return this.request({
url,
data,
method: 'GET',
Loading: !showLoading
})
}
/**
* 发送POST请求
* @param {String} url 请求地址
* @param {Object} data 请求参数
* @param {Boolean} showLoading 是否显示加载提示
* @returns {Promise} 返回请求Promise
*/
static post(url, data = {}, showLoading = true) {
return this.request({
url,
data,
method: 'POST',
Loading: !showLoading
})
}
}
export default RequestManager;