gaoluyang
17 小时以前 8a2832d02126f33596c125c855d7effe96d69da1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import type { RouteRecordRaw } from 'vue-router';
 
import { useAccess } from '@vben/access';
import { useAccessStore, useUserStore } from '@vben/stores';
 
/** 首页常驻,业务数据和入口仍需遵循当前用户的菜单权限。 */
export function useHomeAccess() {
  const accessStore = useAccessStore();
  const userStore = useUserStore();
  const { hasAccessByCodes } = useAccess();
 
  /**
   * 接口权限:没有对应权限码就取不到数,请求会直接 403,所以取数前先问一句。
   *
   * 后端 `@ss.hasPermission` 对超管是直接放行的(不看权限码),前端这里保持一致,
   * 否则超管会因为权限码没在菜单里配而少看到卡片。
   */
  function canQuery(permission: string) {
    return (
      userStore.userRoles.includes('super_admin') ||
      hasAccessByCodes([permission, '*:*:*'])
    );
  }
 
  /**
   * 该菜单对当前用户是否「开着」—— 用于首页模块开关。
   *
   * 后端菜单 `visible = 0` 会被前端转成路由的 `meta.hideInMenu`,这类路由仍然注册在
   * router 里(页面可以直接访问),只是整棵子树不会出现在侧边栏。所以判断「这个模块有
   * 没有开」不能只看路由是否存在,还要看它和它的每一级祖先是否可见。
   *
   * @param name 路由 name,即后端菜单的 component_name
   */
  function canSeeMenu(name: string) {
    function find(
      routes: RouteRecordRaw[],
      ancestorHidden: boolean,
    ): boolean | undefined {
      for (const route of routes) {
        const hidden =
          ancestorHidden ||
          route.meta?.hideInMenu === true ||
          route.meta?.menuVisibleWithForbidden === true;
        if (route.name === name) return !hidden;
        const found = find(route.children ?? [], hidden);
        if (found !== undefined) return found;
      }
      return undefined;
    }
    return find(accessStore.accessRoutes, false) === true;
  }
 
  return { canQuery, canSeeMenu };
}