aslan-h5/src/components/PermissionGuard.vue

142 lines
3.0 KiB
Vue

<!-- 权限控制组件示例 -->
<template>
<div class="permission-guard">
<!-- 权限不足提示 -->
<div v-if="!hasPermission && showDeniedMessage" class="permission-denied">
<div class="denied-icon">🚫</div>
<h3>Access Denied</h3>
<p>You don't have permission to access this feature.</p>
<p>Current role: {{ roleDisplayName }}</p>
<button @click="redirectToDefaultPage" class="redirect-btn">
Go to {{ defaultPageName }}
</button>
</div>
<!-- 有权限时显示内容 -->
<slot v-else></slot>
</div>
</template>
<script setup>
import { computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { permissionManager, hasPermission, getDefaultPage, getPrimaryRole } from '../utils/permissionManager.js'
const props = defineProps({
// 需要的权限页面路径
requiredPage: {
type: String,
required: true
},
// 是否显示权限不足消息
showDeniedMessage: {
type: Boolean,
default: true
},
// 权限不足时是否自动重定向
autoRedirect: {
type: Boolean,
default: false
}
})
const router = useRouter()
// 计算权限
const hasPagePermission = computed(() => {
return hasPermission(props.requiredPage)
})
// 实际显示权限(考虑是否已加载)
const hasPermission = computed(() => {
return permissionManager.isLoaded() && hasPagePermission.value
})
// 当前角色显示名称
const roleDisplayName = computed(() => {
return permissionManager.getRoleDisplayName()
})
// 默认页面名称
const defaultPageName = computed(() => {
const defaultPage = getDefaultPage()
const pageNames = {
'/coin-seller': 'Coin Seller',
'/agency-center': 'Agency Center',
'/bd-center': 'BD Center',
'/host-center': 'Host Center',
'/apply': 'Application'
}
return pageNames[defaultPage] || 'Home'
})
// 重定向到默认页面
const redirectToDefaultPage = () => {
const defaultPage = getDefaultPage()
router.push(defaultPage)
}
// 组件挂载时检查自动重定向
onMounted(() => {
if (props.autoRedirect && !hasPermission.value && permissionManager.isLoaded()) {
redirectToDefaultPage()
}
})
</script>
<style scoped>
.permission-guard {
width: 100%;
height: 100%;
}
.permission-denied {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 20px;
text-align: center;
min-height: 300px;
}
.denied-icon {
font-size: 48px;
margin-bottom: 16px;
}
.permission-denied h3 {
margin: 0 0 12px 0;
font-size: 24px;
font-weight: 600;
color: #dc2626;
}
.permission-denied p {
margin: 0 0 8px 0;
font-size: 16px;
color: #6b7280;
}
.redirect-btn {
margin-top: 20px;
padding: 12px 24px;
background-color: #8b5cf6;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.redirect-btn:hover {
background-color: #7c3aed;
}
.redirect-btn:active {
transform: scale(0.98);
}
</style>