mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-09 13:53:38 +08:00
refactor: permission (#357)
* refactor: permission * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * fix: 修复`mix`混合模式导航在生产环境左侧菜单一定机率不显示的问题 * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update * chore: update
This commit is contained in:
@@ -2,8 +2,8 @@ import { getConfig } from "/@/config";
|
||||
import { toRouteType } from "./types";
|
||||
import NProgress from "/@/utils/progress";
|
||||
import { findIndex } from "lodash-unified";
|
||||
import type { StorageConfigs } from "/#/index";
|
||||
import { transformI18n } from "/@/plugins/i18n";
|
||||
import { sessionKey, type DataInfo } from "/@/utils/auth";
|
||||
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
import {
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
import {
|
||||
ascending,
|
||||
initRouter,
|
||||
isOneOfArray,
|
||||
getHistoryMode,
|
||||
findRouteByPath,
|
||||
handleAliveRoute,
|
||||
@@ -121,10 +122,10 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
handleAliveRoute(newMatched);
|
||||
}
|
||||
}
|
||||
const name = storageSession.getItem<StorageConfigs>("info");
|
||||
const userInfo = storageSession.getItem<DataInfo<number>>(sessionKey);
|
||||
NProgress.start();
|
||||
const externalLink = isUrl(to?.name as string);
|
||||
if (!externalLink)
|
||||
if (!externalLink) {
|
||||
to.matched.some(item => {
|
||||
if (!item.meta.title) return "";
|
||||
const Title = getConfig().Title;
|
||||
@@ -132,7 +133,12 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
document.title = `${transformI18n(item.meta.title)} | ${Title}`;
|
||||
else document.title = transformI18n(item.meta.title);
|
||||
});
|
||||
if (name) {
|
||||
}
|
||||
if (userInfo) {
|
||||
// 无权限跳转403页面
|
||||
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
||||
next({ path: "/error/403" });
|
||||
}
|
||||
if (_from?.name) {
|
||||
// name为超链接
|
||||
if (externalLink) {
|
||||
@@ -143,8 +149,11 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
}
|
||||
} else {
|
||||
// 刷新
|
||||
if (usePermissionStoreHook().wholeMenus.length === 0)
|
||||
initRouter(name.username).then((router: Router) => {
|
||||
if (
|
||||
usePermissionStoreHook().wholeMenus.length === 0 &&
|
||||
to.path !== "/login"
|
||||
)
|
||||
initRouter().then((router: Router) => {
|
||||
if (!useMultiTagsStoreHook().getMultiTagsCache) {
|
||||
const { path } = to;
|
||||
const index = findIndex(remainingRouter, v => {
|
||||
|
||||
@@ -6,7 +6,7 @@ const errorRouter: RouteConfigsTable = {
|
||||
redirect: "/error/403",
|
||||
meta: {
|
||||
icon: "information-line",
|
||||
title: $t("menus.hserror"),
|
||||
title: $t("menus.hsabnormal"),
|
||||
rank: 9
|
||||
},
|
||||
children: [
|
||||
|
||||
@@ -2,6 +2,7 @@ import { RouteLocationNormalized } from "vue-router";
|
||||
|
||||
export interface toRouteType extends RouteLocationNormalized {
|
||||
meta: {
|
||||
roles: Array<string>;
|
||||
keepAlive?: boolean;
|
||||
dynamicLevel?: string;
|
||||
};
|
||||
|
||||
@@ -9,10 +9,16 @@ import {
|
||||
import { router } from "./index";
|
||||
import { isProxy, toRaw } from "vue";
|
||||
import { loadEnv } from "../../build";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { useTimeoutFn } from "@vueuse/core";
|
||||
import { RouteConfigs } from "/@/layout/types";
|
||||
import { buildHierarchyTree } from "@pureadmin/utils";
|
||||
import {
|
||||
isString,
|
||||
storageSession,
|
||||
buildHierarchyTree,
|
||||
isIncludeAllChildren
|
||||
} from "@pureadmin/utils";
|
||||
import { cloneDeep, intersection } from "lodash-unified";
|
||||
import { sessionKey, type DataInfo } from "/@/utils/auth";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
const IFrame = () => import("/@/layout/frameView.vue");
|
||||
// https://cn.vitejs.dev/guide/features.html#glob-import
|
||||
@@ -38,7 +44,7 @@ function ascending(arr: any[]) {
|
||||
);
|
||||
}
|
||||
|
||||
/** 过滤meta中showLink为false的路由 */
|
||||
/** 过滤meta中showLink为false的菜单 */
|
||||
function filterTree(data: RouteComponent[]) {
|
||||
const newTree = cloneDeep(data).filter(
|
||||
(v: { meta: { showLink: boolean } }) => v.meta?.showLink !== false
|
||||
@@ -49,6 +55,37 @@ function filterTree(data: RouteComponent[]) {
|
||||
return newTree;
|
||||
}
|
||||
|
||||
/** 过滤children长度为0的的目录,当目录下没有菜单时,会过滤此目录,目录没有赋予roles权限,当目录下只要有一个菜单有显示权限,那么此目录就会显示 */
|
||||
function filterChildrenTree(data: RouteComponent[]) {
|
||||
const newTree = cloneDeep(data).filter((v: any) => v?.children?.length !== 0);
|
||||
newTree.forEach(
|
||||
(v: { children }) => v.children && (v.children = filterTree(v.children))
|
||||
);
|
||||
return newTree;
|
||||
}
|
||||
|
||||
/** 判断两个数组彼此是否存在相同值 */
|
||||
function isOneOfArray(a: Array<string>, b: Array<string>) {
|
||||
return Array.isArray(a) && Array.isArray(b)
|
||||
? intersection(a, b).length > 0
|
||||
? true
|
||||
: false
|
||||
: true;
|
||||
}
|
||||
|
||||
/** 从sessionStorage里取出当前登陆用户的角色roles,过滤无权限的菜单 */
|
||||
function filterNoPermissionTree(data: RouteComponent[]) {
|
||||
const currentRoles =
|
||||
storageSession.getItem<DataInfo<number>>(sessionKey).roles ?? [];
|
||||
const newTree = cloneDeep(data).filter((v: any) =>
|
||||
isOneOfArray(v.meta?.roles, currentRoles)
|
||||
);
|
||||
newTree.forEach(
|
||||
(v: any) => v.children && (v.children = filterNoPermissionTree(v.children))
|
||||
);
|
||||
return filterChildrenTree(newTree);
|
||||
}
|
||||
|
||||
/** 批量删除缓存路由(keepalive) */
|
||||
function delAliveRoutes(delAliveRouteList: Array<RouteConfigs>) {
|
||||
delAliveRouteList.forEach(route => {
|
||||
@@ -115,13 +152,13 @@ function addPathMatch() {
|
||||
}
|
||||
|
||||
/** 初始化路由 */
|
||||
function initRouter(name: string) {
|
||||
function initRouter() {
|
||||
return new Promise(resolve => {
|
||||
getAsyncRoutes({ name }).then(({ info }) => {
|
||||
if (info.length === 0) {
|
||||
usePermissionStoreHook().changeSetting(info);
|
||||
getAsyncRoutes().then(({ data }) => {
|
||||
if (data.length === 0) {
|
||||
usePermissionStoreHook().handleWholeMenus(data);
|
||||
} else {
|
||||
formatFlatteningRoutes(addAsyncRoutes(info)).map(
|
||||
formatFlatteningRoutes(addAsyncRoutes(data)).map(
|
||||
(v: RouteRecordRaw) => {
|
||||
// 防止重复添加路由
|
||||
if (
|
||||
@@ -144,7 +181,7 @@ function initRouter(name: string) {
|
||||
resolve(router);
|
||||
}
|
||||
);
|
||||
usePermissionStoreHook().changeSetting(info);
|
||||
usePermissionStoreHook().handleWholeMenus(data);
|
||||
}
|
||||
addPathMatch();
|
||||
});
|
||||
@@ -275,30 +312,29 @@ function getHistoryMode(): RouterHistory {
|
||||
}
|
||||
}
|
||||
|
||||
/** 是否有权限 */
|
||||
function hasPermissions(value: Array<string>): boolean {
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const roles = usePermissionStoreHook().buttonAuth;
|
||||
const permissionRoles = value;
|
||||
/** 获取当前页面按钮级别的权限 */
|
||||
function getAuths(): Array<string> {
|
||||
return router.currentRoute.value.meta.auths as Array<string>;
|
||||
}
|
||||
|
||||
const hasPermission = roles.some(role => {
|
||||
return permissionRoles.includes(role);
|
||||
});
|
||||
|
||||
if (!hasPermission) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
/** 是否有按钮级别的权限 */
|
||||
function hasAuth(value: string | Array<string>): boolean {
|
||||
if (!value) return false;
|
||||
/** 从当前路由的`meta`字段里获取按钮级别的所有自定义`code`值 */
|
||||
const metaAuths = getAuths();
|
||||
const isAuths = isString(value)
|
||||
? metaAuths.includes(value)
|
||||
: isIncludeAllChildren(value, metaAuths);
|
||||
return isAuths ? true : false;
|
||||
}
|
||||
|
||||
export {
|
||||
hasAuth,
|
||||
getAuths,
|
||||
ascending,
|
||||
filterTree,
|
||||
initRouter,
|
||||
hasPermissions,
|
||||
isOneOfArray,
|
||||
getHistoryMode,
|
||||
addAsyncRoutes,
|
||||
delAliveRoutes,
|
||||
@@ -306,5 +342,6 @@ export {
|
||||
findRouteByPath,
|
||||
handleAliveRoute,
|
||||
formatTwoStageRoutes,
|
||||
formatFlatteningRoutes
|
||||
formatFlatteningRoutes,
|
||||
filterNoPermissionTree
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user