6 changed files with 163 additions and 11 deletions
@ -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> |
||||
|
|||||
@ -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,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