feat: Improve the front-end permission access logic and sample code
parent
dd71988253
commit
a60467b01c
|
@ -1,9 +1,115 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Fallback } from '@vben/universal-ui';
|
import type { LoginAndRegisterParams } from '@vben/universal-ui';
|
||||||
|
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import { RoleAuthority, useAccess } from '@vben/access';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useAccessStore, useAppStore } from '#/store';
|
||||||
|
|
||||||
defineOptions({ name: 'AccessFrontendButtonControl' });
|
defineOptions({ name: 'AccessFrontendButtonControl' });
|
||||||
|
|
||||||
|
const { accessMode, hasAuthByRole } = useAccess();
|
||||||
|
const accessStore = useAccessStore();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
function roleButtonType(role: string) {
|
||||||
|
return accessStore.userRoles.includes(role) ? 'primary' : 'default';
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeAccount(role: string) {
|
||||||
|
if (accessStore.userRoles.includes(role)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const accounts: Record<string, LoginAndRegisterParams> = {
|
||||||
|
admin: {
|
||||||
|
password: '123456',
|
||||||
|
username: 'admin',
|
||||||
|
},
|
||||||
|
super: {
|
||||||
|
password: '123456',
|
||||||
|
username: 'vben',
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
password: '123456',
|
||||||
|
username: 'jack',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const account = accounts[role];
|
||||||
|
await appStore.resetAppState();
|
||||||
|
await accessStore.authLogin(account, async () => {
|
||||||
|
router.go(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Fallback status="comming-soon" />
|
<div class="p-5">
|
||||||
|
<div class="card-box p-5">
|
||||||
|
<h1 class="text-xl font-semibold">前端按钮访问权限演示</h1>
|
||||||
|
<div class="text-foreground/80 mt-2">
|
||||||
|
切换不同的账号,观察按钮显示变化
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="accessMode === 'frontend'">
|
||||||
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
|
<div class="mb-3">
|
||||||
|
<span class="text-lg">当前账号:</span>
|
||||||
|
<span class="text-primary mx-4">
|
||||||
|
{{ accessStore.userRoles }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button :type="roleButtonType('super')" @click="changeAccount('super')">
|
||||||
|
切换为 Super 账号
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
:type="roleButtonType('admin')"
|
||||||
|
class="mx-4"
|
||||||
|
@click="changeAccount('admin')"
|
||||||
|
>
|
||||||
|
切换为 Admin 账号
|
||||||
|
</Button>
|
||||||
|
<Button :type="roleButtonType('user')" @click="changeAccount('user')">
|
||||||
|
切换为 User 账号
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
|
<div class="mb-3 text-lg">组件形式控制</div>
|
||||||
|
<RoleAuthority :roles="['super']">
|
||||||
|
<Button class="mr-4"> Super 角色可见 </Button>
|
||||||
|
</RoleAuthority>
|
||||||
|
<RoleAuthority :roles="['admin']">
|
||||||
|
<Button class="mr-4"> Admin 角色可见 </Button>
|
||||||
|
</RoleAuthority>
|
||||||
|
<RoleAuthority :roles="['user']">
|
||||||
|
<Button class="mr-4"> User 角色可见 </Button>
|
||||||
|
</RoleAuthority>
|
||||||
|
<RoleAuthority :roles="['super', 'admin']">
|
||||||
|
<Button class="mr-4"> Super 和 Admin 角色都可见 </Button>
|
||||||
|
</RoleAuthority>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
|
<div class="mb-3 text-lg">函数形式控制</div>
|
||||||
|
<Button v-if="hasAuthByRole(['super'])" class="mr-4">
|
||||||
|
Super 角色可见
|
||||||
|
</Button>
|
||||||
|
<Button v-if="hasAuthByRole(['admin'])" class="mr-4">
|
||||||
|
Admin 角色可见
|
||||||
|
</Button>
|
||||||
|
<Button v-if="hasAuthByRole(['user'])" class="mr-4">
|
||||||
|
User 角色可见
|
||||||
|
</Button>
|
||||||
|
<Button v-if="hasAuthByRole(['super', 'admin'])" class="mr-4">
|
||||||
|
Super 和 Admin 角色都可见
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -49,7 +49,7 @@ async function changeAccount(role: string) {
|
||||||
<template>
|
<template>
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
<div class="card-box p-5">
|
<div class="card-box p-5">
|
||||||
<h1 class="text-xl font-semibold">前端页面访问演示</h1>
|
<h1 class="text-xl font-semibold">前端页面访问权限演示</h1>
|
||||||
<div class="text-foreground/80 mt-2">
|
<div class="text-foreground/80 mt-2">
|
||||||
切换不同的账号,观察左侧菜单变化。
|
切换不同的账号,观察左侧菜单变化。
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,14 +57,14 @@ async function changeAccount(role: string) {
|
||||||
|
|
||||||
<template v-if="accessMode === 'frontend'">
|
<template v-if="accessMode === 'frontend'">
|
||||||
<div class="card-box mt-5 p-5 font-semibold">
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
当前权限模式:
|
<span class="text-lg">当前权限模式:</span>
|
||||||
<span class="text-primary mx-4">{{ accessMode }}</span>
|
<span class="text-primary mx-4">{{ accessMode }}</span>
|
||||||
<Button type="primary">切换权限模式</Button>
|
<Button type="primary">切换权限模式</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-box mt-5 p-5 font-semibold">
|
<div class="card-box mt-5 p-5 font-semibold">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
当前账号:
|
<span class="text-lg">当前账号:</span>
|
||||||
<span class="text-primary mx-4">
|
<span class="text-primary mx-4">
|
||||||
{{ accessStore.userRoles }}
|
{{ accessStore.userRoles }}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!--
|
||||||
|
Access control component for fine-grained access control.
|
||||||
|
-->
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useAccess } from './use-access';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/**
|
||||||
|
* Specified codes is visible
|
||||||
|
* @default []
|
||||||
|
*/
|
||||||
|
codes?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'CodeAuthority',
|
||||||
|
});
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
codes: () => [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const { hasAuthByRole } = useAccess();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<slot v-if="!codes"></slot>
|
||||||
|
<slot v-else-if="hasAuthByRole(codes)"></slot>
|
||||||
|
</template>
|
|
@ -1,3 +1,4 @@
|
||||||
|
export { default as CodeAuthority } from './code-authority.vue';
|
||||||
export * from './generate-menu-and-routes';
|
export * from './generate-menu-and-routes';
|
||||||
export { default as RoleAuthority } from './role-authority.vue';
|
export { default as RoleAuthority } from './role-authority.vue';
|
||||||
export type * from './types';
|
export type * from './types';
|
||||||
|
|
|
@ -2,25 +2,28 @@
|
||||||
Access control component for fine-grained access control.
|
Access control component for fine-grained access control.
|
||||||
-->
|
-->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { useAccess } from './use-access';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* Specified role is visible
|
* Specified role is visible
|
||||||
* - When the permission mode is 'frontend', the value can be a role value.
|
* @default []
|
||||||
* - When the permission mode is 'backend', the value can be a code permission value.
|
|
||||||
* @default ''
|
|
||||||
*/
|
*/
|
||||||
roles?: string[];
|
roles?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'FrontendAuthority',
|
name: 'RoleAuthority',
|
||||||
});
|
});
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
withDefaults(defineProps<Props>(), {
|
||||||
roles: undefined,
|
roles: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { hasAuthByRole } = useAccess();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<slot></slot>
|
<slot v-if="!roles"></slot>
|
||||||
|
<slot v-else-if="hasAuthByRole(roles)"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { preferences } from '@vben-core/preferences';
|
import { preferences } from '@vben-core/preferences';
|
||||||
|
import { useCoreAccessStore } from '@vben-core/stores';
|
||||||
|
|
||||||
function useAccess() {
|
function useAccess() {
|
||||||
|
const coreAccessStore = useCoreAccessStore();
|
||||||
const accessMode = computed(() => {
|
const accessMode = computed(() => {
|
||||||
return preferences.app.accessMode;
|
return preferences.app.accessMode;
|
||||||
});
|
});
|
||||||
|
|
||||||
return { accessMode };
|
/**
|
||||||
|
* 基于角色判断是否有权限
|
||||||
|
* @description: Determine whether there is permission,The role is judged by the user's role
|
||||||
|
* @param roles
|
||||||
|
*/
|
||||||
|
function hasAuthByRole(roles: string[]) {
|
||||||
|
const userRoleSet = new Set(coreAccessStore.getUserRoles);
|
||||||
|
const intersection = roles.filter((item) => userRoleSet.has(item));
|
||||||
|
return intersection.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { accessMode, hasAuthByRole };
|
||||||
}
|
}
|
||||||
|
|
||||||
export { useAccess };
|
export { useAccess };
|
||||||
|
|
Loading…
Reference in New Issue