import type { RouteRecordRaw } from 'vue-router';
|
|
import { computed } from 'vue';
|
|
import { useAccess } from '@vben/access';
|
import { useAccessStore } from '@vben/stores';
|
|
/** 首页常驻,业务数据和入口仍需遵循当前用户的菜单权限。 */
|
export function useHomeAccess() {
|
const accessStore = useAccessStore();
|
const { hasAccessByCodes } = useAccess();
|
|
function canQuery(permission: string) {
|
return hasAccessByCodes([permission, '*:*:*']);
|
}
|
|
function canNavigate(name: string) {
|
function contains(routes: RouteRecordRaw[]): boolean {
|
return routes.some((route) => {
|
if (route.meta?.menuVisibleWithForbidden) return false;
|
return route.name === name || contains(route.children ?? []);
|
});
|
}
|
return contains(accessStore.accessRoutes);
|
}
|
|
/**
|
* 该菜单对当前用户是否「开着」—— 用于首页模块开关。
|
*
|
* 后端菜单 `visible = 0` 会被前端转成路由的 `meta.hideInMenu`,这类路由仍然注册在
|
* router 里(`canNavigate` 为 true,页面可以直接访问),只是整棵子树不会出现在侧边栏。
|
* 所以判断「这个模块有没有开」不能只看路由是否存在,还要看它和它的每一级祖先是否可见。
|
*/
|
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;
|
}
|
|
const canViewHome = computed(() => canQuery('mes:home:query'));
|
|
return { canNavigate, canQuery, canSeeMenu, canViewHome };
|
}
|