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;
|