import { defineAsyncComponent, Component } from 'vue' import { useRoute, useRouter } from 'vue-router' import { sessionData } from '@/stores' import { AuthType } from '@/constants/enum/menu' import { AuthMenu } from './interface' export function useAuth(code?: string) { const route = useRoute() const router = useRouter() const userMenus = sessionData.getValue('userMenus') const componentMap = new Map() /** * 获取路由菜单(无限级) * @param level * @returns */ const getMenus = (level = 0) => { // 过滤层级 const filterLevel = (list: Ermcp.UserMenu[], n: number): Ermcp.UserMenu[] => { if (level) { return list.map((e) => ({ ...e, children: n <= 1 ? [] : filterLevel(e.children ?? [], n - 1) })) } return list } // 过滤菜单 const filterMenu = (list: Ermcp.UserMenu[], parentPath = '') => { const result: AuthMenu[] = [] list.forEach((e) => { if (e.authType === AuthType.Menu) { const routePath = (parentPath ? parentPath + '/' : '') + e.url result.push({ path: routePath, name: e.code, label: e.title, icon: e.icon, children: e.children ? filterMenu(e.children, routePath) : [], }) } }) return result } return filterMenu(filterLevel(userMenus, level)) } /** * 获取路由子菜单 * @param routeName * @returns */ const getChildrenMenus = (routeName?: string) => { const filter = (list: AuthMenu[]): AuthMenu[] => { if (routeName) { for (const item of list) { const { name, children } = item if (name === routeName) return children ?? [] if (children) { const res = filter(children) if (res.length) return res } } } return [] } return filter(getMenus()) } /** * 获取权限子菜单 * @returns */ const getChildrenAuth = () => { const routeName = code ?? route.name?.toString() const filter = (list: Ermcp.UserMenu[]): Ermcp.UserMenu | undefined => { if (routeName) { for (const item of list) { const { code, children } = item; if (code === routeName) return item; if (children) { const res = filter(children); if (res) return res; } } } return undefined; } return filter(userMenus); } /** * 获取操作权限 * @returns */ const getAuth = (authType: AuthType) => { const auth = getChildrenAuth(); if (auth && auth.children) { return auth.children.reduce((res, cur) => { if (cur.authType === authType) { if (!componentMap.get(cur.code) && cur.component) { const componentString = cur.component.replace(/^\/+/, ''); // 过滤字符串前面所有 '/' 字符 const componentPath = componentString.replace(/\.\w+$/, ''); // 过滤后缀名,为了让 import 加入 .vue ,不然会有警告提示... const asyncComponent = defineAsyncComponent({ loader: () => import('/' + process.env.VUE_APP_ROOT + componentPath + '.vue'), }); componentMap.set(cur.code, asyncComponent); } res.push(cur); } return res; }, [] as Ermcp.UserMenu[]) } return []; } /** * 过滤操作权限 * @param filtered 过滤的数据项 * @param reverse 是否反向过滤 * @returns */ const authFilter = (authType: AuthType, filtered: string[], reverse: boolean) => { const auth = getAuth(authType); if (filtered.length) { if (reverse) { // 返回除指定的权限代码 return auth.filter((e) => !filtered.includes(e.code)); } else { // 返回指定的权限代码 return auth.filter((e) => filtered.includes(e.code)); } } return auth; } /** * 获取权限按钮 * @param filtered * @param reverse * @returns */ const getAuthButton = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Button, filtered, reverse); /** * 获取权限组件 * @param filtered * @param reverse * @returns */ const getAuthComponent = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Component, filtered, reverse); return { route, router, userMenus, componentMap, getMenus, getChildrenMenus, getAuthButton, getAuthComponent, } }