mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-07 12:48:30 +08:00
195 lines
6.2 KiB
TypeScript
195 lines
6.2 KiB
TypeScript
import { cloneDeep } from 'lodash-es'
|
|
import useSettingsStore from './settings'
|
|
import useUserStore from './user'
|
|
import useRouteStore from './route'
|
|
import type { Menu } from '#/global'
|
|
|
|
import { resolveRoutePath } from '@/utils'
|
|
import api from '@/api'
|
|
import menu from '@/menu'
|
|
|
|
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 api.get('menu/list', {
|
|
baseURL: '/mock/',
|
|
}).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(() => {})
|
|
}
|
|
// 切换主导航
|
|
function setActived(data: number | string) {
|
|
if (typeof data === 'number') {
|
|
// 如果是 number 类型,则认为是主导航的索引
|
|
actived.value = data
|
|
}
|
|
else {
|
|
// 如果是 string 类型,则认为是路由,需要查找对应的主导航索引
|
|
const findIndex = allMenus.value.findIndex(item => item.children.some(r => data.indexOf(`${r.path}/`) === 0 || data === r.path))
|
|
if (findIndex >= 0) {
|
|
actived.value = findIndex
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
menus,
|
|
actived,
|
|
allMenus,
|
|
sidebarMenus,
|
|
sidebarMenusFirstDeepestPath,
|
|
defaultOpenedPaths,
|
|
generateMenusAtFront,
|
|
generateMenusAtBack,
|
|
setActived,
|
|
}
|
|
},
|
|
)
|
|
|
|
export default useMenuStore
|