fix: 完善文档权限接口接入
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
1. **文档库权限矩阵**:说明可见、可用、可维护和继承规则。
|
1. **文档库权限矩阵**:说明可见、可用、可维护和继承规则。
|
||||||
2. **按角色授权**:选择一个文档模板,调整角色的 VIEW、USE、MAINTAIN。
|
2. **按角色授权**:选择一个文档模板,调整角色的 VIEW、USE、MAINTAIN。
|
||||||
3. **按科室授权**:沿用当前模板,调整科室的 VIEW、USE、MAINTAIN。
|
3. **按科室授权**:沿用当前模板,调整科室的 VIEW、USE、MAINTAIN。
|
||||||
4. **模板权限明细与直接授权**:可选择角色、科室或用户新增/删除直接绑定。
|
4. **模板权限明细与直接授权**:可选择角色、科室或用户新增/删除直接绑定,并选择用户预览继承结果。
|
||||||
|
|
||||||
## 已接入接口
|
## 已接入接口
|
||||||
|
|
||||||
@@ -36,6 +36,10 @@
|
|||||||
- USE:可发起签署
|
- USE:可发起签署
|
||||||
- MAINTAIN:可维护模板
|
- MAINTAIN:可维护模板
|
||||||
|
|
||||||
|
模板、科室和用户接口都是分页接口,页面按后端返回的 `total` 自动补齐后续页,不会因为接口单页上限 200 而漏掉授权对象。角色优先使用 `/roles/summary` 获取人数;该接口失败时回退 `/roles`,人数按已加载用户的角色关系估算。
|
||||||
|
|
||||||
|
查询模板权限时不传 `userId` 表示查看当前登录用户的继承结果;页面也支持选择用户,将其 UUID 作为 `userId` 重新查询,用于预览该用户的科室签署员默认 `USE` 继承。接口返回的直接绑定和继承结果统一展示,但只有直接绑定带有可删除的 `id`。
|
||||||
|
|
||||||
## 页面保存行为
|
## 页面保存行为
|
||||||
|
|
||||||
当前契约没有更新权限绑定的 PUT 接口,因此开关按以下规则保存:
|
当前契约没有更新权限绑定的 PUT 接口,因此开关按以下规则保存:
|
||||||
@@ -44,7 +48,7 @@
|
|||||||
- 关闭:撤销直接 ALLOW;如果仍有继承的 ALLOW,POST 直接 DENY 覆盖继承。
|
- 关闭:撤销直接 ALLOW;如果仍有继承的 ALLOW,POST 直接 DENY 覆盖继承。
|
||||||
- 继承 DENY 没有持久化绑定 ID,且契约约定拒绝优先,页面将其显示为不可直接覆盖。
|
- 继承 DENY 没有持久化绑定 ID,且契约约定拒绝优先,页面将其显示为不可直接覆盖。
|
||||||
|
|
||||||
页面不会把继承结果当成可删除的直接绑定,也不会伪造全局权限矩阵数据。真实环境接口没有数据时会显示空态。
|
页面不会把继承结果当成可删除的直接绑定,也不会伪造全局权限矩阵数据。权限查询失败时会显示错误态并禁用新增、删除和矩阵调整,避免把空响应误当成“无权限”。真实环境接口没有数据时会显示空态。
|
||||||
|
|
||||||
## 当前 OpenAPI 未提供的能力
|
## 当前 OpenAPI 未提供的能力
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { unwrapApiResponse, unwrapNullableApiResponse } from '@/utils/api-response'
|
import { unwrapApiResponse, unwrapNullableApiResponse } from '@/utils/api-response'
|
||||||
import { request } from '@/utils/request'
|
import { request } from '@/utils/request'
|
||||||
import type { ApiResponse } from '@/types/common'
|
import type { ApiResponse, PageResult } from '@/types/common'
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
BackendCollection,
|
BackendCollection,
|
||||||
@@ -46,24 +46,54 @@ export function getDepartments(campusId?: string): Promise<DepartmentRecord[]> {
|
|||||||
return Promise.resolve([])
|
return Promise.resolve([])
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = campusId ? { page: 1, size: 200, campusId } : { page: 1, size: 200 }
|
return getDepartmentPage(campusId).then((page) => page.records)
|
||||||
|
}
|
||||||
|
|
||||||
return request
|
async function getDepartmentPage(
|
||||||
.get<ApiResponse<BackendCollection<OrganizationResponseDto>>>('/v1/departments', {
|
campusId: string | undefined,
|
||||||
params,
|
page = 1,
|
||||||
})
|
pageSize = 200,
|
||||||
.then(unwrapApiResponse)
|
): Promise<PageResult<DepartmentRecord>> {
|
||||||
.then((data) =>
|
if (useMockData) {
|
||||||
getRecords(data).map((item) => ({
|
return { records: [], total: 0, page, pageSize }
|
||||||
id: item.id,
|
}
|
||||||
campusId: item.campusId ?? '',
|
|
||||||
parentId: item.parentId,
|
const params: Record<string, string | number> = { page, size: pageSize }
|
||||||
code: item.code ?? item.id,
|
|
||||||
name: item.name ?? item.departmentName ?? item.id,
|
if (campusId) {
|
||||||
status: item.status ?? 'ENABLED',
|
params.campusId = campusId
|
||||||
sortNo: item.sortNo ?? 0,
|
}
|
||||||
})),
|
|
||||||
|
const response = await request.get<ApiResponse<BackendCollection<OrganizationResponseDto>>>(
|
||||||
|
'/v1/departments',
|
||||||
|
{ params },
|
||||||
)
|
)
|
||||||
|
const data = unwrapApiResponse(response)
|
||||||
|
const records = getRecords(data).map(mapDepartment)
|
||||||
|
|
||||||
|
return {
|
||||||
|
records,
|
||||||
|
total: Array.isArray(data) ? records.length : (data.total ?? records.length),
|
||||||
|
page: Array.isArray(data) ? page : (data.page ?? page),
|
||||||
|
pageSize: Array.isArray(data) ? pageSize : (data.size ?? pageSize),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAllDepartments(campusId?: string): Promise<DepartmentRecord[]> {
|
||||||
|
const firstPage = await getDepartmentPage(campusId, 1, 200)
|
||||||
|
const pageCount = Math.ceil(firstPage.total / firstPage.pageSize)
|
||||||
|
|
||||||
|
if (pageCount <= 1) {
|
||||||
|
return firstPage.records
|
||||||
|
}
|
||||||
|
|
||||||
|
const remainingPages = await Promise.all(
|
||||||
|
Array.from({ length: pageCount - 1 }, (_, index) =>
|
||||||
|
getDepartmentPage(campusId, index + 2, firstPage.pageSize),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return [firstPage, ...remainingPages].flatMap((page) => page.records)
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapCampus(data: OrganizationResponseDto): CampusRecord {
|
function mapCampus(data: OrganizationResponseDto): CampusRecord {
|
||||||
|
|||||||
+64
-2
@@ -12,12 +12,16 @@ const props = defineProps<{
|
|||||||
subjects: PermissionSubjectOption[]
|
subjects: PermissionSubjectOption[]
|
||||||
loading: boolean
|
loading: boolean
|
||||||
saving: boolean
|
saving: boolean
|
||||||
|
error: boolean
|
||||||
|
previewUserId: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:selectedTemplateId': [value: string]
|
'update:selectedTemplateId': [value: string]
|
||||||
|
'update:previewUserId': [value: string]
|
||||||
add: [form: TemplatePermissionForm]
|
add: [form: TemplatePermissionForm]
|
||||||
delete: [permissionId: string]
|
delete: [permissionId: string]
|
||||||
|
retry: []
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const form = reactive<TemplatePermissionForm>({
|
const form = reactive<TemplatePermissionForm>({
|
||||||
@@ -48,6 +52,8 @@ const availableSubjects = computed(() =>
|
|||||||
props.subjects.filter((subject) => subject.type === form.subjectType),
|
props.subjects.filter((subject) => subject.type === form.subjectType),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const previewUsers = computed(() => props.subjects.filter((subject) => subject.type === 'USER'))
|
||||||
|
|
||||||
const selectedTemplate = computed(() =>
|
const selectedTemplate = computed(() =>
|
||||||
props.templates.find((template) => template.id === props.selectedTemplateId),
|
props.templates.find((template) => template.id === props.selectedTemplateId),
|
||||||
)
|
)
|
||||||
@@ -56,6 +62,10 @@ function handleTemplateChange(event: Event) {
|
|||||||
emit('update:selectedTemplateId', (event.target as HTMLSelectElement).value)
|
emit('update:selectedTemplateId', (event.target as HTMLSelectElement).value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePreviewUserChange(event: Event) {
|
||||||
|
emit('update:previewUserId', (event.target as HTMLSelectElement).value)
|
||||||
|
}
|
||||||
|
|
||||||
function handleSubjectTypeChange() {
|
function handleSubjectTypeChange() {
|
||||||
form.subjectId = availableSubjects.value[0]?.id ?? ''
|
form.subjectId = availableSubjects.value[0]?.id ?? ''
|
||||||
}
|
}
|
||||||
@@ -105,10 +115,23 @@ watch(
|
|||||||
<span v-if="selectedTemplate" class="template-meta">
|
<span v-if="selectedTemplate" class="template-meta">
|
||||||
{{ selectedTemplate.code || selectedTemplate.id }} · {{ selectedTemplate.category }}
|
{{ selectedTemplate.code || selectedTemplate.id }} · {{ selectedTemplate.category }}
|
||||||
</span>
|
</span>
|
||||||
|
<label class="template-select preview-select">
|
||||||
|
<span>继承预览用户</span>
|
||||||
|
<select :value="previewUserId" :disabled="loading" @change="handlePreviewUserChange">
|
||||||
|
<option value="">当前登录用户</option>
|
||||||
|
<option v-for="user in previewUsers" :key="user.id" :value="user.id">
|
||||||
|
{{ user.label }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="!selectedTemplateId" class="empty-state">暂无模板,请先选择一个模板。</div>
|
<div v-if="!selectedTemplateId" class="empty-state">暂无模板,请先选择一个模板。</div>
|
||||||
<div v-else-if="loading" class="loading-state">正在加载模板权限…</div>
|
<div v-else-if="loading" class="loading-state">正在加载模板权限…</div>
|
||||||
|
<div v-else-if="error" class="error-state">
|
||||||
|
<span>模板权限加载失败</span>
|
||||||
|
<button type="button" class="retry-button" @click="emit('retry')">重新加载</button>
|
||||||
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="permission-list">
|
<div class="permission-list">
|
||||||
<div class="list-heading">
|
<div class="list-heading">
|
||||||
@@ -128,7 +151,18 @@ watch(
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="permission in permissions" :key="permission.id">
|
<tr
|
||||||
|
v-for="permission in permissions"
|
||||||
|
:key="
|
||||||
|
permission.id ??
|
||||||
|
[
|
||||||
|
permission.subjectType,
|
||||||
|
permission.subjectId,
|
||||||
|
permission.permissionLevel,
|
||||||
|
permission.effect,
|
||||||
|
].join('-')
|
||||||
|
"
|
||||||
|
>
|
||||||
<td>
|
<td>
|
||||||
<span class="subject-type">{{ subjectTypeLabels[permission.subjectType] }}</span>
|
<span class="subject-type">{{ subjectTypeLabels[permission.subjectType] }}</span>
|
||||||
{{ formatSubject(permission.subjectType, permission.subjectId) }}
|
{{ formatSubject(permission.subjectType, permission.subjectId) }}
|
||||||
@@ -232,6 +266,10 @@ watch(
|
|||||||
min-width: min(420px, 100%);
|
min-width: min(420px, 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview-select {
|
||||||
|
min-width: min(280px, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 7px 10px;
|
padding: 7px 10px;
|
||||||
@@ -356,13 +394,37 @@ td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.empty-state,
|
.empty-state,
|
||||||
.loading-state {
|
.loading-state,
|
||||||
|
.error-state {
|
||||||
padding: 32px 16px;
|
padding: 32px 16px;
|
||||||
color: var(--mut);
|
color: var(--mut);
|
||||||
font-size: 12.5px;
|
font-size: 12.5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-state {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: var(--err);
|
||||||
|
background: #f8fbfc;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-button {
|
||||||
|
padding: 4px 10px;
|
||||||
|
color: var(--brand);
|
||||||
|
font-size: 12px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid var(--brand);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-button:hover {
|
||||||
|
background: var(--brand-l);
|
||||||
|
}
|
||||||
|
|
||||||
.empty-state.compact {
|
.empty-state.compact {
|
||||||
padding: 18px 12px;
|
padding: 18px 12px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
import { getDepartments } from '@/api/management/organization'
|
import { getAllDepartments } from '@/api/management/organization'
|
||||||
import { getDocuments } from '@/api/management/documents'
|
import { getDocuments } from '@/api/management/documents'
|
||||||
import {
|
import {
|
||||||
createTemplatePermission,
|
createTemplatePermission,
|
||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
isPermissionMockEnabled,
|
isPermissionMockEnabled,
|
||||||
} from '@/api/management/document-permissions'
|
} from '@/api/management/document-permissions'
|
||||||
import { getUsers } from '@/api/management/users'
|
import { getUsers } from '@/api/management/users'
|
||||||
import { getRoleSummaries } from '@/api/management/roles'
|
import { getRoleSummaries, getRoles } from '@/api/management/roles'
|
||||||
import type {
|
import type {
|
||||||
DepartmentRecord,
|
DepartmentRecord,
|
||||||
DocumentRecord,
|
DocumentRecord,
|
||||||
@@ -54,6 +54,7 @@ const templatePermissions = ref<TemplatePermissionRecord[]>([])
|
|||||||
const permissionLoading = ref(false)
|
const permissionLoading = ref(false)
|
||||||
const permissionSaving = ref(false)
|
const permissionSaving = ref(false)
|
||||||
const permissionError = ref(false)
|
const permissionError = ref(false)
|
||||||
|
const permissionPreviewUserId = ref('')
|
||||||
let permissionRequestId = 0
|
let permissionRequestId = 0
|
||||||
|
|
||||||
const selectedTemplate = computed(() =>
|
const selectedTemplate = computed(() =>
|
||||||
@@ -94,14 +95,14 @@ function resolvePermission(
|
|||||||
const hasInheritedDeny = records.some((record) => record.inherited && record.effect === 'DENY')
|
const hasInheritedDeny = records.some((record) => record.inherited && record.effect === 'DENY')
|
||||||
const hasInheritedAllow = records.some((record) => record.inherited && record.effect === 'ALLOW')
|
const hasInheritedAllow = records.some((record) => record.inherited && record.effect === 'ALLOW')
|
||||||
|
|
||||||
if (hasDirectDeny) {
|
|
||||||
return { enabled: false, state: 'direct-deny' }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasInheritedDeny) {
|
if (hasInheritedDeny) {
|
||||||
return { enabled: false, state: 'inherited-deny' }
|
return { enabled: false, state: 'inherited-deny' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasDirectDeny) {
|
||||||
|
return { enabled: false, state: 'direct-deny' }
|
||||||
|
}
|
||||||
|
|
||||||
if (hasDirectAllow) {
|
if (hasDirectAllow) {
|
||||||
return { enabled: true, state: 'direct-allow' }
|
return { enabled: true, state: 'direct-allow' }
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,8 @@ function syncPermissionRows() {
|
|||||||
name: role.name,
|
name: role.name,
|
||||||
color: role.color ?? ['#6b5bd2', '#0e6e8c', '#0f9d6c', '#d9821f'][index % 4],
|
color: role.color ?? ['#6b5bd2', '#0e6e8c', '#0f9d6c', '#d9821f'][index % 4],
|
||||||
description: role.description,
|
description: role.description,
|
||||||
userCount: role.userCount ?? 0,
|
userCount:
|
||||||
|
role.userCount ?? userRecords.value.filter((user) => user.roleIds?.includes(role.id)).length,
|
||||||
...buildPermissionMaps('ROLE', role.id),
|
...buildPermissionMaps('ROLE', role.id),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -143,6 +145,41 @@ function syncPermissionRows() {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getAllTemplatesForPermission() {
|
||||||
|
const firstPage = await getDocuments({ page: 1, pageSize: 200, status: 'all' })
|
||||||
|
const pageCount = Math.ceil(firstPage.total / firstPage.pageSize)
|
||||||
|
|
||||||
|
if (pageCount <= 1) {
|
||||||
|
return firstPage.records
|
||||||
|
}
|
||||||
|
|
||||||
|
const remainingPages = await Promise.all(
|
||||||
|
Array.from({ length: pageCount - 1 }, (_, index) =>
|
||||||
|
getDocuments({ page: index + 2, pageSize: firstPage.pageSize, status: 'all' }),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return [firstPage, ...remainingPages].flatMap((page) => page.records)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRolesForPermission(): Promise<{
|
||||||
|
records: RoleRecord[]
|
||||||
|
usedFallback: boolean
|
||||||
|
}> {
|
||||||
|
try {
|
||||||
|
return { records: await getRoleSummaries(), usedFallback: false }
|
||||||
|
} catch (summaryError) {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
records: await getRoles({ page: 1, pageSize: 200 }),
|
||||||
|
usedFallback: true,
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
throw summaryError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function getAllUsersForPermission() {
|
async function getAllUsersForPermission() {
|
||||||
const firstPage = await getUsers({ page: 1, pageSize: 200, status: 'all' })
|
const firstPage = await getUsers({ page: 1, pageSize: 200, status: 'all' })
|
||||||
const pageCount = Math.ceil(firstPage.total / firstPage.pageSize)
|
const pageCount = Math.ceil(firstPage.total / firstPage.pageSize)
|
||||||
@@ -178,9 +215,9 @@ async function loadPermissions() {
|
|||||||
|
|
||||||
const [templatesResult, rolesResult, departmentsResult, usersResult] = await Promise.allSettled(
|
const [templatesResult, rolesResult, departmentsResult, usersResult] = await Promise.allSettled(
|
||||||
[
|
[
|
||||||
getDocuments({ page: 1, pageSize: 200, status: 'all' }),
|
getAllTemplatesForPermission(),
|
||||||
getRoleSummaries(),
|
getRolesForPermission(),
|
||||||
getDepartments(),
|
getAllDepartments(),
|
||||||
getAllUsersForPermission(),
|
getAllUsersForPermission(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -189,8 +226,8 @@ async function loadPermissions() {
|
|||||||
throw templatesResult.reason
|
throw templatesResult.reason
|
||||||
}
|
}
|
||||||
|
|
||||||
templates.value = templatesResult.value.records
|
templates.value = templatesResult.value
|
||||||
roleRecords.value = rolesResult.status === 'fulfilled' ? rolesResult.value : []
|
roleRecords.value = rolesResult.status === 'fulfilled' ? rolesResult.value.records : []
|
||||||
departmentRecords.value =
|
departmentRecords.value =
|
||||||
departmentsResult.status === 'fulfilled' ? departmentsResult.value : []
|
departmentsResult.status === 'fulfilled' ? departmentsResult.value : []
|
||||||
userRecords.value = usersResult.status === 'fulfilled' ? usersResult.value : []
|
userRecords.value = usersResult.status === 'fulfilled' ? usersResult.value : []
|
||||||
@@ -202,9 +239,17 @@ async function loadPermissions() {
|
|||||||
usersResult.status === 'rejected'
|
usersResult.status === 'rejected'
|
||||||
) {
|
) {
|
||||||
ElMessage.warning('角色、科室或用户列表加载不完整,部分授权对象暂不可配置')
|
ElMessage.warning('角色、科室或用户列表加载不完整,部分授权对象暂不可配置')
|
||||||
|
} else if (rolesResult.value.usedFallback) {
|
||||||
|
ElMessage.warning('角色人数统计接口暂不可用,已回退到角色列表,人数仅按当前用户列表估算')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!userRecords.value.some((user) => user.id === permissionPreviewUserId.value)) {
|
||||||
|
permissionPreviewUserId.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!templates.value.some((template) => template.id === selectedTemplateId.value)) {
|
||||||
selectedTemplateId.value = templates.value[0]?.id ?? ''
|
selectedTemplateId.value = templates.value[0]?.id ?? ''
|
||||||
|
}
|
||||||
await loadTemplatePermissions()
|
await loadTemplatePermissions()
|
||||||
} catch {
|
} catch {
|
||||||
roleRecords.value = []
|
roleRecords.value = []
|
||||||
@@ -228,6 +273,7 @@ async function loadTemplatePermissions() {
|
|||||||
if (!templateId || isPermissionMockEnabled) {
|
if (!templateId || isPermissionMockEnabled) {
|
||||||
templatePermissions.value = []
|
templatePermissions.value = []
|
||||||
permissionError.value = false
|
permissionError.value = false
|
||||||
|
permissionLoading.value = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +281,10 @@ async function loadTemplatePermissions() {
|
|||||||
permissionError.value = false
|
permissionError.value = false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const records = await getTemplatePermissions(templateId)
|
const records = await getTemplatePermissions(
|
||||||
|
templateId,
|
||||||
|
permissionPreviewUserId.value || undefined,
|
||||||
|
)
|
||||||
|
|
||||||
if (requestId !== permissionRequestId || templateId !== selectedTemplateId.value) {
|
if (requestId !== permissionRequestId || templateId !== selectedTemplateId.value) {
|
||||||
return
|
return
|
||||||
@@ -349,7 +398,7 @@ async function setSubjectPermission(
|
|||||||
subjectId: string,
|
subjectId: string,
|
||||||
permission: PermissionKey,
|
permission: PermissionKey,
|
||||||
) {
|
) {
|
||||||
if (!selectedTemplateId.value || permissionSaving.value) {
|
if (!selectedTemplateId.value || permissionSaving.value || permissionError.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +430,7 @@ async function setSubjectPermission(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function addTemplatePermission(form: TemplatePermissionForm) {
|
async function addTemplatePermission(form: TemplatePermissionForm) {
|
||||||
if (!selectedTemplateId.value || permissionSaving.value) {
|
if (!selectedTemplateId.value || permissionSaving.value || permissionError.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +448,7 @@ async function addTemplatePermission(form: TemplatePermissionForm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function removeTemplatePermission(permissionId: string) {
|
async function removeTemplatePermission(permissionId: string) {
|
||||||
if (!selectedTemplateId.value || permissionSaving.value) {
|
if (!selectedTemplateId.value || permissionSaving.value || permissionError.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,6 +475,11 @@ function handlePanelTemplateChange(templateId: string) {
|
|||||||
void loadTemplatePermissions()
|
void loadTemplatePermissions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handlePermissionPreviewUserChange(userId: string) {
|
||||||
|
permissionPreviewUserId.value = userId
|
||||||
|
void loadTemplatePermissions()
|
||||||
|
}
|
||||||
|
|
||||||
function retryTemplatePermissions() {
|
function retryTemplatePermissions() {
|
||||||
void loadTemplatePermissions()
|
void loadTemplatePermissions()
|
||||||
}
|
}
|
||||||
@@ -541,9 +595,13 @@ onMounted(loadPermissions)
|
|||||||
:subjects="templateSubjects"
|
:subjects="templateSubjects"
|
||||||
:loading="permissionLoading"
|
:loading="permissionLoading"
|
||||||
:saving="permissionSaving"
|
:saving="permissionSaving"
|
||||||
|
:error="permissionError"
|
||||||
|
:preview-user-id="permissionPreviewUserId"
|
||||||
@update:selected-template-id="handlePanelTemplateChange"
|
@update:selected-template-id="handlePanelTemplateChange"
|
||||||
|
@update:preview-user-id="handlePermissionPreviewUserChange"
|
||||||
@add="addTemplatePermission"
|
@add="addTemplatePermission"
|
||||||
@delete="removeTemplatePermission"
|
@delete="removeTemplatePermission"
|
||||||
|
@retry="retryTemplatePermissions"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user