142 lines
3.0 KiB
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>
|