208 lines
6.5 KiB
TypeScript
Raw Normal View History

2023-04-02 01:01:56 +08:00
import { defineStore } from 'pinia';
import router, { constantRoutes, dynamicRoutes } from '@/router';
import store from '@/store';
import { getRouters } from '@/api/menu';
import auth from '@/plugins/auth';
import { RouteRecordRaw } from 'vue-router';
2023-04-02 01:01:56 +08:00
import Layout from '@/layout/index.vue';
import ParentView from '@/components/ParentView/index.vue';
import InnerLink from '@/layout/components/InnerLink/index.vue';
2025-03-12 12:08:23 +08:00
import { ref } from 'vue';
import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
2023-04-02 01:01:56 +08:00
// 匹配views里面所有的.vue文件
const modules = import.meta.glob('./../../views/**/*.vue');
export const usePermissionStore = defineStore('permission', () => {
const routes = ref<RouteRecordRaw[]>([]);
const addRoutes = ref<RouteRecordRaw[]>([]);
const defaultRoutes = ref<RouteRecordRaw[]>([]);
const topbarRouters = ref<RouteRecordRaw[]>([]);
const sidebarRouters = ref<RouteRecordRaw[]>([]);
2023-04-02 01:01:56 +08:00
2023-12-27 12:12:51 +08:00
const getRoutes = (): RouteRecordRaw[] => {
2024-08-02 13:53:48 +08:00
return routes.value as RouteRecordRaw[];
2023-12-27 12:12:51 +08:00
};
const getDefaultRoutes = (): RouteRecordRaw[] => {
return defaultRoutes.value as RouteRecordRaw[];
};
2023-12-27 12:12:51 +08:00
const getSidebarRoutes = (): RouteRecordRaw[] => {
2024-08-02 13:53:48 +08:00
return sidebarRouters.value as RouteRecordRaw[];
2023-12-27 12:12:51 +08:00
};
const getTopbarRoutes = (): RouteRecordRaw[] => {
2024-08-02 13:53:48 +08:00
return topbarRouters.value as RouteRecordRaw[];
2023-12-27 12:12:51 +08:00
};
const setRoutes = (newRoutes: RouteRecordRaw[]): void => {
2023-04-03 00:05:09 +08:00
addRoutes.value = newRoutes;
routes.value = constantRoutes.concat(newRoutes);
};
const setDefaultRoutes = (routes: RouteRecordRaw[]): void => {
2023-04-03 00:05:09 +08:00
defaultRoutes.value = constantRoutes.concat(routes);
};
const setTopbarRoutes = (routes: RouteRecordRaw[]): void => {
2023-04-03 00:05:09 +08:00
topbarRouters.value = routes;
};
const setSidebarRouters = (routes: RouteRecordRaw[]): void => {
2023-04-03 00:05:09 +08:00
sidebarRouters.value = routes;
};
const generateRoutes = async (): Promise<RouteRecordRaw[]> => {
2023-04-03 00:05:09 +08:00
const res = await getRouters();
const { data } = res;
const sdata = JSON.parse(JSON.stringify(data));
const rdata = JSON.parse(JSON.stringify(data));
const defaultData = JSON.parse(JSON.stringify(data));
const sidebarRoutes = filterAsyncRouter(sdata);
const rewriteRoutes = filterAsyncRouter(rdata, undefined, true);
const defaultRoutes = filterAsyncRouter(defaultData);
const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
asyncRoutes.forEach((route) => {
router.addRoute(route);
});
setRoutes(rewriteRoutes);
setSidebarRouters(constantRoutes.concat(sidebarRoutes));
setDefaultRoutes(sidebarRoutes);
setTopbarRoutes(defaultRoutes);
2024-06-26 11:34:40 +08:00
// 路由name重复检查
duplicateRouteChecker(asyncRoutes, sidebarRoutes);
return new Promise<RouteRecordRaw[]>((resolve) => resolve(rewriteRoutes));
2023-04-03 00:05:09 +08:00
};
2023-04-02 01:01:56 +08:00
2023-04-03 00:05:09 +08:00
/**
*
* @param asyncRouterMap
* @param lastRouter
* @param type
*/
const filterAsyncRouter = (asyncRouterMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw, type = false): RouteRecordRaw[] => {
2023-04-03 00:05:09 +08:00
return asyncRouterMap.filter((route) => {
if (type && route.children) {
route.children = filterChildren(route.children, undefined);
}
// Layout ParentView 组件特殊处理
if (route.component?.toString() === 'Layout') {
route.component = Layout;
} else if (route.component?.toString() === 'ParentView') {
route.component = ParentView;
} else if (route.component?.toString() === 'InnerLink') {
route.component = InnerLink;
} else {
route.component = loadView(route.component, route.name as string);
2023-04-03 00:05:09 +08:00
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type);
} else {
delete route.children;
delete route.redirect;
}
return true;
});
};
const filterChildren = (childrenMap: RouteRecordRaw[], lastRouter?: RouteRecordRaw): RouteRecordRaw[] => {
let children: RouteRecordRaw[] = [];
childrenMap.forEach((el) => {
el.path = lastRouter ? lastRouter.path + '/' + el.path : el.path;
if (el.children && el.children.length && el.component?.toString() === 'ParentView') {
children = children.concat(filterChildren(el.children, el));
} else {
children.push(el);
2023-04-03 00:05:09 +08:00
}
});
2023-04-03 00:05:09 +08:00
return children;
};
2023-12-27 12:12:51 +08:00
return {
routes,
topbarRouters,
sidebarRouters,
defaultRoutes,
getRoutes,
getDefaultRoutes,
2023-12-27 12:12:51 +08:00
getSidebarRoutes,
getTopbarRoutes,
setRoutes,
generateRoutes,
setSidebarRouters
};
2023-04-02 01:01:56 +08:00
});
// 动态路由遍历,验证是否具备权限
export const filterDynamicRoutes = (routes: RouteRecordRaw[]) => {
const res: RouteRecordRaw[] = [];
2023-04-03 00:05:09 +08:00
routes.forEach((route) => {
if (route.permissions) {
if (auth.hasPermiOr(route.permissions)) {
res.push(route);
}
} else if (route.roles) {
if (auth.hasRoleOr(route.roles)) {
res.push(route);
}
}
});
return res;
2023-04-02 01:01:56 +08:00
};
export const loadView = (view: any, name: string) => {
2023-04-03 00:05:09 +08:00
let res;
for (const path in modules) {
const viewsIndex = path.indexOf('/views/');
let dir = path.substring(viewsIndex + 7);
dir = dir.substring(0, dir.lastIndexOf('.vue'));
2023-04-03 00:05:09 +08:00
if (dir === view) {
res = createCustomNameComponent(modules[path], { name });
return res;
2023-04-03 00:05:09 +08:00
}
}
return res;
2023-04-02 01:01:56 +08:00
};
// 非setup
export const usePermissionStoreHook = () => {
2023-04-03 00:05:09 +08:00
return usePermissionStore(store);
2023-04-02 01:01:56 +08:00
};
2024-06-26 11:34:40 +08:00
interface Route {
name?: string | symbol;
path: string;
children?: Route[];
}
/**
* name是否重复
* @param localRoutes
* @param routes
*/
function duplicateRouteChecker(localRoutes: Route[], routes: Route[]) {
// 展平
function flatRoutes(routes: Route[]) {
const res: Route[] = [];
routes.forEach((route) => {
if (route.children) {
res.push(...flatRoutes(route.children));
} else {
res.push(route);
}
});
return res;
}
const allRoutes = flatRoutes([...localRoutes, ...routes]);
const nameList: string[] = [];
allRoutes.forEach((route) => {
const name = route.name.toString();
if (name && nameList.includes(name)) {
2024-06-26 11:59:41 +08:00
const message = `路由名称: [${name}] 重复, 会造成 404`;
console.error(message);
ElNotification({
title: '路由名称重复',
message,
type: 'error'
});
2024-06-26 11:34:40 +08:00
return;
}
nameList.push(route.name.toString());
});
}