import type { AppRouteRecordRaw, Menu } from '/@/router/types'; import { defineStore } from 'pinia'; import { store } from '/@/store'; import { useI18n } from '/@/hooks/web/useI18n'; import { useUserStore } from './user'; import { useAppStoreWithOut } from './app'; import { toRaw } from 'vue'; import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper'; import { transformRouteToMenu } from '/@/router/helper/menuHelper'; import projectSetting from '/@/settings/projectSetting'; import { PermissionModeEnum } from '/@/enums/appEnum'; import { asyncRoutes } from '/@/router/routes'; import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; import { filter } from '/@/utils/helper/treeHelper'; import { getMenuList } from '/@/api/sys/menu'; import { getPermCode } from '/@/api/sys/user'; import { isArray } from '/@/utils/is'; import { useMessage } from '/@/hooks/web/useMessage'; import { PageEnum } from '/@/enums/pageEnum'; import { intersection } from 'lodash-es'; interface PermissionState { // Permission code list permCodeList: string[] ; // Whether the route has been dynamically added isDynamicAddedRoute: boolean; // To trigger a menu update lastBuildMenuTime: number; // Backstage menu list backMenuList: Menu[]; frontMenuList: Menu[]; } export const usePermissionStore = defineStore({ id: 'app-permission', state: (): PermissionState => ({ permCodeList: [], // Whether the route has been dynamically added isDynamicAddedRoute: false, // To trigger a menu update lastBuildMenuTime: 0, // Backstage menu list backMenuList: [], // menu List frontMenuList: [], }), getters: { getPermCodeList(): string[] | number[] { return this.permCodeList; }, getBackMenuList(): Menu[] { return this.backMenuList; }, getFrontMenuList(): Menu[] { return this.frontMenuList; }, getLastBuildMenuTime(): number { return this.lastBuildMenuTime; }, getIsDynamicAddedRoute(): boolean { return this.isDynamicAddedRoute; }, }, actions: { setPermCodeList(codeList: string[]) { this.permCodeList = codeList; }, getCheckPerm(value:string|string[]): boolean{ const permCodeList = this.permCodeList; if (!value) { return false; } if (!isArray(value)) { return permCodeList?.includes(value); } return (intersection(value, permCodeList)).length > 0; }, setBackMenuList(list: Menu[]) { this.backMenuList = list; list?.length > 0 && this.setLastBuildMenuTime(); }, setFrontMenuList(list: Menu[]) { this.frontMenuList = list; }, setLastBuildMenuTime() { this.lastBuildMenuTime = new Date().getTime(); }, setDynamicAddedRoute(added: boolean) { this.isDynamicAddedRoute = added; }, resetState(): void { this.isDynamicAddedRoute = false; this.permCodeList = []; this.backMenuList = []; this.lastBuildMenuTime = 0; }, async changePermissionCode() { const codeList = await getPermCode(); const permsList = codeList.map(ele => ele.perms) this.setPermCodeList(permsList); }, async buildRoutesAction(): Promise { const { t } = useI18n(); const userStore = useUserStore(); const appStore = useAppStoreWithOut(); let routes: AppRouteRecordRaw[] = []; const roleList = toRaw(userStore.getRoleList) || []; const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig; const routeFilter = (route: AppRouteRecordRaw) => { const { meta } = route; const { roles } = meta || {}; if (!roles) return true; return roleList.some((role) => roles.includes(role)); }; const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => { const { meta } = route; const { ignoreRoute } = meta || {}; return !ignoreRoute; }; /** * @description 根据设置的首页path,修正routes中的affix标记(固定首页) * */ const patchHomeAffix = (routes: AppRouteRecordRaw[]) => { if (!routes || routes.length === 0) return; let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME; function patcher(routes: AppRouteRecordRaw[], parentPath = '') { if (parentPath) parentPath = parentPath + '/'; routes.forEach((route: AppRouteRecordRaw) => { const { path, children, redirect } = route; const currentPath = path.startsWith('/') ? path : parentPath + path; if (currentPath === homePath) { if (redirect) { homePath = route.redirect! as string; } else { route.meta = Object.assign({}, route.meta, { affix: true }); throw new Error('end'); } } children && children.length > 0 && patcher(children, currentPath); }); } try { patcher(routes); } catch (e) { // 已处理完毕跳出循环 } return; }; switch (permissionMode) { case PermissionModeEnum.ROLE: routes = filter(asyncRoutes, routeFilter); routes = routes.filter(routeFilter); // Convert multi-level routing to level 2 routing routes = flatMultiLevelRoutes(routes); break; case PermissionModeEnum.ROUTE_MAPPING: routes = filter(asyncRoutes, routeFilter); routes = routes.filter(routeFilter); const menuList = transformRouteToMenu(routes, true); routes = filter(routes, routeRemoveIgnoreFilter); routes = routes.filter(routeRemoveIgnoreFilter); menuList.sort((a, b) => { return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0); }); this.setFrontMenuList(menuList); // Convert multi-level routing to level 2 routing routes = flatMultiLevelRoutes(routes); break; // If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below case PermissionModeEnum.BACK: const { createMessage } = useMessage(); createMessage.loading({ content: t('sys.app.menuLoading'), duration: 1, }); // !Simulate to obtain permission codes from the background, // this function may only need to be executed once, and the actual project can be put at the right time by itself let routeList: AppRouteRecordRaw[] = []; try { routeList = (await getMenuList()) as AppRouteRecordRaw[]; this.changePermissionCode(); } catch (error) { console.error(error); } // Dynamically introduce components routeList = transformObjToRoute(routeList); routeList.sort((a, b) => { return (a.sort || 0) - (b.sort || 0); }); // Background routing to menu structure const backMenuList = transformRouteToMenu(routeList); this.setBackMenuList(backMenuList); // remove meta.ignoreRoute item routeList = filter(routeList, routeRemoveIgnoreFilter); routeList = routeList.filter(routeRemoveIgnoreFilter); routeList = flatMultiLevelRoutes(routeList); routes = [PAGE_NOT_FOUND_ROUTE, ...routeList]; break; } // routes.push(ERROR_LOG_ROUTE); patchHomeAffix(routes); return routes; }, }, }); // Need to be used outside the setup export function usePermissionStoreWithOut() { return usePermissionStore(store); }