menu.ts
6.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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
200
import { cloneDeep } from 'lodash-es'
import useSettingsStore from './settings'
import useUserStore from './user'
import useRouteStore from './route'
import { resolveRoutePath } from '@/utils'
import apiApp from '@/api/modules/app'
import menu from '@/menu'
import type { Menu } from '#/global'
const useMenuStore = defineStore(
// 唯一ID
'menu',
() => {
const settingsStore = useSettingsStore()
const userStore = useUserStore()
const routeStore = useRouteStore()
const menus = ref<Menu.recordMainRaw[]>([{
meta: {},
children: [],
}])
const actived = ref(0)
// 完整导航数据
const allMenus = computed(() => {
let returnMenus: Menu.recordMainRaw[] = [{
meta: {},
children: [],
}]
if (settingsStore.settings.app.routeBaseOn !== 'filesystem') {
if (settingsStore.settings.menu.menuMode === 'single') {
returnMenus[0].children = []
routeStore.routes.forEach((item) => {
returnMenus[0].children?.push(...item.children as Menu.recordRaw[])
})
}
else {
returnMenus = routeStore.routes as Menu.recordMainRaw[]
}
}
else {
returnMenus = menus.value
}
return returnMenus
})
// 次导航数据
const sidebarMenus = computed<Menu.recordMainRaw['children']>(() => {
return allMenus.value.length > 0
? allMenus.value[actived.value].children
: []
})
// 次导航第一层最深路径
const sidebarMenusFirstDeepestPath = computed(() => {
return allMenus.value.length > 0
? getDeepestPath(sidebarMenus.value[0])
: '/'
})
function getDeepestPath(menu: Menu.recordRaw, rootPath = '') {
let retnPath = ''
if (menu.children) {
const item = menu.children.find(item => item.meta?.sidebar !== false)
if (item) {
retnPath = getDeepestPath(item, resolveRoutePath(rootPath, menu.path))
}
else {
retnPath = getDeepestPath(menu.children[0], resolveRoutePath(rootPath, menu.path))
}
}
else {
retnPath = resolveRoutePath(rootPath, menu.path)
}
return retnPath
}
// 默认展开的导航路径
const defaultOpenedPaths = computed(() => {
let defaultOpenedPaths: string[] = []
if (settingsStore.settings.app.routeBaseOn !== 'filesystem') {
defaultOpenedPaths = getDefaultOpenedPaths(sidebarMenus.value)
}
return defaultOpenedPaths
})
function getDefaultOpenedPaths(menus: Menu.recordRaw[], rootPath = '') {
const defaultOpenedPaths: string[] = []
menus.forEach((item) => {
if (item.meta?.defaultOpened && item.children) {
defaultOpenedPaths.push(resolveRoutePath(rootPath, item.path))
const childrenDefaultOpenedPaths = getDefaultOpenedPaths(item.children, resolveRoutePath(rootPath, item.path))
if (childrenDefaultOpenedPaths.length > 0) {
defaultOpenedPaths.push(...childrenDefaultOpenedPaths)
}
}
})
return defaultOpenedPaths
}
// 判断是否有权限
function hasPermission(permissions: string[], menu: Menu.recordMainRaw | Menu.recordRaw) {
let isAuth = false
if (menu.meta && menu.meta.auth) {
isAuth = permissions.some((auth) => {
if (typeof menu.meta?.auth === 'string') {
return menu.meta.auth !== '' ? menu.meta.auth === auth : true
}
else if (typeof menu.meta?.auth === 'object') {
return menu.meta.auth.length > 0 ? menu.meta.auth.includes(auth) : true
}
else {
return false
}
})
}
else {
isAuth = true
}
return isAuth
}
// 根据权限过滤导航
function filterAsyncMenus<T extends Menu.recordMainRaw[] | Menu.recordRaw[]>(menus: T, permissions: string[]): T {
const res: any = []
menus.forEach((menu) => {
const tmpMenu = cloneDeep(menu)
if (hasPermission(permissions, tmpMenu)) {
if (tmpMenu.children) {
tmpMenu.children = filterAsyncMenus(tmpMenu.children, permissions) as Menu.recordRaw[]
tmpMenu.children.length && res.push(tmpMenu)
}
else {
res.push(tmpMenu)
}
}
})
return res
}
// 生成导航(前端生成)
async function generateMenusAtFront() {
let accessedMenus
// 如果权限功能开启,则需要对导航数据进行筛选过滤
if (settingsStore.settings.app.enablePermission) {
const permissions = await userStore.getPermissions()
accessedMenus = filterAsyncMenus(menu, permissions)
}
else {
accessedMenus = cloneDeep(menu)
}
menus.value = accessedMenus.filter(item => item.children.length !== 0)
}
// 生成导航(后端生成)
async function generateMenusAtBack() {
await apiApp.menuList().then(async (res) => {
let accessedMenus: Menu.recordMainRaw[]
// 如果权限功能开启,则需要对导航数据进行筛选过滤
if (settingsStore.settings.app.enablePermission) {
const permissions = await userStore.getPermissions()
accessedMenus = filterAsyncMenus(res.data, permissions)
}
else {
accessedMenus = cloneDeep(res.data)
}
menus.value = accessedMenus.filter(item => item.children.length !== 0)
}).catch(() => {})
}
// 切换主导航
async function setActived(data: number | string) {
if (typeof data === 'number') {
// 如果是 number 类型,则认为是主导航的索引
actived.value = data
// 切换主导航时清空顶部tabs标签页
await userStore.setTabbar('menu')
}
else {
// 如果是 string 类型,则认为是路由,需要查找对应的主导航索引
const findIndex = allMenus.value.findIndex(item => item.children.some(r => {
if (data.indexOf(`${r.path}/`) === 0 || data === r.path) {
return true;
}
if (r.children?.length) {
return r.children.some(c => data === `${r.path}/${c.path}`);
}
}))
if (findIndex >= 0) {
actived.value = findIndex
}
}
}
return {
menus,
actived,
allMenus,
sidebarMenus,
sidebarMenusFirstDeepestPath,
defaultOpenedPaths,
generateMenusAtFront,
generateMenusAtBack,
setActived,
}
},
)
export default useMenuStore