dma_handbook/docs/utils/request.js

160 lines
6.1 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 { 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();
const token = userStore.token || localStorage.getItem('rt_token') || '';
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();
localStorage.removeItem('rt_token');
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;