permission.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { defineStore } from 'pinia';
  2. import router, { constantRoutes, dynamicRoutes } from '@/router';
  3. import store from '@/store';
  4. import { getRouters } from '@/api/menu';
  5. import Layout from '@/layout/index.vue';
  6. import ParentView from '@/components/ParentView/index.vue';
  7. import InnerLink from '@/layout/components/InnerLink/index.vue';
  8. import auth from '@/plugins/auth';
  9. import { RouteOption } from 'vue-router';
  10. // 匹配views里面所有的.vue文件
  11. const modules = import.meta.glob('./../../views/**/*.vue');
  12. export const usePermissionStore = defineStore('permission', () => {
  13. const routes = ref<RouteOption[]>([]);
  14. const addRoutes = ref<RouteOption[]>([]);
  15. const defaultRoutes = ref<RouteOption[]>([]);
  16. const topbarRouters = ref<RouteOption[]>([]);
  17. const sidebarRouters = ref<RouteOption[]>([]);
  18. const setRoutes = (newRoutes: RouteOption[]): void => {
  19. addRoutes.value = newRoutes;
  20. routes.value = constantRoutes.concat(newRoutes);
  21. };
  22. const setDefaultRoutes = (routes: RouteOption[]): void => {
  23. defaultRoutes.value = constantRoutes.concat(routes);
  24. };
  25. const setTopbarRoutes = (routes: RouteOption[]): void => {
  26. topbarRouters.value = routes;
  27. };
  28. const setSidebarRouters = (routes: RouteOption[]): void => {
  29. sidebarRouters.value = routes;
  30. };
  31. const generateRoutes = async (): Promise<RouteOption[]> => {
  32. const res = await getRouters();
  33. const { data } = res;
  34. const sdata = JSON.parse(JSON.stringify(data));
  35. const rdata = JSON.parse(JSON.stringify(data));
  36. const defaultData = JSON.parse(JSON.stringify(data));
  37. const sidebarRoutes = filterAsyncRouter(sdata);
  38. const rewriteRoutes = filterAsyncRouter(rdata, undefined, true);
  39. const defaultRoutes = filterAsyncRouter(defaultData);
  40. const asyncRoutes = filterDynamicRoutes(dynamicRoutes);
  41. asyncRoutes.forEach((route) => {
  42. router.addRoute(route);
  43. });
  44. setRoutes(rewriteRoutes);
  45. setSidebarRouters(constantRoutes.concat(sidebarRoutes));
  46. setDefaultRoutes(sidebarRoutes);
  47. setTopbarRoutes(defaultRoutes);
  48. return new Promise<RouteOption[]>((resolve) => resolve(rewriteRoutes));
  49. };
  50. /**
  51. * 遍历后台传来的路由字符串,转换为组件对象
  52. * @param asyncRouterMap 后台传来的路由字符串
  53. * @param lastRouter 上一级路由
  54. * @param type 是否是重写路由
  55. */
  56. const filterAsyncRouter = (asyncRouterMap: RouteOption[], lastRouter?: RouteOption, type = false): RouteOption[] => {
  57. return asyncRouterMap.filter((route) => {
  58. if (type && route.children) {
  59. route.children = filterChildren(route.children, undefined);
  60. }
  61. if (route.component) {
  62. // Layout ParentView 组件特殊处理
  63. if (route.component === 'Layout') {
  64. route.component = Layout;
  65. } else if (route.component === 'ParentView') {
  66. route.component = ParentView;
  67. } else if (route.component === 'InnerLink') {
  68. route.component = InnerLink;
  69. } else {
  70. route.component = loadView(route.component);
  71. }
  72. }
  73. if (route.children != null && route.children && route.children.length) {
  74. route.children = filterAsyncRouter(route.children, route, type);
  75. } else {
  76. delete route.children;
  77. delete route.redirect;
  78. }
  79. return true;
  80. });
  81. };
  82. const filterChildren = (childrenMap: RouteOption[], lastRouter?: RouteOption): RouteOption[] => {
  83. let children: RouteOption[] = [];
  84. childrenMap.forEach((el) => {
  85. if (el.children && el.children.length) {
  86. if (el.component === 'ParentView' && !lastRouter) {
  87. el.children.forEach((c) => {
  88. c.path = el.path + '/' + c.path;
  89. if (c.children && c.children.length) {
  90. children = children.concat(filterChildren(c.children, c));
  91. return;
  92. }
  93. children.push(c);
  94. });
  95. return;
  96. }
  97. }
  98. if (lastRouter) {
  99. el.path = lastRouter.path + '/' + el.path;
  100. if (el.children && el.children.length) {
  101. children = children.concat(filterChildren(el.children, el))
  102. return
  103. }
  104. }
  105. children = children.concat(el);
  106. });
  107. return children;
  108. };
  109. return { routes, setRoutes, generateRoutes, setSidebarRouters, topbarRouters, sidebarRouters, defaultRoutes };
  110. });
  111. // 动态路由遍历,验证是否具备权限
  112. export const filterDynamicRoutes = (routes: RouteOption[]) => {
  113. const res: RouteOption[] = [];
  114. routes.forEach((route) => {
  115. if (route.permissions) {
  116. if (auth.hasPermiOr(route.permissions)) {
  117. res.push(route);
  118. }
  119. } else if (route.roles) {
  120. if (auth.hasRoleOr(route.roles)) {
  121. res.push(route);
  122. }
  123. }
  124. });
  125. return res;
  126. };
  127. export const loadView = (view: any) => {
  128. let res;
  129. for (const path in modules) {
  130. const dir = path.split('views/')[1].split('.vue')[0];
  131. if (dir === view) {
  132. res = () => modules[path]();
  133. }
  134. }
  135. return res;
  136. };
  137. // 非setup
  138. export const usePermissionStoreHook = () => {
  139. return usePermissionStore(store);
  140. };
  141. export default usePermissionStore;