import { toRaw, unref } from 'vue'; import { defineStore } from 'pinia'; import { RouteRecordRaw } from 'vue-router'; import { store } from '@/store'; import { asyncRoutes, constantRouter } from '@/router/index'; import { generatorDynamicRouter } from '@/router/generator-routers'; import { useProjectSetting } from '@/hooks/setting/useProjectSetting'; import { isUrl } from '@/utils'; import { cloneDeep } from 'lodash-es'; interface TreeHelperConfig { id: string; children: string; pid: string; } const DEFAULT_CONFIG: TreeHelperConfig = { id: 'id', children: 'children', pid: 'pid', }; const getConfig = (config: Partial) => Object.assign({}, DEFAULT_CONFIG, config); export interface IAsyncRouteState { menus: RouteRecordRaw[]; routers: any[]; addRouters: any[]; keepAliveComponents: string[]; isDynamicAddedRoute: boolean; } function filter( tree: T[], func: (n: T) => boolean, config: Partial = {}, ): T[] { config = getConfig(config); const children = config.children as string; function listFilter(list: T[]) { return list .map((node: any) => ({ ...node })) .filter((node) => { node[children] = node[children] && listFilter(node[children]); return func(node) || (node[children] && node[children].length); }); } return listFilter(tree); } function formatRelativePath(menus, parent?) { // 计算路由绝对路径 return cloneDeep(menus).map((route) => { // if (parent) { // route.path = `${parent.path || ''}/${route.path}`; // } else { // route.path = `/${route.path}`; // } // route.path = route.path.replace('//', '/'); //如果是外部地址,特殊处理 if (route.meta?.target && isUrl(route.name)) { route.path = route.name; } // format children routes if (route.children && route.children.length > 0) { route.children = formatRelativePath(route.children, route); } return route; }); } export const useAsyncRouteStore = defineStore({ id: 'app-async-route', state: (): IAsyncRouteState => ({ menus: [], routers: constantRouter, addRouters: [], keepAliveComponents: [], // Whether the route has been dynamically added isDynamicAddedRoute: false, }), getters: { getMenus(): RouteRecordRaw[] { return formatRelativePath(this.menus); }, getIsDynamicAddedRoute(): boolean { return this.isDynamicAddedRoute; }, getRouters() { return toRaw(this.addRouters); }, }, actions: { //从缓存列表删除路由 removeKeepAliveComponents(compNames) { if (!compNames || !compNames.length) return; this.keepAliveComponents = this.keepAliveComponents.filter( (item) => !compNames.includes(item), ); }, setDynamicAddedRoute(added: boolean) { this.isDynamicAddedRoute = added; }, // 设置动态路由 setRouters(routers) { this.addRouters = routers; this.routers = constantRouter.concat(routers); }, setMenus(menus) { // 设置动态路由 this.menus = menus; }, setKeepAliveComponents(compNames) { // 设置需要缓存的组件 this.keepAliveComponents = compNames; }, async generateRoutes(data) { let accessedRouters; const permissionsList = data.permissions || []; const routeFilter = (route) => { const { meta } = route; const { permissions, authEvery } = meta || {}; if (!permissions) return true; if (authEvery === true) { return permissionsList.every((item) => permissions.includes(item.value)); } return permissionsList.some((item) => permissions.includes(item.value)); }; const { getPermissionMode } = useProjectSetting(); const permissionMode = unref(getPermissionMode); if (permissionMode === 'BACK') { // 动态获取菜单 try { accessedRouters = await generatorDynamicRouter(); } catch (error) { console.log(error); } } else { try { //过滤账户是否拥有某一个权限,并将菜单从加载列表移除 accessedRouters = filter(asyncRoutes, routeFilter); } catch (error) { console.log(error); } } accessedRouters = accessedRouters.filter(routeFilter); this.setRouters(accessedRouters); this.setMenus(accessedRouters); return toRaw(accessedRouters); }, }, }); // Need to be used outside the setup export function useAsyncRouteStoreWidthOut() { return useAsyncRouteStore(store); }