mall-uniapp/sheep/request/index.js

247 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Shopro-request
* @description api模块管理loading配置请求拦截错误处理
*/
import Request from 'luch-request';
import {
baseUrl,
apiPath
} from '@/sheep/config';
import $store from '@/sheep/store';
import $platform from '@/sheep/platform';
import {
showAuthModal
} from '@/sheep/hooks/useModal';
const options = {
// 显示操作成功消息 默认不显示
showSuccess: false,
// 成功提醒 默认使用后端返回值
successMsg: '',
// 显示失败消息 默认显示
showError: true,
// 失败提醒 默认使用后端返回信息
errorMsg: '',
// 显示请求时loading模态框 默认显示
showLoading: true,
// loading提醒文字
loadingMsg: '加载中',
// 需要授权才能请求 默认放开
auth: false,
// ...
};
// Loading全局实例
let LoadingInstance = {
target: null,
count: 0,
};
/**
* 关闭loading
*/
function closeLoading() {
if (LoadingInstance.count > 0) LoadingInstance.count--;
if (LoadingInstance.count === 0) uni.hideLoading();
}
/**
* @description 请求基础配置 可直接使用访问自定义请求
*/
const http = new Request({
baseURL: baseUrl,
timeout: 8000,
method: 'GET',
header: {
Accept: 'text/json',
'Content-Type': 'application/json;charset=UTF-8',
platform: $platform.name,
},
// #ifdef APP-PLUS
sslVerify: false,
// #endif
// #ifdef H5
// 跨域请求时是否携带凭证cookies仅H5支持HBuilderX 2.6.15+
withCredentials: false,
// #endif
custom: options,
});
/**
* @description 请求拦截器
*/
http.interceptors.request.use(
(config) => {
// 自定义处理【auth 授权】:必须登录的接口,则跳出 AuthModal 登录弹窗
if (config.custom.auth && !$store('user').isLogin) {
showAuthModal();
return Promise.reject();
}
// 自定义处理【loading 加载中】:如果需要显示 loading则显示 loading
if (config.custom.showLoading) {
LoadingInstance.count++;
LoadingInstance.count === 1 &&
uni.showLoading({
title: config.custom.loadingMsg,
mask: true,
fail: () => {
uni.hideLoading();
},
});
}
// 增加 token 令牌、terminal 终端、tenant 租户的请求头
const token = uni.getStorageSync('token');
if (token) config.header['Authorization'] = token;
// TODO 芋艿:特殊处理
if (config.url.indexOf('/app-api/') !== -1) {
config.header['Accept'] = '*/*'
config.header['tenant-id'] = '1';
config.header['terminal'] = '20';
// config.header['Authorization'] = 'Bearer test247';
}
return config;
},
(error) => {
return Promise.reject(error);
},
);
/**
* @description 响应拦截器
*/
http.interceptors.response.use(
(response) => {
// 约定:如果是 /auth/ 下的 URL 地址,并且返回了 accessToken 说明是登录相关的接口,则自动设置登陆令牌
if (response.config.url.indexOf('/member/auth/') >= 0 && response.data?.data?.accessToken) {
$store('user').setToken(response.data.data.accessToken);
}
// 自定处理【loading 加载中】:如果需要显示 loading则关闭 loading
response.config.custom.showLoading && closeLoading();
// 自定义处理【error 错误提示】:如果需要显示错误提示,则显示错误提示
if (response.data.code !== 0) {
// 特殊:如果 401 错误码,则跳转到登录页 or 刷新令牌
if (response.data.code === 401) {
handleAuthorized();
}
// 错误提示
if (response.config.custom.showError) {
uni.showToast({
title: response.data.msg || '服务器开小差啦,请稍后再试~',
icon: 'none',
mask: true,
});
}
}
// 自定义处理【showSuccess 成功提示】:如果需要显示成功提示,则显示成功提示
if (response.config.custom.showSuccess
&& response.config.custom.successMsg !== ''
&& response.data.code === 0) {
uni.showToast({
title: response.config.custom.successMsg,
icon: 'none',
});
}
// 返回结果:包括 code + data + msg
return Promise.resolve(response.data);
},
(error) => {
const userStore = $store('user');
const isLogin = userStore.isLogin;
let errorMessage = '网络请求出错';
if (error !== undefined) {
switch (error.statusCode) {
case 400:
errorMessage = '请求错误';
break;
case 401:
if (isLogin) {
errorMessage = '您的登陆已过期';
} else {
errorMessage = '请先登录';
}
handleAuthorized()
break;
case 403:
errorMessage = '拒绝访问';
break;
case 404:
errorMessage = '请求出错';
break;
case 408:
errorMessage = '请求超时';
break;
case 429:
errorMessage = '请求频繁, 请稍后再访问';
break;
case 500:
errorMessage = '服务器开小差啦,请稍后再试~';
break;
case 501:
errorMessage = '服务未实现';
break;
case 502:
errorMessage = '网络错误';
break;
case 503:
errorMessage = '服务不可用';
break;
case 504:
errorMessage = '网络超时';
break;
case 505:
errorMessage = 'HTTP 版本不受支持';
break;
}
if (error.errMsg.includes('timeout')) errorMessage = '请求超时';
// #ifdef H5
if (error.errMsg.includes('Network'))
errorMessage = window.navigator.onLine ? '服务器异常' : '请检查您的网络连接';
// #endif
}
if (error && error.config) {
if (error.config.custom.showError === false) {
uni.showToast({
title: error.data?.msg || errorMessage,
icon: 'none',
mask: true,
});
}
error.config.custom.showLoading && closeLoading();
}
return false;
},
);
/**
* 处理 401 未登录的错误
*/
const handleAuthorized = () => {
const userStore = $store('user');
userStore.logout(true);
showAuthModal();
}
const request = (config) => {
if (config.url[0] !== '/') {
config.url = apiPath + config.url;
}
// TODO 芋艿:额外拼接
if (config.url.indexOf('/app-api/') >= 0) {
// config.url = 'http://api-dashboard.yudao.iocoder.cn' + config.url; // 调用【云端】
config.url = 'http://127.0.0.1:48080' + config.url; // 调用【本地】
// config.url = 'http://yunai.natapp1.cc' + config.url; // 调用【natapp】
}
return http.middleware(config);
};
export default request;