feat(permissions): implement document permission matrix

This commit is contained in:
yelan
2026-08-27 16:47:55 +08:00
parent e7aa4843b7
commit 94a0d88f8b
5 changed files with 578 additions and 17 deletions
@@ -1,12 +1,187 @@
<script setup lang="ts">
import PagePlaceholder from '@/components/PagePlaceholder.vue'
import { onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus'
import DepartmentPermissionTable from './components/DepartmentPermissionTable.vue'
import RolePermissionMatrix from './components/RolePermissionMatrix.vue'
import { departmentPermissionRows, permissionColumns, rolePermissionRows } from './mock'
import type { DepartmentPermissionRow, PermissionKey, RolePermissionRow } from './types'
const loading = ref(true)
const roles = ref<RolePermissionRow[]>([])
const departments = ref<DepartmentPermissionRow[]>([])
async function loadPermissions() {
loading.value = true
await Promise.resolve()
roles.value = rolePermissionRows.map((role) => ({
...role,
permissions: { ...role.permissions },
}))
departments.value = departmentPermissionRows.map((row) => ({ ...row }))
loading.value = false
}
function toggleRolePermission(roleId: string, permission: PermissionKey) {
const role = roles.value.find((item) => item.id === roleId)
if (!role) {
return
}
role.permissions[permission] = !role.permissions[permission]
ElMessage.info('权限已调整并记录审计日志')
}
function adjustDepartmentPermission(row: DepartmentPermissionRow) {
ElMessage.info(`原型演示:调整${row.department}文档权限`)
}
onMounted(loadPermissions)
</script>
<template>
<PagePlaceholder
group="管理"
title="文档权限"
icon="⊞"
description="文档权限页面占位,待根据 Web 端需求实现。"
/>
<section class="permissions-page">
<section class="page-card intro-card">
<div class="card-heading">
<h2>文档库权限矩阵</h2>
<span>可见 / 可用 / 可维护 分级授权,下级继承上级</span>
</div>
<p>
可见=可浏览模板;可用=可发起签署;可维护=可编辑/停用模板。科室签署员默认继承本科室「可用」权限。调整即时生效并记录审计日志。
</p>
</section>
<template v-if="loading">
<section class="page-card loading-card" aria-label="正在加载权限配置">
<span class="loading-title" />
<span class="loading-row" />
<span class="loading-row" />
<span class="loading-row short" />
</section>
</template>
<template v-else>
<section class="page-card">
<div class="card-heading">
<h2>按角色授权</h2>
</div>
<RolePermissionMatrix
:rows="roles"
:columns="permissionColumns"
@toggle="toggleRolePermission"
/>
</section>
<section class="page-card department-card">
<div class="card-heading">
<h2>按科室授权</h2>
<span>科室级别的文档可用范围</span>
</div>
<DepartmentPermissionTable :rows="departments" @adjust="adjustDepartmentPermission" />
</section>
</template>
</section>
</template>
<style scoped>
.permissions-page {
width: 100%;
max-width: 1440px;
margin: 0 auto;
}
.page-card {
padding: 16px 18px;
margin-bottom: 16px;
background: var(--card);
border-radius: var(--r);
box-shadow: var(--sh);
}
.intro-card {
margin-bottom: 14px;
}
.card-heading {
display: flex;
gap: 10px;
align-items: center;
margin-bottom: 14px;
}
.card-heading h2 {
margin: 0;
color: var(--ink);
font-size: 14.5px;
line-height: 1.4;
}
.card-heading span {
margin-left: auto;
color: var(--mut);
font-size: 12px;
}
.intro-card p {
margin: 0;
color: var(--mut);
font-size: 12px;
line-height: 1.8;
}
.department-card {
margin-top: 16px;
margin-bottom: 0;
}
.loading-card {
display: flex;
flex-direction: column;
gap: 14px;
min-height: 180px;
}
.loading-card span {
display: block;
background: linear-gradient(90deg, #edf3f5 25%, #f7fafb 37%, #edf3f5 63%);
background-size: 400% 100%;
border-radius: 6px;
animation: skeleton-shimmer 1.4s ease infinite;
}
.loading-title {
width: 28%;
height: 20px;
}
.loading-row {
width: 100%;
height: 14px;
}
.loading-row.short {
width: 70%;
}
@keyframes skeleton-shimmer {
0% {
background-position: 100% 0;
}
100% {
background-position: -100% 0;
}
}
@media (max-width: 600px) {
.card-heading {
align-items: flex-start;
flex-direction: column;
}
.card-heading span {
margin-left: 0;
}
}
</style>