dma_handbook/docs/utils/request.js

162 lines
6.2 KiB
JavaScript
Raw Normal View History

2026-02-05 10:24:40 +08:00
import { ref } from 'vue';
import axios from 'axios';
import { ContentTypeEnum } from './httpEnum';
import { useUserStore } from '../.vuepress/store/modules/user';
// 适配VuePress服务端渲染仅在浏览器环境执行
const isBrowser = typeof window !== 'undefined';
// 协议自动适配
const baseHref = isBrowser ? (window.location.href.includes('https:') ? 'https:' : 'http:') : 'http:';
// 创建axios实例
const service = axios.create({
baseURL: 'https://health.ufutx.com/',
withCredentials: false,
timeout: 50000,
});
// 自定义请求配置仅保留hideLoading扩展
export const requestConfig = {
hideLoading: false
};
// 原生加载提示极简版适配VuePress
let loadingInstance = null;
const showLoading = (msg = '加载中...') => {
if (!isBrowser || loadingInstance) return;
loadingInstance = document.createElement('div');
loadingInstance.style.cssText = `position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);padding:8px 16px;background:rgba(0,0,0,0.7);color:#fff;border-radius:4px;z-index:99999;font-size:14px;`;
loadingInstance.innerText = msg;
document.body.appendChild(loadingInstance);
};
const closeLoading = () => {
if (!isBrowser || !loadingInstance) return;
document.body.removeChild(loadingInstance);
loadingInstance = null;
};
// 原生全局提示(极简版)
export const showToast = (msg = '操作失败', duration = 2000) => {
if (!isBrowser) return;
const toast = document.createElement('div');
toast.style.cssText = `position:fixed;top:80%;left:50%;transform:translate(-50%,-50%);padding:8px 16px;background:rgba(0,0,0,0.7);color:#fff;border-radius:4px;z-index:99999;font-size:14px;pointer-events:none;`;
toast.innerText = msg;
document.body.appendChild(toast);
setTimeout(() => document.body.removeChild(toast), duration);
};
// 请求拦截器核心保留Token、Content-Type、版本号
service.interceptors.request.use(
(config) => {
// 加载提示控制
if (!config.hideLoading) showLoading();
// 初始化请求头
if (!config.headers) config.headers = {};
// 默认Content-Type为JSON
config.headers['Content-Type'] = config.headers['Content-Type'] || ContentTypeEnum.JSON;
// 携带版本号
if (isBrowser) config.headers['Version'] = import.meta.env.VITE_BASE_API_VERSION;
// 携带Token仅保留核心rt_token联动Pinia
if (isBrowser) {
const userStore = useUserStore();
2026-02-06 10:12:08 +08:00
const token = userStore.token || typeof window !== 'undefined' ? localStorage.getItem('rt_token') : '' || '';
2026-02-05 10:24:40 +08:00
if (token) config.headers['Authorization'] = `Bearer ${token}`;
}
// 处理POST表单参数
if (config.method?.toLocaleUpperCase() === 'POST' && config.data) {
const contentType = config.headers['Content-Type'];
if (contentType === ContentTypeEnum.FORM_URLENCODED) {
config.data = qs.stringify(config.data);
}
}
return config;
},
(error) => {
closeLoading();
console.log('请求错误:', error);
return Promise.reject(error);
}
);
// 响应拦截器:精简状态码,仅保留核心业务逻辑
service.interceptors.response.use(
(response) => {
closeLoading();
const res = response.data;
// 成功码仅保留0后端统一成功标识剔除冗余兼容
if (res.code === 0) return Promise.resolve(res.data);
// 业务错误code!==0统一提示
showToast(res.msg || res.message || '请求失败');
return Promise.reject(res);
},
(error) => {
closeLoading();
// 网络/超时错误
if (error.message?.includes('timeout')) {
showToast('网络超时,请稍后重试');
}
// 401未授权核心鉴权逻辑跳登录页适配VuePress base路径
else if (error.response?.status === 401 && isBrowser) {
showToast('登录已过期,请重新登录');
const userStore = useUserStore();
// 清除状态,跳登录页并记录跳转地址
userStore.resetStore();
2026-02-06 10:12:08 +08:00
if (typeof window !== 'undefined') {
localStorage.removeItem('rt_token');
}
2026-02-05 10:24:40 +08:00
const redirect = encodeURIComponent(window.location.href);
window.location.href = `/dma_handbook/login?redirect=${redirect}`;
}
// 其他错误
else {
showToast(error.message || '网络异常');
}
console.log('响应错误:', error);
return Promise.reject(error);
}
);
// 统一请求方法极简封装适配VuePress
const request = (config) => {
return new Promise((resolve, reject) => {
service
.request(config)
.then((res) => resolve(res))
.catch((err) => reject(err));
});
};
// 放在request.js文件末尾showToast导出后、request默认导出前
/**
* 全局获取用户信息接口每次进入页面调用
* @param {object} userStore - Pinia用户仓库实例传入避免重复实例化
* @returns {Promise<boolean>} - 是否获取成功
*/
export const getUserInfo = async (userStore) => {
// 非浏览器环境/未登录,直接返回失败
if (typeof window === 'undefined' || !userStore.token) return false;
try {
const res = await request({
url: '/api/app/get/service/user/info', // 你的用户信息接口地址baseURL会自动拼接
method: 'get',
hideLoading: true, // 隐藏加载提示,避免页面闪烁
});
// 按你的接口返回格式更新仓库
if (res && res.service_user_info) {
userStore.setUserInfo(res.service_user_info); // 更新用户信息
}
if (res && res.role_list) {
userStore.setRoles(res.role_list); // 更新权限角色
}
return true;
} catch (err) {
// 接口失败轻量提示,不阻塞页面
showToast('用户信息同步失败', 1500);
console.log('获取用户信息失败:', err);
return false;
}
};
export default request;