permission.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import { PermissionState } from '@/types'
  2. import { AppRouteRecordRaw } from '@/router/types'
  3. // import { RouteRecordRaw } from 'vue-router'
  4. import { defineStore } from 'pinia'
  5. // import { sysStaticRouter, noFoundRouters, constantMenuList } from '@/router'
  6. import { getMenuList } from '@/api/system/menu'
  7. const modules = import.meta.glob('@/views/**/*.vue')
  8. export const Layout = () => import('@/layout/index.vue') // todo...
  9. // export const Layout = () => import('@/layout/index_old.vue.vue')
  10. export const RouteView = () => import('@/layout/RouteView.vue')
  11. // const hasPermission = (roles: string[], route: AppRouteRecordRaw) => {
  12. // if (route.meta && route.meta.roles) {
  13. // if (roles.includes('ROOT')) {
  14. // return true
  15. // }
  16. // return roles.some(role => {
  17. // if (route.meta?.roles !== undefined) {
  18. // return (route.meta.roles as string[]).includes(role)
  19. // }
  20. // })
  21. // }
  22. // return false
  23. // }
  24. export const filterAsyncRoutes = (routes: AppRouteRecordRaw[], roles: string[], parentPath = '') => {
  25. const res: AppRouteRecordRaw[] = []
  26. routes.forEach(route => {
  27. const tmp = { ...route } as AppRouteRecordRaw
  28. tmp.meta = tmp.meta ? tmp.meta : {}
  29. // 默认icon
  30. tmp.meta.icon = tmp.meta.icon || 'menu'
  31. // 从接口上对 parentRoute 进行置换 为 parentName
  32. if (tmp.meta?.parentRoute) {
  33. tmp.meta.parentName = tmp.meta.parentRoute
  34. }
  35. // path全链 重组
  36. // tmp.path = /\/.*/.test(tmp.path) ? tmp.path : `${parentPath}/${tmp.path}`
  37. tmp.path = /\/.+/.test(tmp.path) ? tmp.path : `${parentPath}/${tmp.path}`
  38. // if (hasPermission(roles, tmp)) {
  39. // todo be delete
  40. // }
  41. // console.warn(tmp.component, 'tmp.component')
  42. // 特殊Layout 配置 标识
  43. /*if (!tmp.component) {
  44. tmp.component = RouteView
  45. } else*/
  46. if (!tmp.component || tmp.component === 'Layout') {
  47. tmp.component = Layout
  48. } else if (typeof tmp.component === 'string') {
  49. if (tmp.component === 'RouteView') {
  50. tmp.component = RouteView
  51. } else {
  52. const component = modules[`/src/views/${tmp.component}.vue`] as any
  53. // console.error(component, 'component')
  54. if (component) {
  55. tmp.component = component
  56. } else {
  57. tmp.component = modules[`/src/views/error-page/404.vue`]
  58. }
  59. }
  60. }
  61. // 处理判断iframe 外链和路由
  62. if (['iframe', 'link'].includes(tmp.meta.type)) {
  63. tmp.props = { url: tmp.redirect }
  64. Reflect.deleteProperty(tmp, 'redirect')
  65. }
  66. res.push(tmp)
  67. // 递归
  68. if (tmp.children) {
  69. tmp.children = filterAsyncRoutes(tmp.children, roles, tmp.path)
  70. }
  71. })
  72. return res
  73. }
  74. /**
  75. * getFlatMenuList_1children 单child 菜单扁平优化
  76. * 针对:children 只有一个child 的 进行菜单优化
  77. */
  78. const getFlatMenuList_1children = (menuList: AppRouteRecordRaw[]) => {
  79. return menuList.reduce((res, v) => {
  80. // 过滤掉隐藏
  81. if (v.meta?.hidden) return res
  82. const children = v.children
  83. if (Array.isArray(children) && children.length) {
  84. if (children.length === 1) {
  85. const child0 = children[0]
  86. // delete v.children
  87. res.push({
  88. ...child0,
  89. path: /\/.*/.test(child0.path) ? child0.path : v.name !== 'mainLayout' ? `${v.path}/${child0.path}` : `/${child0.path}`
  90. })
  91. } else {
  92. res.push({
  93. ...v,
  94. children: getFlatMenuList_1children(v.children as AppRouteRecordRaw[])
  95. })
  96. }
  97. } else {
  98. res.push(v)
  99. }
  100. return res
  101. }, [] as AppRouteRecordRaw[])
  102. }
  103. // 过滤隐藏
  104. // const getShowMenuList = (menuList: AppRouteRecordRaw[], parentPath = '') => {
  105. const getShowMenuList = (menuList: AppRouteRecordRaw[]) => {
  106. return menuList.filter(item => {
  107. // console.error(item, 'item')
  108. if (!item.meta.hidden) {
  109. // item.children?.length && (item.children = getShowMenuList(item.children, item.path))
  110. item.children?.length && (item.children = getShowMenuList(item.children))
  111. return true
  112. }
  113. return false
  114. })
  115. }
  116. // 可展示的路由平铺
  117. const getMenuListFlat = (menuList: AppRouteRecordRaw[]) => {
  118. const _menuList = JSON.parse(JSON.stringify(menuList))
  119. return _menuList.flatMap((v: AppRouteRecordRaw) => {
  120. const _children = v.children || []
  121. return [v, ...getMenuListFlat(_children)]
  122. })
  123. }
  124. const usePermissionStore = defineStore({
  125. id: 'permission',
  126. state: (): PermissionState => ({
  127. // routes: [],
  128. // 动态菜单
  129. menuList: []
  130. }),
  131. getters: {
  132. // 有效的 菜单列表
  133. // showMenuList: state => getShowMenuList(JSON.parse(JSON.stringify([...constantMenuList, ...state.menuList]))),
  134. showMenuList: state => getShowMenuList(JSON.parse(JSON.stringify(state.menuList))),
  135. /*getShowMenuList([
  136. ...JSON.parse(JSON.stringify(state.menuList)),
  137. // 测试
  138. {
  139. path: 'dashboard',
  140. // path: HOME_URL,
  141. component: () => import('@/views/dashboard/index-old.vue'),
  142. name: 'dashboard',
  143. meta: { title: 'dashboard', icon: 'icon-homepage', affix: true }
  144. }
  145. ])*/
  146. // showMenuList: state => getShowMenuList(JSON.parse(JSON.stringify(state.routes)))
  147. // 菜单权限列表 ==> 扁平化之后的一维数组菜单,主要用来添加动态路由
  148. showMenuListFlat() {
  149. // console.error(state, 'test...', this)
  150. return getMenuListFlat(this.showMenuList)
  151. }
  152. },
  153. actions: {
  154. setRoutes(menuList: AppRouteRecordRaw[]) {
  155. // 授权后的菜单列表 对单个的 children 菜单减级优化
  156. this.menuList = getFlatMenuList_1children(menuList)
  157. // menuList
  158. /*this.routes = menuList
  159. sysStaticRouter.concat(
  160. menuList,
  161. noFoundRouters /!*, {
  162. // 管理员管理
  163. path: '/adminManage1',
  164. name: 'adminManage1',
  165. // component: 'demo/adminManage/index',
  166. // component: 'demo/adminManage/index',
  167. component: modules[`/src/views/${'demo/adminManage/index'}.vue`],
  168. // const = modules[`/src/views/${tmp.component}.vue`] as any
  169. // if (component) {
  170. // tmp.component = component
  171. meta: { title: 'demo_adminManage' }
  172. }*!/
  173. )*/
  174. },
  175. queryMenuList(roles: string[]) {
  176. return getMenuList().then((data: any) => {
  177. const menuList = filterAsyncRoutes(
  178. data!.menu, // .filter((v: any) => /\/.*/.test(v.path)),
  179. roles
  180. )
  181. this.setRoutes(menuList)
  182. return menuList
  183. })
  184. }
  185. }
  186. })
  187. export default usePermissionStore