feat: 管理端 RBAC 权限体系与员工管理
新增多角色权限控制(赛事/财务/客服管理员),支持员工 CRUD、路由菜单按权限显隐、审计日志范围过滤;登录返回角色与权限列表。玩家端赛事列表增加静默刷新避免图片闪烁。Seed 补充演示员工账号与充值相关权限。附带 RBAC/审计范围单元测试及 UAT 文档更新。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,17 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import { shallowRef, onBeforeMount, type Component } from 'vue';
|
||||
import { RouterView } from 'vue-router';
|
||||
import { RouterView, RouterLink, useRoute, useRouter } from 'vue-router';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import { ensureStaffSession } from '../utils/session-hydrate';
|
||||
import DashboardSubNav from '../components/DashboardSubNav.vue';
|
||||
import { usePermissions } from '../composables/usePermissions';
|
||||
import { AdminPerm } from '../constants/permissions';
|
||||
|
||||
const auth = useAuthStore();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const { t } = useAdminLocale();
|
||||
const { hasPermission, role } = usePermissions();
|
||||
const agentDashboard = shallowRef<Component | null>(null);
|
||||
const booting = shallowRef(true);
|
||||
|
||||
const showSupportShortcuts = shallowRef(false);
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await ensureStaffSession();
|
||||
if (!auth.isAdmin.value) {
|
||||
if (auth.isAdmin.value) {
|
||||
const code = role.value;
|
||||
if (code === 'FINANCE_ADMIN' && route.path === '/') {
|
||||
await router.replace('/dashboard/players');
|
||||
} else if (code === 'SUPPORT') {
|
||||
showSupportShortcuts.value = true;
|
||||
if (route.path === '/' || route.path === '/dashboard/players') {
|
||||
if (hasPermission(AdminPerm.usersView, AdminPerm.agentsView)) {
|
||||
await router.replace('/users');
|
||||
} else if (hasPermission(AdminPerm.bets)) {
|
||||
await router.replace('/bets');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
agentDashboard.value = (await import('./agent/Dashboard.vue')).default;
|
||||
}
|
||||
booting.value = false;
|
||||
@@ -21,6 +44,17 @@ onBeforeMount(async () => {
|
||||
<template>
|
||||
<div v-if="booting" v-loading="true" class="home-boot" />
|
||||
<template v-else-if="auth.isAdmin.value">
|
||||
<div v-if="showSupportShortcuts" class="support-shortcuts">
|
||||
<RouterLink v-if="hasPermission(AdminPerm.usersView, AdminPerm.agentsView)" to="/users" class="support-link">
|
||||
{{ t('nav.agents_players') }}
|
||||
</RouterLink>
|
||||
<RouterLink v-if="hasPermission(AdminPerm.bets)" to="/bets" class="support-link">
|
||||
{{ t('nav.bets') }}
|
||||
</RouterLink>
|
||||
<RouterLink v-if="hasPermission(AdminPerm.reports)" to="/finance-logs" class="support-link">
|
||||
{{ t('nav.finance_logs') }}
|
||||
</RouterLink>
|
||||
</div>
|
||||
<div class="dashboard-shell">
|
||||
<div class="list-chrome">
|
||||
<div class="list-chrome__row">
|
||||
@@ -40,6 +74,28 @@ onBeforeMount(async () => {
|
||||
min-height: 240px;
|
||||
}
|
||||
|
||||
.support-shortcuts {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.support-link {
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
background: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 650;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.support-link:hover {
|
||||
border-color: var(--primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.dashboard-shell :deep(.list-chrome) {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user