前端打包
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import axios, { AxiosResponse, AxiosError, InternalAxiosRequestConfig } from "axios";
|
||||
import { ElLoading, ElMessage } from "element-plus";
|
||||
import type { ResultDomain } from "@/types";
|
||||
import { API_BASE_URL } from "@/config";
|
||||
|
||||
/**
|
||||
* 扩展AxiosRequestConfig以支持自定义配置
|
||||
@@ -67,9 +68,13 @@ export const TokenManager = {
|
||||
|
||||
/**
|
||||
* 创建axios实例
|
||||
*
|
||||
* 说明:
|
||||
* - 统一使用配置模块提供的 API_BASE_URL 作为基础路径
|
||||
* - API_BASE_URL 在开发环境来自 devConfig,在生产环境来自 window.APP_RUNTIME_CONFIG
|
||||
*/
|
||||
const request = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_BASE_URL || "/api",
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json;charset=UTF-8',
|
||||
|
||||
@@ -9,6 +9,9 @@ import type { SysMenu } from '@/types';
|
||||
import { MenuType } from '@/types/enums';
|
||||
import { routes } from '@/router';
|
||||
|
||||
// 预注册所有视图组件,构建时由 Vite 解析并生成按需加载的 chunk
|
||||
const VIEW_MODULES = import.meta.glob('../views/**/*.vue');
|
||||
|
||||
/**
|
||||
* 布局组件映射
|
||||
*/
|
||||
@@ -281,69 +284,44 @@ function findFirstMenuWithUrl(menus: SysMenu[]): SysMenu | null {
|
||||
* @returns 组件异步加载函数
|
||||
*/
|
||||
function getComponent(componentName: string) {
|
||||
// 检查是否是布局组件
|
||||
// 1. 若是布局组件,直接返回预定义映射
|
||||
if (LAYOUT_MAP[componentName]) {
|
||||
return LAYOUT_MAP[componentName];
|
||||
}
|
||||
|
||||
// 处理页面组件路径
|
||||
|
||||
// 2. 将后台给的 component 字段转换为 ../views/**.vue 形式的 key
|
||||
let componentPath = componentName;
|
||||
|
||||
// 如果不是以@/开头的完整路径,则添加@/views/前缀
|
||||
|
||||
// 如果不是以 @/ 开头,则认为是相对 views 根目录的路径,例如 "user/home/HomeView"
|
||||
if (!componentPath.startsWith('@/')) {
|
||||
// 确保路径以/开头
|
||||
if (!componentPath.startsWith('/')) {
|
||||
componentPath = '/' + componentPath;
|
||||
}
|
||||
// 添加@/views前缀
|
||||
componentPath = '@/views' + componentPath;
|
||||
componentPath = '@/views' + componentPath; // => '@/views/user/home/HomeView'
|
||||
}
|
||||
|
||||
// 将@/别名转换为相对路径,因为Vite动态导入可能无法正确解析别名
|
||||
if (componentPath.startsWith('@/')) {
|
||||
componentPath = componentPath.replace('@/', '../');
|
||||
}
|
||||
|
||||
// 如果没有.vue扩展名,添加它
|
||||
|
||||
// 将别名 @/ 转为相对于当前文件的路径,必须与 import.meta.glob 中的模式一致
|
||||
componentPath = componentPath.replace(/^@\//, '../'); // => '../views/user/home/HomeView'
|
||||
|
||||
// 补全 .vue 后缀
|
||||
if (!componentPath.endsWith('.vue')) {
|
||||
componentPath += '.vue';
|
||||
}
|
||||
|
||||
|
||||
// 动态导入组件
|
||||
return () => {
|
||||
return import(/* @vite-ignore */ componentPath)
|
||||
.then(module => {
|
||||
return module;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('[路由生成] 组件加载失败:', {
|
||||
原始组件名: componentName,
|
||||
最终路径: componentPath,
|
||||
错误: error
|
||||
});
|
||||
// 返回404组件
|
||||
return import('@/views/public/error/404.vue').catch(() =>
|
||||
Promise.resolve({
|
||||
template: `<div class="component-error">
|
||||
<h3>组件加载失败</h3>
|
||||
<p>无法加载组件: ${componentPath}</p>
|
||||
<p>原始组件名: ${componentName}</p>
|
||||
<p>错误: ${error instanceof Error ? error.message : String(error)}</p>
|
||||
</div>`,
|
||||
style: `
|
||||
.component-error {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #f56565;
|
||||
background: #fed7d7;
|
||||
border-radius: 4px;
|
||||
}
|
||||
`
|
||||
})
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// 3. 从 VIEW_MODULES 中查找对应的 loader
|
||||
const loader = VIEW_MODULES[componentPath];
|
||||
|
||||
if (!loader) {
|
||||
console.error('[路由生成] 未找到组件模块', {
|
||||
原始组件名: componentName,
|
||||
期望路径: componentPath,
|
||||
可用模块: Object.keys(VIEW_MODULES)
|
||||
});
|
||||
// 找不到时退回到 404 组件
|
||||
return () => import('@/views/public/error/404.vue');
|
||||
}
|
||||
|
||||
return loader as () => Promise<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user