LooSheng
2023-03-24 74ded8aed7bd5f2e4f3008a4566d8e3dd0510566
提交 | 用户 | age
2f6253 1 import type { AppRouteRecordRaw, Menu } from '/@/router/types';
2
215d8b 3 import { defineStore } from 'pinia';
V 4 import { store } from '/@/store';
5 import { useI18n } from '/@/hooks/web/useI18n';
6 import { useUserStore } from './user';
913c22 7 import { useAppStoreWithOut } from './app';
8fb039 8 import { toRaw } from 'vue';
215d8b 9 import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper';
V 10 import { transformRouteToMenu } from '/@/router/helper/menuHelper';
8fb039 11
215d8b 12 import projectSetting from '/@/settings/projectSetting';
2f6253 13
14 import { PermissionModeEnum } from '/@/enums/appEnum';
15
ecfb70 16 import { asyncRoutes } from '/@/router/routes';
8fb039 17 import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
2f6253 18
8fb039 19 import { filter } from '/@/utils/helper/treeHelper';
V 20
9e5e63 21 import { getMenuList } from '/@/api/sys/menu';
N 22 import { getPermCode } from '/@/api/sys/user';
8fb039 23
2f6253 24 import { useMessage } from '/@/hooks/web/useMessage';
0a3683 25 import { PageEnum } from '/@/enums/pageEnum';
66acb2 26
215d8b 27 interface PermissionState {
e23336 28   // Permission code list
19dc88 29   // 权限代码列表
e8d6f8 30   permCodeList: string[] | number[];
2f6253 31   // Whether the route has been dynamically added
19dc88 32   // 路由是否动态添加
215d8b 33   isDynamicAddedRoute: boolean;
e23336 34   // To trigger a menu update
19dc88 35   // 触发菜单更新
215d8b 36   lastBuildMenuTime: number;
e23336 37   // Backstage menu list
19dc88 38   // 后台菜单列表
215d8b 39   backMenuList: Menu[];
19dc88 40   // 菜单列表
913c22 41   frontMenuList: Menu[];
2f6253 42 }
19dc88 43
215d8b 44 export const usePermissionStore = defineStore({
V 45   id: 'app-permission',
46   state: (): PermissionState => ({
19dc88 47     // 权限代码列表
215d8b 48     permCodeList: [],
V 49     // Whether the route has been dynamically added
19dc88 50     // 路由是否动态添加
215d8b 51     isDynamicAddedRoute: false,
V 52     // To trigger a menu update
19dc88 53     // 触发菜单更新
215d8b 54     lastBuildMenuTime: 0,
V 55     // Backstage menu list
19dc88 56     // 后台菜单列表
215d8b 57     backMenuList: [],
913c22 58     // menu List
19dc88 59     // 菜单列表
913c22 60     frontMenuList: [],
215d8b 61   }),
V 62   getters: {
74ded8 63     getPermCodeList(state): string[] | number[] {
L 64       return state.permCodeList;
215d8b 65     },
74ded8 66     getBackMenuList(state): Menu[] {
L 67       return state.backMenuList;
913c22 68     },
74ded8 69     getFrontMenuList(state): Menu[] {
L 70       return state.frontMenuList;
215d8b 71     },
74ded8 72     getLastBuildMenuTime(state): number {
L 73       return state.lastBuildMenuTime;
215d8b 74     },
74ded8 75     getIsDynamicAddedRoute(state): boolean {
L 76       return state.isDynamicAddedRoute;
215d8b 77     },
V 78   },
79   actions: {
80     setPermCodeList(codeList: string[]) {
81       this.permCodeList = codeList;
82     },
83
84     setBackMenuList(list: Menu[]) {
85       this.backMenuList = list;
132c7f 86       list?.length > 0 && this.setLastBuildMenuTime();
913c22 87     },
V 88
89     setFrontMenuList(list: Menu[]) {
90       this.frontMenuList = list;
215d8b 91     },
V 92
93     setLastBuildMenuTime() {
94       this.lastBuildMenuTime = new Date().getTime();
95     },
96
97     setDynamicAddedRoute(added: boolean) {
98       this.isDynamicAddedRoute = added;
99     },
100     resetState(): void {
101       this.isDynamicAddedRoute = false;
102       this.permCodeList = [];
103       this.backMenuList = [];
104       this.lastBuildMenuTime = 0;
105     },
9e5e63 106     async changePermissionCode() {
N 107       const codeList = await getPermCode();
215d8b 108       this.setPermCodeList(codeList);
V 109     },
19dc88 110
J 111     // 构建路由
9e5e63 112     async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
215d8b 113       const { t } = useI18n();
V 114       const userStore = useUserStore();
913c22 115       const appStore = useAppStoreWithOut();
215d8b 116
V 117       let routes: AppRouteRecordRaw[] = [];
aebad6 118       const roleList = toRaw(userStore.getRoleList) || [];
215d8b 119       const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
913c22 120
19dc88 121       // 路由过滤器 在 函数filter 作为回调传入遍历使用
913c22 122       const routeFilter = (route: AppRouteRecordRaw) => {
V 123         const { meta } = route;
19dc88 124         // 抽出角色
913c22 125         const { roles } = meta || {};
V 126         if (!roles) return true;
19dc88 127         // 进行角色权限判断
913c22 128         return roleList.some((role) => roles.includes(role));
V 129       };
130
91cbe0 131       const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => {
72ac24 132         const { meta } = route;
19dc88 133         // ignoreRoute 为true 则路由仅用于菜单生成,不会在实际的路由表中出现
72ac24 134         const { ignoreRoute } = meta || {};
19dc88 135         // arr.filter 返回 true 表示该元素通过测试
72ac24 136         return !ignoreRoute;
137       };
138
0a3683 139       /**
140        * @description 根据设置的首页path,修正routes中的affix标记(固定首页)
141        * */
142       const patchHomeAffix = (routes: AppRouteRecordRaw[]) => {
143         if (!routes || routes.length === 0) return;
c11780 144         let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME;
19dc88 145
0a3683 146         function patcher(routes: AppRouteRecordRaw[], parentPath = '') {
147           if (parentPath) parentPath = parentPath + '/';
148           routes.forEach((route: AppRouteRecordRaw) => {
c11780 149             const { path, children, redirect } = route;
0a3683 150             const currentPath = path.startsWith('/') ? path : parentPath + path;
151             if (currentPath === homePath) {
c11780 152               if (redirect) {
153                 homePath = route.redirect! as string;
154               } else {
155                 route.meta = Object.assign({}, route.meta, { affix: true });
156                 throw new Error('end');
157               }
0a3683 158             }
159             children && children.length > 0 && patcher(children, currentPath);
160           });
161         }
19dc88 162
0a3683 163         try {
164           patcher(routes);
165         } catch (e) {
166           // 已处理完毕跳出循环
167         }
168         return;
169       };
170
913c22 171       switch (permissionMode) {
19dc88 172         // 角色权限
913c22 173         case PermissionModeEnum.ROLE:
19dc88 174           // 对非一级路由进行过滤
913c22 175           routes = filter(asyncRoutes, routeFilter);
19dc88 176           // 对一级路由根据角色权限过滤
913c22 177           routes = routes.filter(routeFilter);
V 178           // Convert multi-level routing to level 2 routing
19dc88 179           // 将多级路由转换为 2 级路由
913c22 180           routes = flatMultiLevelRoutes(routes);
V 181           break;
182
19dc88 183         // 路由映射, 默认进入该case
913c22 184         case PermissionModeEnum.ROUTE_MAPPING:
19dc88 185           // 对非一级路由进行过滤
913c22 186           routes = filter(asyncRoutes, routeFilter);
19dc88 187           // 对一级路由再次根据角色权限过滤
913c22 188           routes = routes.filter(routeFilter);
19dc88 189           // 将路由转换成菜单
387120 190           const menuList = transformRouteToMenu(routes, true);
19dc88 191           // 移除掉 ignoreRoute: true 的路由 非一级路由
91cbe0 192           routes = filter(routes, routeRemoveIgnoreFilter);
19dc88 193           // 移除掉 ignoreRoute: true 的路由 一级路由;
91cbe0 194           routes = routes.filter(routeRemoveIgnoreFilter);
19dc88 195           // 对菜单进行排序
913c22 196           menuList.sort((a, b) => {
V 197             return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0);
198           });
cdb10c 199
19dc88 200           // 设置菜单列表
913c22 201           this.setFrontMenuList(menuList);
19dc88 202
913c22 203           // Convert multi-level routing to level 2 routing
19dc88 204           // 将多级路由转换为 2 级路由
913c22 205           routes = flatMultiLevelRoutes(routes);
V 206           break;
207
215d8b 208         //  If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
a89ba2 209         //  如果确定不需要做后台动态权限,请在下方注释整个判断
913c22 210         case PermissionModeEnum.BACK:
V 211           const { createMessage } = useMessage();
215d8b 212
913c22 213           createMessage.loading({
V 214             content: t('sys.app.menuLoading'),
215             duration: 1,
216           });
215d8b 217
913c22 218           // !Simulate to obtain permission codes from the background,
19dc88 219           // 模拟从后台获取权限码,
913c22 220           // this function may only need to be executed once, and the actual project can be put at the right time by itself
19dc88 221           // 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间
913c22 222           let routeList: AppRouteRecordRaw[] = [];
V 223           try {
19dc88 224             await this.changePermissionCode();
913c22 225             routeList = (await getMenuList()) as AppRouteRecordRaw[];
V 226           } catch (error) {
227             console.error(error);
228           }
215d8b 229
913c22 230           // Dynamically introduce components
19dc88 231           // 动态引入组件
913c22 232           routeList = transformObjToRoute(routeList);
215d8b 233
913c22 234           //  Background routing to menu structure
19dc88 235           //  后台路由到菜单结构
913c22 236           const backMenuList = transformRouteToMenu(routeList);
V 237           this.setBackMenuList(backMenuList);
215d8b 238
72ac24 239           // remove meta.ignoreRoute item
19dc88 240           // 删除 meta.ignoreRoute 项
91cbe0 241           routeList = filter(routeList, routeRemoveIgnoreFilter);
H 242           routeList = routeList.filter(routeRemoveIgnoreFilter);
72ac24 243
913c22 244           routeList = flatMultiLevelRoutes(routeList);
V 245           routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
246           break;
215d8b 247       }
913c22 248
215d8b 249       routes.push(ERROR_LOG_ROUTE);
0a3683 250       patchHomeAffix(routes);
215d8b 251       return routes;
V 252     },
253   },
254 });
255
256 // Need to be used outside the setup
19dc88 257 // 需要在设置之外使用
913c22 258 export function usePermissionStoreWithOut() {
215d8b 259   return usePermissionStore(store);
V 260 }