feat: Improve the front-end and back-end permission mode and useAccess
This commit is contained in:
@@ -9,7 +9,7 @@ import type {
|
||||
|
||||
type BreadcrumbStyleType = 'background' | 'normal';
|
||||
|
||||
type accessModeType = 'allow-all' | 'backend' | 'frontend';
|
||||
type AccessModeType = 'allow-all' | 'backend' | 'frontend';
|
||||
|
||||
type NavigationStyleType = 'plain' | 'rounded';
|
||||
|
||||
@@ -19,7 +19,7 @@ type AuthPageLayoutType = 'panel-center' | 'panel-left' | 'panel-right';
|
||||
|
||||
interface AppPreferences {
|
||||
/** 权限模式 */
|
||||
accessMode: accessModeType;
|
||||
accessMode: AccessModeType;
|
||||
/** 是否开启vben助手 */
|
||||
aiAssistant: boolean;
|
||||
/** 登录注册页面布局 */
|
||||
@@ -190,6 +190,7 @@ interface Preferences {
|
||||
type PreferencesKeys = keyof Preferences;
|
||||
|
||||
export type {
|
||||
AccessModeType,
|
||||
AppPreferences,
|
||||
AuthPageLayoutType,
|
||||
BreadcrumbPreferences,
|
||||
@@ -212,5 +213,4 @@ export type {
|
||||
ThemeModeType,
|
||||
ThemePreferences,
|
||||
TransitionPreferences,
|
||||
accessModeType,
|
||||
};
|
||||
|
@@ -29,6 +29,10 @@ interface BasicUserInfo {
|
||||
}
|
||||
|
||||
interface AccessState {
|
||||
/**
|
||||
* 权限码
|
||||
*/
|
||||
accessCodes: string[];
|
||||
/**
|
||||
* 可访问的菜单列表
|
||||
*/
|
||||
@@ -60,6 +64,9 @@ interface AccessState {
|
||||
*/
|
||||
const useCoreAccessStore = defineStore('core-access', {
|
||||
actions: {
|
||||
setAccessCodes(codes: string[]) {
|
||||
this.accessCodes = codes;
|
||||
},
|
||||
setAccessMenus(menus: MenuRecordRaw[]) {
|
||||
this.accessMenus = menus;
|
||||
},
|
||||
@@ -84,6 +91,9 @@ const useCoreAccessStore = defineStore('core-access', {
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
getAccessCodes(): string[] {
|
||||
return this.accessCodes;
|
||||
},
|
||||
getAccessMenus(): MenuRecordRaw[] {
|
||||
return this.accessMenus;
|
||||
},
|
||||
@@ -102,12 +112,16 @@ const useCoreAccessStore = defineStore('core-access', {
|
||||
getUserRoles(): string[] {
|
||||
return this.userRoles;
|
||||
},
|
||||
string(): string[] {
|
||||
return this.accessCodes;
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
// 持久化
|
||||
paths: ['accessToken', 'refreshToken'],
|
||||
paths: ['accessToken', 'refreshToken', 'accessCodes'],
|
||||
},
|
||||
state: (): AccessState => ({
|
||||
accessCodes: [],
|
||||
accessMenus: [],
|
||||
accessRoutes: [],
|
||||
accessToken: null,
|
||||
|
@@ -9,7 +9,7 @@ interface Props {
|
||||
* Specified codes is visible
|
||||
* @default []
|
||||
*/
|
||||
codes?: string[];
|
||||
value?: string[];
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
@@ -17,13 +17,13 @@ defineOptions({
|
||||
});
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
codes: () => [],
|
||||
value: () => [],
|
||||
});
|
||||
|
||||
const { hasAuthByRole } = useAccess();
|
||||
const { hasAuthByCodes } = useAccess();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot v-if="!codes"></slot>
|
||||
<slot v-else-if="hasAuthByRole(codes)"></slot>
|
||||
<slot v-if="!value"></slot>
|
||||
<slot v-else-if="hasAuthByCodes(value)"></slot>
|
||||
</template>
|
||||
|
@@ -30,6 +30,7 @@ async function generateRoutesByBackend(
|
||||
}
|
||||
|
||||
const routes = convertRoutes(menuRoutes, layoutMap, normalizePageMap);
|
||||
|
||||
return routes;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { accessModeType } from '@vben-core/preferences';
|
||||
import type { AccessModeType } from '@vben-core/preferences';
|
||||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import type { GeneratorMenuAndRoutesOptions } from '../types';
|
||||
@@ -10,7 +10,7 @@ import { generateRoutesByBackend } from './generate-routes-backend';
|
||||
import { generateRoutesByFrontend } from './generate-routes-frontend';
|
||||
|
||||
async function generateMenusAndRoutes(
|
||||
mode: accessModeType,
|
||||
mode: AccessModeType,
|
||||
options: GeneratorMenuAndRoutesOptions,
|
||||
) {
|
||||
const { router } = options;
|
||||
@@ -20,7 +20,9 @@ async function generateMenusAndRoutes(
|
||||
const accessibleRoutes = await generateRoutes(mode, options);
|
||||
|
||||
// 动态添加到router实例内
|
||||
accessibleRoutes.forEach((route) => router.addRoute(route));
|
||||
accessibleRoutes.forEach((route) => {
|
||||
router.addRoute(route);
|
||||
});
|
||||
|
||||
// 生成菜单
|
||||
const accessibleMenus = await generateMenus1(mode, accessibleRoutes, options);
|
||||
@@ -33,7 +35,7 @@ async function generateMenusAndRoutes(
|
||||
* @param mode
|
||||
*/
|
||||
async function generateRoutes(
|
||||
mode: accessModeType,
|
||||
mode: AccessModeType,
|
||||
options: GeneratorMenuAndRoutesOptions,
|
||||
) {
|
||||
const { forbiddenComponent, roles, routes } = options;
|
||||
@@ -60,7 +62,7 @@ async function generateRoutes(
|
||||
}
|
||||
|
||||
async function generateMenus1(
|
||||
mode: accessModeType,
|
||||
mode: AccessModeType,
|
||||
routes: RouteRecordRaw[],
|
||||
options: GeneratorMenuAndRoutesOptions,
|
||||
) {
|
||||
|
@@ -9,7 +9,7 @@ interface Props {
|
||||
* Specified role is visible
|
||||
* @default []
|
||||
*/
|
||||
roles?: string[];
|
||||
value?: string[];
|
||||
}
|
||||
|
||||
defineOptions({
|
||||
@@ -17,13 +17,13 @@ defineOptions({
|
||||
});
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
roles: undefined,
|
||||
value: undefined,
|
||||
});
|
||||
|
||||
const { hasAuthByRole } = useAccess();
|
||||
const { hasAuthByRoles } = useAccess();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot v-if="!roles"></slot>
|
||||
<slot v-else-if="hasAuthByRole(roles)"></slot>
|
||||
<slot v-if="!value"></slot>
|
||||
<slot v-else-if="hasAuthByRoles(value)"></slot>
|
||||
</template>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { preferences } from '@vben-core/preferences';
|
||||
import { preferences, updatePreferences } from '@vben-core/preferences';
|
||||
import { useCoreAccessStore } from '@vben-core/stores';
|
||||
|
||||
function useAccess() {
|
||||
@@ -14,13 +14,39 @@ function useAccess() {
|
||||
* @description: Determine whether there is permission,The role is judged by the user's role
|
||||
* @param roles
|
||||
*/
|
||||
function hasAuthByRole(roles: string[]) {
|
||||
function hasAuthByRoles(roles: string[]) {
|
||||
const userRoleSet = new Set(coreAccessStore.getUserRoles);
|
||||
const intersection = roles.filter((item) => userRoleSet.has(item));
|
||||
return intersection.length > 0;
|
||||
}
|
||||
|
||||
return { accessMode, hasAuthByRole };
|
||||
/**
|
||||
* 基于权限码判断是否有权限
|
||||
* @description: Determine whether there is permission,The permission code is judged by the user's permission code
|
||||
* @param codes
|
||||
*/
|
||||
function hasAuthByCodes(codes: string[]) {
|
||||
const userCodesSet = new Set(coreAccessStore.getAccessCodes);
|
||||
|
||||
const intersection = codes.filter((item) => userCodesSet.has(item));
|
||||
return intersection.length > 0;
|
||||
}
|
||||
|
||||
async function toggleAccessMode() {
|
||||
updatePreferences({
|
||||
app: {
|
||||
accessMode:
|
||||
preferences.app.accessMode === 'frontend' ? 'backend' : 'frontend',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
accessMode,
|
||||
hasAuthByCodes,
|
||||
hasAuthByRoles,
|
||||
toggleAccessMode,
|
||||
};
|
||||
}
|
||||
|
||||
export { useAccess };
|
||||
|
@@ -9,9 +9,9 @@ page:
|
||||
page: Page visit
|
||||
button: Button control
|
||||
loading-menu: In the loading menu
|
||||
access-test-1: Admin visit
|
||||
access-test-2: User visit
|
||||
access-test-3: Super visit
|
||||
access-test-1: Super visit
|
||||
access-test-2: Admin visit
|
||||
access-test-3: User visit
|
||||
nested:
|
||||
title: Nested Menu
|
||||
menu1: Menu 1
|
||||
|
@@ -8,9 +8,9 @@ page:
|
||||
backend-control: 后端控制
|
||||
page: 页面访问
|
||||
button: 按钮控制
|
||||
access-test-1: Admin 角色可见
|
||||
access-test-2: User 角色可见
|
||||
access-test-3: Super 角色可见
|
||||
access-test-1: Super 可见
|
||||
access-test-2: Admin 可见
|
||||
access-test-3: User 可见
|
||||
|
||||
nested:
|
||||
title: 嵌套菜单
|
||||
|
Reference in New Issue
Block a user