提交 | 用户 | 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 |
} |