Blame view

src/store/modules/permission.ts 7.12 KB
陈文彬 authored
1
2
import type { AppRouteRecordRaw, Menu } from '/@/router/types';
Vben authored
3
4
5
6
import { defineStore } from 'pinia';
import { store } from '/@/store';
import { useI18n } from '/@/hooks/web/useI18n';
import { useUserStore } from './user';
7
import { useAppStoreWithOut } from './app';
8
import { toRaw } from 'vue';
Vben authored
9
10
import { transformObjToRoute, flatMultiLevelRoutes } from '/@/router/helper/routeHelper';
import { transformRouteToMenu } from '/@/router/helper/menuHelper';
陈文彬 authored
11
Vben authored
12
import projectSetting from '/@/settings/projectSetting';
13
陈文彬 authored
14
15
import { PermissionModeEnum } from '/@/enums/appEnum';
vben authored
16
import { asyncRoutes } from '/@/router/routes';
17
18
import { ERROR_LOG_ROUTE, PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
陈文彬 authored
19
import { filter } from '/@/utils/helper/treeHelper';
20
21
22
import { getMenuList } from '/@/api/sys/menu';
import { getPermCode } from '/@/api/sys/user';
陈文彬 authored
23
24

import { useMessage } from '/@/hooks/web/useMessage';
25
import { PageEnum } from '/@/enums/pageEnum';
vben authored
26
Vben authored
27
interface PermissionState {
vben authored
28
  // Permission code list
29
  permCodeList: string[] | number[];
陈文彬 authored
30
  // Whether the route has been dynamically added
Vben authored
31
  isDynamicAddedRoute: boolean;
vben authored
32
  // To trigger a menu update
Vben authored
33
  lastBuildMenuTime: number;
vben authored
34
  // Backstage menu list
Vben authored
35
  backMenuList: Menu[];
36
  frontMenuList: Menu[];
Vben authored
37
38
39
40
41
42
43
44
45
46
47
}
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: [],
48
49
    // menu List
    frontMenuList: [],
Vben authored
50
51
  }),
  getters: {
52
    getPermCodeList(): string[] | number[] {
Vben authored
53
54
      return this.permCodeList;
    },
55
    getBackMenuList(): Menu[] {
Vben authored
56
57
      return this.backMenuList;
    },
58
59
60
    getFrontMenuList(): Menu[] {
      return this.frontMenuList;
    },
61
    getLastBuildMenuTime(): number {
Vben authored
62
63
      return this.lastBuildMenuTime;
    },
64
    getIsDynamicAddedRoute(): boolean {
Vben authored
65
66
67
68
69
70
71
72
73
74
      return this.isDynamicAddedRoute;
    },
  },
  actions: {
    setPermCodeList(codeList: string[]) {
      this.permCodeList = codeList;
    },

    setBackMenuList(list: Menu[]) {
      this.backMenuList = list;
75
      list?.length > 0 && this.setLastBuildMenuTime();
Vben authored
76
77
    },
78
79
80
81
    setFrontMenuList(list: Menu[]) {
      this.frontMenuList = list;
    },
Vben authored
82
83
84
85
86
87
88
89
90
91
92
93
94
    setLastBuildMenuTime() {
      this.lastBuildMenuTime = new Date().getTime();
    },

    setDynamicAddedRoute(added: boolean) {
      this.isDynamicAddedRoute = added;
    },
    resetState(): void {
      this.isDynamicAddedRoute = false;
      this.permCodeList = [];
      this.backMenuList = [];
      this.lastBuildMenuTime = 0;
    },
95
96
    async changePermissionCode() {
      const codeList = await getPermCode();
Vben authored
97
98
      this.setPermCodeList(codeList);
    },
99
    async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
Vben authored
100
101
      const { t } = useI18n();
      const userStore = useUserStore();
102
      const appStore = useAppStoreWithOut();
Vben authored
103
104

      let routes: AppRouteRecordRaw[] = [];
105
      const roleList = toRaw(userStore.getRoleList) || [];
Vben authored
106
      const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
107
108
109
110
111
112
113
114

      const routeFilter = (route: AppRouteRecordRaw) => {
        const { meta } = route;
        const { roles } = meta || {};
        if (!roles) return true;
        return roleList.some((role) => roles.includes(role));
      };
115
116
117
118
119
120
      const routeRmoveIgnoreFilter = (route: AppRouteRecordRaw) => {
        const { meta } = route;
        const { ignoreRoute } = meta || {};
        return !ignoreRoute;
      };
121
122
123
124
125
      /**
       * @description 根据设置的首页path,修正routes中的affix标记(固定首页)
       * */
      const patchHomeAffix = (routes: AppRouteRecordRaw[]) => {
        if (!routes || routes.length === 0) return;
126
        let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME;
127
128
129
        function patcher(routes: AppRouteRecordRaw[], parentPath = '') {
          if (parentPath) parentPath = parentPath + '/';
          routes.forEach((route: AppRouteRecordRaw) => {
130
            const { path, children, redirect } = route;
131
132
            const currentPath = path.startsWith('/') ? path : parentPath + path;
            if (currentPath === homePath) {
133
134
135
136
137
138
              if (redirect) {
                homePath = route.redirect! as string;
              } else {
                route.meta = Object.assign({}, route.meta, { affix: true });
                throw new Error('end');
              }
139
140
141
142
143
144
145
146
147
148
149
150
            }
            children && children.length > 0 && patcher(children, currentPath);
          });
        }
        try {
          patcher(routes);
        } catch (e) {
          // 已处理完毕跳出循环
        }
        return;
      };
151
152
153
154
155
156
157
158
159
160
161
      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);
162
          const menuList = transformRouteToMenu(routes, true);
163
164
          routes = filter(routes, routeRmoveIgnoreFilter);
          routes = routes.filter(routeRmoveIgnoreFilter);
165
166
167
          menuList.sort((a, b) => {
            return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0);
          });
168
169
170
171
172
173
          this.setFrontMenuList(menuList);
          // Convert multi-level routing to level 2 routing
          routes = flatMultiLevelRoutes(routes);
          break;
Vben authored
174
        //  If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        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 {
            this.changePermissionCode();
            routeList = (await getMenuList()) as AppRouteRecordRaw[];
          } catch (error) {
            console.error(error);
          }

          // Dynamically introduce components
          routeList = transformObjToRoute(routeList);

          //  Background routing to menu structure
          const backMenuList = transformRouteToMenu(routeList);
          this.setBackMenuList(backMenuList);
200
201
202
203
          // remove meta.ignoreRoute item
          routeList = filter(routeList, routeRmoveIgnoreFilter);
          routeList = routeList.filter(routeRmoveIgnoreFilter);
204
205
206
          routeList = flatMultiLevelRoutes(routeList);
          routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
          break;
陈文彬 authored
207
      }
208
Vben authored
209
      routes.push(ERROR_LOG_ROUTE);
210
      patchHomeAffix(routes);
Vben authored
211
212
213
214
215
216
      return routes;
    },
  },
});

// Need to be used outside the setup
217
export function usePermissionStoreWithOut() {
Vben authored
218
  return usePermissionStore(store);
陈文彬 authored
219
}