index.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import { shallowRef, defineAsyncComponent, Component } from 'vue'
  2. import { useRoute, useRouter } from 'vue-router'
  3. import { useMenuStore } from '@/stores'
  4. import { AuthType } from '@/constants/menu'
  5. export function useMenu(authCode?: string) {
  6. const { userMenus } = useMenuStore()
  7. const route = useRoute()
  8. const router = useRouter()
  9. const componentMap = new Map<string, Component>()
  10. const componentId = shallowRef<string>() // 当前选中的组件
  11. // 过滤菜单
  12. const filterMenu = (data: Ermcp.UserMenu[], parentPath = '') => {
  13. const result: Ermcp.UserMenu[] = []
  14. data.forEach((e) => {
  15. if (!e.hidden && e.authType === AuthType.Menu) {
  16. const routePath = (parentPath ? parentPath + '/' : '') + e.url
  17. result.push({
  18. ...e,
  19. url: routePath,
  20. children: e.children ? filterMenu(e.children, routePath) : [],
  21. })
  22. }
  23. })
  24. return result
  25. }
  26. /**
  27. * 根据 code 查找对应的子菜单
  28. * @returns
  29. */
  30. const findChildren = (data: Ermcp.UserMenu[], code?: string): Ermcp.UserMenu[] => {
  31. const routeName = code ?? route.name?.toString()
  32. for (const item of data) {
  33. const { code, children } = item
  34. if (code === routeName) return children ?? []
  35. if (children) {
  36. const res = findChildren(children, routeName)
  37. if (res.length) return res
  38. }
  39. }
  40. return []
  41. }
  42. /**
  43. * 获取路由菜单(无限级)
  44. * @param level
  45. * @returns
  46. */
  47. const getMenus = (level = 0) => {
  48. // 过滤层级
  49. const filterLevel = (data: Ermcp.UserMenu[], n: number): Ermcp.UserMenu[] => {
  50. if (level) {
  51. return data.map((e) => ({ ...e, children: n <= 1 ? [] : filterLevel(e.children ?? [], n - 1) }))
  52. }
  53. return data
  54. }
  55. return filterMenu(filterLevel(userMenus.value, level))
  56. }
  57. /**
  58. * 获取路由子菜单
  59. * @param code
  60. * @returns
  61. */
  62. const getChildrenMenus = (code?: string) => {
  63. const children = findChildren(userMenus.value, code)
  64. return filterMenu(children)
  65. }
  66. /**
  67. * 获取操作权限
  68. * @returns
  69. */
  70. const getAuth = (authType: AuthType) => {
  71. const children = findChildren(userMenus.value, authCode)
  72. return children.reduce((res, cur) => {
  73. if (!cur.hidden && cur.authType === authType) {
  74. if (!componentMap.get(cur.code) && cur.component) {
  75. const componentString = cur.component.replace(/^\/+/, '') // 过滤字符串前面所有 '/' 字符
  76. const componentPath = componentString.replace(/\.\w+$/, '') // 过滤后缀名,为了让 import 加入 .vue ,不然会有警告提示...
  77. const asyncComponent = defineAsyncComponent({
  78. loader: () => import('/' + process.env.VUE_APP_ROOT + componentPath + '.vue'),
  79. })
  80. componentMap.set(cur.code, asyncComponent)
  81. }
  82. res.push(JSON.parse(JSON.stringify(cur)))
  83. }
  84. return res
  85. }, [] as Ermcp.UserMenu[])
  86. }
  87. /**
  88. * 过滤操作权限
  89. * @param filtered 过滤的数据项
  90. * @param reverse 是否反向过滤
  91. * @returns
  92. */
  93. const authFilter = (authType: AuthType, filtered: string[], reverse: boolean) => {
  94. const auth = getAuth(authType);
  95. if (filtered.length) {
  96. if (reverse) {
  97. // 返回除指定的权限代码
  98. return auth.filter((e) => !filtered.includes(e.code))
  99. } else {
  100. // 返回指定的权限代码
  101. return auth.filter((e) => filtered.includes(e.code))
  102. }
  103. }
  104. return auth
  105. }
  106. /**
  107. * 获取权限按钮
  108. * @param filtered
  109. * @param reverse
  110. * @returns
  111. */
  112. const getAuthButtons = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Button, filtered, reverse)
  113. /**
  114. * 获取权限组件
  115. * @param filtered
  116. * @param reverse
  117. * @returns
  118. */
  119. const getAuthComponents = (filtered: string[] = [], reverse = false) => authFilter(AuthType.Component, filtered, reverse)
  120. return {
  121. route,
  122. router,
  123. userMenus,
  124. componentMap,
  125. componentId,
  126. getMenus,
  127. getChildrenMenus,
  128. getAuthButtons,
  129. getAuthComponents,
  130. }
  131. }