feat: 管理端 RBAC 权限体系与员工管理

新增多角色权限控制(赛事/财务/客服管理员),支持员工 CRUD、路由菜单按权限显隐、审计日志范围过滤;登录返回角色与权限列表。玩家端赛事列表增加静默刷新避免图片闪烁。Seed 补充演示员工账号与充值相关权限。附带 RBAC/审计范围单元测试及 UAT 文档更新。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-15 17:52:39 +08:00
parent be5b4a4921
commit 567ec9ec8a
44 changed files with 1717 additions and 125 deletions

View File

@@ -3,6 +3,8 @@ import { computed, onMounted, ref } from 'vue';
import type { TableColumnCtx } from 'element-plus';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useAdminLocale } from '../composables/useAdminLocale';
import { usePermissions } from '../composables/usePermissions';
import { AdminPerm } from '../constants/permissions';
import { formatAmount, formatAmountFull } from '../utils/format-amount';
import { formatRatePercent } from '../utils/rate-percent';
import AdminTableEmpty from '../components/AdminTableEmpty.vue';
@@ -46,6 +48,8 @@ interface CashbackPreview {
}
const { t, localeTag } = useAdminLocale();
const { hasPermission } = usePermissions();
const canConfirmCashback = computed(() => hasPermission(AdminPerm.cashback));
const preview = ref<CashbackPreview | null>(null);
const rulesVisible = ref(false);
@@ -418,7 +422,7 @@ onMounted(loadHistory);
</el-table>
</div>
<div v-if="preview.batch.status === 'PREVIEW'" class="preview-actions">
<div v-if="preview.batch.status === 'PREVIEW' && canConfirmCashback" class="preview-actions">
<el-button type="success" :disabled="previewItems.length === 0" @click="confirm">
{{ t('cashback.confirm_issue') }}
</el-button>
@@ -484,7 +488,7 @@ onMounted(loadHistory);
<el-button link type="primary" @click="openDetail(row.id)">
{{ t('cashback.view_detail') }}
</el-button>
<template v-if="row.status === 'PREVIEW'">
<template v-if="row.status === 'PREVIEW' && canConfirmCashback">
<el-button link type="success" @click="confirmBatchId(row.id)">
{{ t('cashback.confirm_issue') }}
</el-button>
@@ -577,7 +581,7 @@ onMounted(loadHistory);
</el-table-column>
</el-table>
</div>
<div v-if="detail?.batch.status === 'PREVIEW'" class="detail-actions">
<div v-if="detail?.batch.status === 'PREVIEW' && canConfirmCashback" class="detail-actions">
<el-button type="success" :disabled="detailItems.length === 0" @click="confirmBatchId(detail.batch.id)">
{{ t('cashback.confirm_issue') }}
</el-button>