38 lines
1.3 KiB
Vue
38 lines
1.3 KiB
Vue
<script setup lang="ts">
|
||||
|
|
import { computed } from 'vue'
|
|||
|
|
import { ShieldX } from '@lucide/vue'
|
|||
|
|
import { useRoute, useRouter } from 'vue-router'
|
|||
|
|
import { sanitizeInternalPath } from '@/router/accessDecision'
|
|||
|
|
import { useAccessPreviewStore } from '@/stores/accessPreview'
|
|||
|
|
|
|||
|
|
const route = useRoute()
|
|||
|
|
const router = useRouter()
|
|||
|
|
const access = useAccessPreviewStore()
|
|||
|
|
|
|||
|
|
const sourcePath = computed(() => sanitizeInternalPath(route.query.from))
|
|||
|
|
const previewRoleLabel = computed(() => access.currentRole
|
|||
|
|
? `权限预览:${access.currentRole.name}`
|
|||
|
|
: '当前无可用角色')
|
|||
|
|
|
|||
|
|
async function returnToAccessiblePage() {
|
|||
|
|
if (!access.firstAccessiblePath) return
|
|||
|
|
await router.replace(access.firstAccessiblePath)
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<template>
|
|||
|
|
<section class="forbidden-page" aria-labelledby="forbidden-title">
|
|||
|
|
<div class="forbidden-icon" aria-hidden="true">
|
|||
|
|
<ShieldX :size="32" />
|
|||
|
|
</div>
|
|||
|
|
<p class="section-kicker">403 · 权限不足</p>
|
|||
|
|
<h2 id="forbidden-title">当前预览角色无法访问此页面</h2>
|
|||
|
|
<p>{{ previewRoleLabel }}</p>
|
|||
|
|
<p class="forbidden-source">来源页面:{{ sourcePath }}</p>
|
|||
|
|
<el-button v-if="access.firstAccessiblePath" type="primary" @click="returnToAccessiblePage">
|
|||
|
|
返回可访问页面
|
|||
|
|
</el-button>
|
|||
|
|
<p v-else>请使用顶栏切换角色,选择具有可访问菜单的角色。</p>
|
|||
|
|
</section>
|
|||
|
|
</template>
|