136 lines
4.3 KiB
TypeScript
136 lines
4.3 KiB
TypeScript
// utils/request.ts
|
|
import { RequestOptions, ApiResponse, RequestPromise } from '../types/request';
|
|
|
|
// 基础域名(区分开发/生产环境,建议通过环境变量配置)
|
|
|
|
const BASE_URL = 'https://yueyingkeji.twaycloud.com/api' // 生产环境‘
|
|
|
|
/**
|
|
* 通用请求函数(Promise 风格)
|
|
* @param options 请求配置
|
|
* @returns Promise<ApiResponse<T>>
|
|
*/
|
|
export const request = <T = any>(options: RequestOptions): RequestPromise<T> => {
|
|
// 解构配置,设置默认值
|
|
const {
|
|
url,
|
|
method = 'GET',
|
|
data = {},
|
|
header = {},
|
|
timeout = 10000
|
|
} = options;
|
|
let { showLoading, ...realData } = data;
|
|
|
|
// 2. 真正要传给接口的数据(已经剔除了 showLoading)
|
|
const requestData = realData;
|
|
showLoading = options.data?options.data.showLoading:true;
|
|
// 显示加载中弹窗
|
|
if (showLoading) {
|
|
wx.showLoading({ title: options.method == 'POST'?'提交中...':'加载中...', mask: true });
|
|
}
|
|
|
|
// 拼接完整URL(相对路径补全域名,完整URL直接使用)
|
|
const fullUrl = url.startsWith('http') ? url : `${BASE_URL}${url}`;
|
|
const userInfo = wx.getStorageSync('userInfo');
|
|
const token = `${userInfo.id},${userInfo.accesstoken}`;
|
|
const devicecode = wx.getStorageSync('deviceCode');
|
|
// 构建请求头(默认JSON格式,自动携带登录Token)
|
|
const defaultHeader = {
|
|
'Content-Type': 'application/json',
|
|
// 从本地缓存获取Token(结合之前的登录逻辑)
|
|
'Authorization': token,
|
|
'devicecode': devicecode
|
|
};
|
|
const finalHeader = { ...defaultHeader, ...header };
|
|
|
|
// 返回Promise,封装wx.request
|
|
return new Promise((resolve, reject) => {
|
|
wx.request({
|
|
url: fullUrl,
|
|
method,
|
|
data: requestData,
|
|
header: finalHeader,
|
|
timeout,
|
|
// 成功回调(后端返回响应,无论code是否为200)
|
|
success: (res) => {
|
|
// 类型断言:将res.data转为ApiResponse类型
|
|
// const response = res.data;
|
|
// 业务错误(如code≠200):reject出去,外层catch处理
|
|
if (res.statusCode == 401) {
|
|
const userInfo = wx.getStorageSync('userInfo');
|
|
if (userInfo) {
|
|
wx.showToast({ title: '登录已过期,请重新登录', icon: 'none',duration: 1500 });
|
|
wx.removeStorageSync('userInfo');
|
|
setTimeout(() => {
|
|
wx.reLaunch({ url: '/pages/login/login' });
|
|
}, 1300);
|
|
}
|
|
return;
|
|
}
|
|
if ((!res.statusCode || res.statusCode != 200) || res.data.success == false) {
|
|
wx.showToast({ title: res.data.message || '请求失败', icon: 'none',duration: 1500 });
|
|
reject({
|
|
type: 'business', // 业务错误类型
|
|
...res
|
|
});
|
|
return;
|
|
}
|
|
|
|
// 业务成功:resolve返回响应数据
|
|
resolve(res);
|
|
},
|
|
// 失败回调(网络错误、超时等)
|
|
fail: (err) => {
|
|
const errMsg = err.errMsg || '网络异常,请稍后重试';
|
|
wx.showToast({ title: errMsg, icon: 'none',duration: 1500 });
|
|
reject({
|
|
type: 'network', // 网络错误类型
|
|
code: -1,
|
|
msg: errMsg,
|
|
data: null
|
|
});
|
|
},
|
|
// 完成回调(无论成功/失败,关闭加载弹窗)
|
|
complete: () => {
|
|
if (showLoading) {
|
|
setTimeout(() => {
|
|
wx.hideLoading();
|
|
}, 500);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
// 封装常用请求方法(简化调用)
|
|
export const get = <T = any>(
|
|
url: string,
|
|
data?: Record<string, any>,
|
|
options?: Omit<RequestOptions, 'url' | 'method'>
|
|
): RequestPromise<T> => {
|
|
return request<T>({ url, method: 'GET', ...data, ...options });
|
|
};
|
|
|
|
export const post = <T = any>(
|
|
url: string,
|
|
data?: Record<string, any>,
|
|
options?: Omit<RequestOptions, 'url' | 'method'>
|
|
): RequestPromise<T> => {
|
|
return request<T>({ url, method: 'POST', data, ...options });
|
|
};
|
|
|
|
export const put = <T = any>(
|
|
url: string,
|
|
data?: Record<string, any>,
|
|
options?: Omit<RequestOptions, 'url' | 'method'>
|
|
): RequestPromise<T> => {
|
|
return request<T>({ url, method: 'PUT', data, ...options });
|
|
};
|
|
|
|
export const del = <T = any>(
|
|
url: string,
|
|
data?: Record<string, any>,
|
|
options?: Omit<RequestOptions, 'url' | 'method'>
|
|
): RequestPromise<T> => {
|
|
return request<T>({ url, method: 'DELETE', data, ...options });
|
|
}; |