|
|
@@ -0,0 +1,162 @@
|
|
|
+import { defineAsyncComponent, Component } from 'vue'
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import { useMenuStore } from '@/stores'
|
|
|
+import { AuthType } from '@/constants/menu'
|
|
|
+
|
|
|
+// 待优化
|
|
|
+export function useMenu(authCode?: string) {
|
|
|
+ const menuStore = useMenuStore()
|
|
|
+ const { userRoutes } = menuStore.$toRefs()
|
|
|
+
|
|
|
+ const route = useRoute()
|
|
|
+ const router = useRouter()
|
|
|
+ const componentMap = new Map<string, Component>()
|
|
|
+
|
|
|
+ // 过滤菜单
|
|
|
+ const filterMenu = (data: Model.UserRoutes[], parentPath = '') => {
|
|
|
+ const result: Model.UserRoutes[] = []
|
|
|
+ data.forEach((e) => {
|
|
|
+ if (!e.hidden && e.authType === AuthType.Menu) {
|
|
|
+ const routePath = (parentPath ? parentPath + '/' : '') + e.url
|
|
|
+ result.push({
|
|
|
+ ...e,
|
|
|
+ url: routePath,
|
|
|
+ children: e.children ? filterMenu(e.children, routePath) : [],
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据 code 查找对应的子菜单
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ const findChildren = (data: Model.UserRoutes[], code?: string): Model.UserRoutes[] => {
|
|
|
+ const routeName = code ?? route.name?.toString()
|
|
|
+ for (const item of data) {
|
|
|
+ const { code, children } = item
|
|
|
+ if (code === routeName) return children ?? []
|
|
|
+ if (children) {
|
|
|
+ const res = findChildren(children, routeName)
|
|
|
+ if (res.length) return res
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return []
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取路由菜单(无限级)
|
|
|
+ * @param level
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ const getMenus = (level = 0) => {
|
|
|
+ // 过滤层级
|
|
|
+ const filterLevel = (data: Model.UserRoutes[], n: number): Model.UserRoutes[] => {
|
|
|
+ if (level) {
|
|
|
+ return data.map((e) => ({ ...e, children: n <= 1 ? [] : filterLevel(e.children ?? [], n - 1) }))
|
|
|
+ }
|
|
|
+ return data
|
|
|
+ }
|
|
|
+ return filterMenu(filterLevel(userRoutes.value, level))
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取路由子菜单
|
|
|
+ * @param code
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ const getChildrenMenus = (code?: string) => {
|
|
|
+ const children = findChildren(userRoutes.value, code)
|
|
|
+ return filterMenu(children)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取首页地址
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ const getHomeUrl = () => {
|
|
|
+ const findNode = (tree: Model.UserRoutes[]): string => {
|
|
|
+ for (const node of tree) {
|
|
|
+ if (node.children?.length) {
|
|
|
+ const res = findNode(node.children)
|
|
|
+ if (res) return res
|
|
|
+ } else {
|
|
|
+ return node.url
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return '/404'
|
|
|
+ }
|
|
|
+ return findNode(getMenus())
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取操作权限
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ const getAuth = (authType: AuthType) => {
|
|
|
+ const children = findChildren(userRoutes.value, authCode)
|
|
|
+ return children.reduce((res, cur) => {
|
|
|
+ if (!cur.hidden && 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(JSON.parse(JSON.stringify(cur)))
|
|
|
+ }
|
|
|
+ return res
|
|
|
+ }, [] as Model.UserRoutes[])
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 过滤操作权限
|
|
|
+ * @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 getAuthButtons = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Button, filtered, reverse)
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取权限组件
|
|
|
+ * @param filtered
|
|
|
+ * @param reverse
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ const getAuthComponents = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Component, filtered, reverse)
|
|
|
+
|
|
|
+ return {
|
|
|
+ route,
|
|
|
+ router,
|
|
|
+ userRoutes,
|
|
|
+ componentMap,
|
|
|
+ getMenus,
|
|
|
+ getHomeUrl,
|
|
|
+ getChildrenMenus,
|
|
|
+ getAuthButtons,
|
|
|
+ getAuthComponents,
|
|
|
+ }
|
|
|
+}
|