255 lines
5.9 KiB
JavaScript
255 lines
5.9 KiB
JavaScript
|
|
/**
|
|||
|
|
* 网络请求封装 - 基于 uni.request 二次封装
|
|||
|
|
*/
|
|||
|
|
import config from '@/api/config.js';
|
|||
|
|
import { getToken, clearAuthInfo, getUserInfo } from './auth';
|
|||
|
|
|
|||
|
|
// 请求队列(用于防重复请求)
|
|||
|
|
const pendingRequests = new Map();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成请求唯一标识
|
|||
|
|
*/
|
|||
|
|
function generateRequestKey(options) {
|
|||
|
|
return `${options.method}_${options.url}_${JSON.stringify(options.data || {})}`;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 核心请求方法
|
|||
|
|
* @param {Object} options 请求配置
|
|||
|
|
* @param {string} options.url 请求路径(不含 baseUrl)
|
|||
|
|
* @param {string} [options.method='GET'] 请求方法
|
|||
|
|
* @param {Object} [options.data] 请求参数
|
|||
|
|
* @param {Object} [options.header] 自定义请求头
|
|||
|
|
* @param {boolean} [options.loading=false] 是否显示加载提示
|
|||
|
|
* @param {string} [options.loadingText='加载中...'] 加载提示文字
|
|||
|
|
* @param {boolean} [options.showError=true] 是否显示错误提示
|
|||
|
|
* @param {boolean} [options.preventDuplicate=false] 是否防止重复请求
|
|||
|
|
* @param {boolean} [options.isUnitId=true] 是否需要unitId参数
|
|||
|
|
* @returns {Promise}
|
|||
|
|
*/
|
|||
|
|
function request(options) {
|
|||
|
|
const { url, method = 'GET', data = {}, header = {}, loading = false, loadingText = '加载中...', showError = true, preventDuplicate = false, isUnitId = true } = options;
|
|||
|
|
|
|||
|
|
const fullUrl = url.startsWith('http') ? url : `${config.baseUrl}${url}`;
|
|||
|
|
|
|||
|
|
// 防重复请求
|
|||
|
|
const requestKey = generateRequestKey({
|
|||
|
|
method,
|
|||
|
|
url: fullUrl,
|
|||
|
|
data
|
|||
|
|
});
|
|||
|
|
if (preventDuplicate && pendingRequests.has(requestKey)) {
|
|||
|
|
return pendingRequests.get(requestKey);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 显示加载状态
|
|||
|
|
if (loading) {
|
|||
|
|
uni.showLoading({
|
|||
|
|
title: loadingText,
|
|||
|
|
mask: true
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建请求头
|
|||
|
|
const token = getToken();
|
|||
|
|
const requestHeader = {
|
|||
|
|
'Content-Type': 'application/json',
|
|||
|
|
...header
|
|||
|
|
};
|
|||
|
|
if (token) {
|
|||
|
|
requestHeader['token'] = token;
|
|||
|
|
}
|
|||
|
|
//获取用户的unitld
|
|||
|
|
const userInfo = getUserInfo();
|
|||
|
|
if (userInfo?.UnitId && isUnitId) {
|
|||
|
|
console.log('用户id的get', userInfo.UnitId);
|
|||
|
|
data['unitId'] = userInfo.UnitId;
|
|||
|
|
}
|
|||
|
|
const requestPromise = new Promise((resolve, reject) => {
|
|||
|
|
uni.request({
|
|||
|
|
url: fullUrl,
|
|||
|
|
method,
|
|||
|
|
data,
|
|||
|
|
header: requestHeader,
|
|||
|
|
timeout: config.timeout,
|
|||
|
|
success: (res) => {
|
|||
|
|
const { statusCode, data: responseData } = res;
|
|||
|
|
// HTTP 状态码判断
|
|||
|
|
if (statusCode === 200) {
|
|||
|
|
// 根据业务状态码处理(按实际后端接口约定调整)
|
|||
|
|
if (responseData.code === 1 || responseData.code === 200) {
|
|||
|
|
resolve(responseData.data);
|
|||
|
|
} else if (responseData.code === 401) {
|
|||
|
|
// Token 过期/无效
|
|||
|
|
handleUnauthorized();
|
|||
|
|
reject(responseData);
|
|||
|
|
} else {
|
|||
|
|
// 业务错误
|
|||
|
|
if (showError) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: responseData.message || '请求失败',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
reject(responseData);
|
|||
|
|
}
|
|||
|
|
} else if (statusCode === 401) {
|
|||
|
|
handleUnauthorized();
|
|||
|
|
reject(res);
|
|||
|
|
} else {
|
|||
|
|
if (showError) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: `请求错误 (${statusCode})`,
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
reject(res);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
if (showError) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '网络异常,请检查网络连接',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
reject(err);
|
|||
|
|
},
|
|||
|
|
complete: () => {
|
|||
|
|
if (loading) {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
}
|
|||
|
|
pendingRequests.delete(requestKey);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (preventDuplicate) {
|
|||
|
|
pendingRequests.set(requestKey, requestPromise);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return requestPromise;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 处理 401 未授权
|
|||
|
|
*/
|
|||
|
|
function handleUnauthorized() {
|
|||
|
|
clearAuthInfo();
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '登录已过期,请重新登录',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000
|
|||
|
|
});
|
|||
|
|
setTimeout(() => {
|
|||
|
|
uni.reLaunch({
|
|||
|
|
url: '/pages/login/login'
|
|||
|
|
});
|
|||
|
|
}, 1500);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 文件上传
|
|||
|
|
* @param {string} filePath 文件本地路径
|
|||
|
|
* @param {Object} [formData] 额外表单数据
|
|||
|
|
* @param {string} [name='file'] 文件字段名
|
|||
|
|
* @returns {Promise}
|
|||
|
|
*/
|
|||
|
|
export function upload(filePath, formData = {}, name = 'file') {
|
|||
|
|
const token = getToken();
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
uni.showLoading({
|
|||
|
|
title: '上传中...',
|
|||
|
|
mask: true
|
|||
|
|
});
|
|||
|
|
uni.uploadFile({
|
|||
|
|
url: config.uploadUrl || `${config.baseUrl}/upload`,
|
|||
|
|
filePath,
|
|||
|
|
name,
|
|||
|
|
formData,
|
|||
|
|
header: token
|
|||
|
|
? {
|
|||
|
|
Authorization: `Bearer ${token}`
|
|||
|
|
}
|
|||
|
|
: {},
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.statusCode === 200) {
|
|||
|
|
const data = JSON.parse(res.data);
|
|||
|
|
if (data.code === 0 || data.code === 200) {
|
|||
|
|
resolve(data.data);
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: data.message || '上传失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
reject(data);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
reject(res);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '上传失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
});
|
|||
|
|
reject(err);
|
|||
|
|
},
|
|||
|
|
complete: () => {
|
|||
|
|
uni.hideLoading();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 快捷方法
|
|||
|
|
/**
|
|||
|
|
* 核心请求方法
|
|||
|
|
* @param {Object} options 请求配置
|
|||
|
|
* @param {string} options.url 请求路径(不含 baseUrl)
|
|||
|
|
* @param {string} [options.method='GET'] 请求方法
|
|||
|
|
* @param {Object} [options.data] 请求参数
|
|||
|
|
* @param {Object} [options.header] 自定义请求头
|
|||
|
|
* @param {boolean} [options.loading=false] 是否显示加载提示
|
|||
|
|
* @param {string} [options.loadingText='加载中...'] 加载提示文字
|
|||
|
|
* @param {boolean} [options.showError=true] 是否显示错误提示
|
|||
|
|
* @param {boolean} [options.preventDuplicate=false] 是否防止重复请求
|
|||
|
|
* @param {boolean} [options.isUnitId=true] 是否需要unitId参数
|
|||
|
|
* @returns {Promise}
|
|||
|
|
*/
|
|||
|
|
export const get = (url, data, options = {}) =>
|
|||
|
|
request({
|
|||
|
|
url,
|
|||
|
|
method: 'GET',
|
|||
|
|
data,
|
|||
|
|
...options
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export const post = (url, data, options = {}) =>
|
|||
|
|
request({
|
|||
|
|
url,
|
|||
|
|
method: 'POST',
|
|||
|
|
data,
|
|||
|
|
...options
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export const put = (url, data, options = {}) =>
|
|||
|
|
request({
|
|||
|
|
url,
|
|||
|
|
method: 'PUT',
|
|||
|
|
data,
|
|||
|
|
...options
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export const del = (url, data, options = {}) =>
|
|||
|
|
request({
|
|||
|
|
url,
|
|||
|
|
method: 'DELETE',
|
|||
|
|
data,
|
|||
|
|
...options
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export default request;
|