- 重命名 13 个 API 文件,去掉 -api 后缀 * src/api/auth-api.ts auth.ts * src/api/codegen-api.ts codegen.ts * src/api/file-api.ts file.ts * src/api/system/*.ts (9个文件) - 批量更新 50+ 处 API 引用路径 - 修复 websocket 和枚举导入路径 - 确保零编码问题(使用 UTF-8 编码)
105 lines
3.2 KiB
TypeScript
105 lines
3.2 KiB
TypeScript
import type { RouteRecordRaw } from "vue-router";
|
||
import { constantRoutes } from "@/router";
|
||
import { store } from "@/store";
|
||
import router from "@/router";
|
||
|
||
import MenuAPI, { type RouteVO } from "@/api/system/menu";
|
||
const modules = import.meta.glob("../../views/**/**.vue");
|
||
const Layout = () => import("../../layouts/index.vue");
|
||
|
||
export const usePermissionStore = defineStore("permission", () => {
|
||
// 所有路由(静态路由 + 动态路由)
|
||
const routes = ref<RouteRecordRaw[]>([]);
|
||
// 混合布局的左侧菜单路由
|
||
const mixLayoutSideMenus = ref<RouteRecordRaw[]>([]);
|
||
// 动态路由是否已生成
|
||
const isRouteGenerated = ref(false);
|
||
|
||
/** 生成动态路由 */
|
||
async function generateRoutes(): Promise<RouteRecordRaw[]> {
|
||
try {
|
||
const data = await MenuAPI.getRoutes(); // 获取当前登录人的菜单路由
|
||
const dynamicRoutes = transformRoutes(data);
|
||
|
||
routes.value = [...constantRoutes, ...dynamicRoutes];
|
||
isRouteGenerated.value = true;
|
||
|
||
return dynamicRoutes;
|
||
} catch (error) {
|
||
// 路由生成失败,重置状态
|
||
isRouteGenerated.value = false;
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/** 设置混合布局左侧菜单 */
|
||
const setMixLayoutSideMenus = (parentPath: string) => {
|
||
const parentMenu = routes.value.find((item) => item.path === parentPath);
|
||
mixLayoutSideMenus.value = parentMenu?.children || [];
|
||
};
|
||
|
||
/** 重置路由状态 */
|
||
const resetRouter = () => {
|
||
// 移除动态添加的路由
|
||
const constantRouteNames = new Set(constantRoutes.map((route) => route.name).filter(Boolean));
|
||
routes.value.forEach((route) => {
|
||
if (route.name && !constantRouteNames.has(route.name)) {
|
||
router.removeRoute(route.name);
|
||
}
|
||
});
|
||
|
||
// 重置所有状态
|
||
routes.value = [...constantRoutes];
|
||
mixLayoutSideMenus.value = [];
|
||
isRouteGenerated.value = false;
|
||
};
|
||
|
||
return {
|
||
routes,
|
||
mixLayoutSideMenus,
|
||
isRouteGenerated,
|
||
generateRoutes,
|
||
setMixLayoutSideMenus,
|
||
resetRouter,
|
||
};
|
||
});
|
||
|
||
/**
|
||
* 转换后端路由数据为Vue Router配置
|
||
* 处理组件路径映射和Layout层级嵌套
|
||
*/
|
||
const transformRoutes = (routes: RouteVO[], isTopLevel: boolean = true): RouteRecordRaw[] => {
|
||
return routes.map((route) => {
|
||
const { component, children, ...args } = route;
|
||
|
||
// 处理组件:顶层或非Layout保留组件,中间层Layout设为undefined
|
||
const processedComponent = isTopLevel || component !== "Layout" ? component : undefined;
|
||
|
||
const normalizedRoute = { ...args } as RouteRecordRaw;
|
||
|
||
if (!processedComponent) {
|
||
// 多级菜单的父级菜单,不需要组件
|
||
normalizedRoute.component = undefined;
|
||
} else {
|
||
// 动态导入组件,Layout特殊处理,找不到组件时返回404
|
||
normalizedRoute.component =
|
||
processedComponent === "Layout"
|
||
? Layout
|
||
: modules[`../../views/${processedComponent}.vue`] ||
|
||
modules[`../../views/error/404.vue`];
|
||
}
|
||
|
||
// 递归处理子路由
|
||
if (children && children.length > 0) {
|
||
normalizedRoute.children = transformRoutes(children, false);
|
||
}
|
||
|
||
return normalizedRoute;
|
||
});
|
||
};
|
||
|
||
/** 非组件环境使用权限store */
|
||
export function usePermissionStoreHook() {
|
||
return usePermissionStore(store);
|
||
}
|