UNPKG

create-iking-admin

Version:

金合技术中台脚手架

205 lines (196 loc) 6.97 kB
import { cloneDeep } from 'lodash-es' import { resolveRoutePath } from '@main/utils' import apiApp from '@main/api/modules/app' import useSettingsStore from './settings' import useUserStore from './user' import useRouteStore from './route' import type { Menu } from '#/global' const useMenuStore = defineStore( // 唯一ID 'menu', () => { const settingsStore = useSettingsStore() const routeStore = useRouteStore() const menus = ref<Menu.recordMainRaw[]>([{ meta: {}, children: [], }]) const actived = ref(0) const activedMenu = ref('') // 将多级导航的每一级 path 都转换为完整路径 function convertToFullPath(menu: any[], path: string = '') { return menu?.map((item) => { item.path = resolveRoutePath(path, item.path) if (item.children) { item.children = convertToFullPath(item.children, item.path) } return item }) } // 完整导航数据 const allMenus = computed(() => { let returnMenus: Menu.recordMainRaw[] = [{ meta: {}, children: [], }] if (settingsStore.settings.app.routeBaseOn !== 'filesystem') { if (settingsStore.settings.menu.menuMode === EMenuModel.侧边栏) { returnMenus = routeStore.routes } else { returnMenus = routeStore.routes as Menu.recordMainRaw[] } returnMenus.map(item => convertToFullPath(item.children)) } else { returnMenus = menus.value } return returnMenus }) // 次导航数据 const sidebarMenus = computed<Menu.recordMainRaw['children']>(() => { return settingsStore.settings.menu.menuMode === EMenuModel.侧边栏 ? allMenus.value : (allMenus.value.length > 0 ? allMenus.value.length > 1 ? allMenus.value[actived.value].children : allMenus.value[0].children : []) }) // 次导航第一层最深路径 const sidebarMenusFirstDeepestPath = computed(() => { return sidebarMenus.value.length > 0 ? getDeepestPath(sidebarMenus.value[0]) : settingsStore.settings.home.fullPath }) 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(() => { const defaultOpenedPaths: string[] = [] if (settingsStore.settings.app.routeBaseOn !== 'filesystem') { allMenus.value.forEach((item) => { defaultOpenedPaths.push(...getDefaultOpenedPaths(item.children || [item])) }) } 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?.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) => { if (hasPermission(permissions, menu)) { const tmpMenu = cloneDeep(menu) 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 generateMenusAtBack() { await apiApp.menuList().then(async (res) => { const settingsStore = useSettingsStore() let accessedMenus: Menu.recordMainRaw[] // 如果权限功能开启,则需要对导航数据进行筛选过滤 if (settingsStore.settings.app.enablePermission) { accessedMenus = filterAsyncMenus(res.data, []) } else { accessedMenus = cloneDeep(res.data) } menus.value = accessedMenus.filter(item => item.children.length !== 0) }).catch(() => {}) } // 设置主导航 function setActived(data: number | string) { if (typeof data === 'number' && data >= 0) { // 如果是 number 类型,则认为是主导航的索引 actived.value = data } else { const levelFitst = allMenus.value.findIndex((mu: any) => mu.path === data) if (levelFitst >= 0) { actived.value = levelFitst } else { // 如果是 string 类型,则认为是路由,需要查找对应的主导航索引 // (item => item.children?.some(r => data.indexOf(`${r.path}/`) === 0 || data === r.path)) const findIndex = allMenus.value.findIndex(item => data.indexOf(`${item.path}`) === 0) if (findIndex >= 0) { actived.value = findIndex } } } } function setActiveMenu(path: string) { activedMenu.value = path } return { menus, actived, activedMenu, allMenus, sidebarMenus, sidebarMenusFirstDeepestPath, defaultOpenedPaths, generateMenusAtBack, setActived, setActiveMenu, } }, ) export default useMenuStore