按业务模块拆分附件权限

This commit is contained in:
Cheng Zhou
2026-05-28 10:53:00 +08:00
parent d2b41ae454
commit 31fcb7e6f2
7 changed files with 473 additions and 57 deletions
@@ -3,7 +3,7 @@
<div class="header">
<span>{{ headerTitle }}</span>
<AttachmentUploader
v-if="!readonly"
v-if="canCreate"
:study-id="studyId"
:entity-type="entityType"
:entity-id="entityId"
@@ -68,9 +68,10 @@ import { formatFileSize } from "./attachmentUtils";
import { useAuthStore } from "../../store/auth";
import { useStudyStore } from "../../store/study";
import { isSystemAdmin } from "../../utils/roles";
import { usePermission } from "../../utils/permission";
import { listMembers } from "../../api/members";
import { displayDateTime, displayUser, getMemberDisplayName, getUserDisplayName } from "../../utils/display";
import { getAttachmentPermissionKey } from "../../utils/attachmentPermissions";
import { isApiPermissionAllowed } from "../../utils/apiPermissionValue";
import { TEXT } from "../../locales";
const props = defineProps<{
@@ -85,7 +86,6 @@ const attachments = ref<any[]>([]);
const loading = ref(false);
const auth = useAuthStore();
const study = useStudyStore();
const permission = usePermission();
const members = ref<any[]>([]);
const previewVisible = ref(false);
const previewUrl = ref("");
@@ -96,6 +96,20 @@ const previewError = ref("");
const previewLoading = ref(false);
const headerTitle = computed(() => props.title || TEXT.common.labels.attachments);
const currentRolePermissions = computed(() => {
const role = study.currentStudyRole || (study.currentStudy as any)?.role_in_study;
return role ? study.currentPermissions?.[role] : null;
});
const canUseAttachmentPermission = (action: "create" | "read" | "delete") => {
if (isSystemAdmin(auth.user)) return true;
const operationKey = getAttachmentPermissionKey(props.entityType, action);
if (!operationKey) return false;
return isApiPermissionAllowed(currentRolePermissions.value?.[operationKey]);
};
const canCreate = computed(() => !props.readonly && canUseAttachmentPermission("create"));
const load = async () => {
if (!props.studyId || !props.entityId) return;
loading.value = true;
@@ -205,8 +219,7 @@ const preview = (row: any) => {
const canDelete = (row: any) => {
if (props.readonly) return false;
const action = props.entityType === "knowledge_note" ? "shared.library.write" : "file.attachment.delete";
return isSystemAdmin(auth.user) || permission.can(action);
return canUseAttachmentPermission("delete");
};
const remove = async (row: any) => {
@@ -7,6 +7,7 @@
<div v-if="group.description" class="group-desc">{{ group.description }}</div>
</div>
<el-upload
v-if="canCreate"
:http-request="(options: any) => doUpload(group.key, options)"
:show-file-list="false"
:limit="1"
@@ -77,16 +78,17 @@
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, watch } from "vue";
import { computed, onMounted, reactive, ref, watch } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { fetchAttachments, uploadAttachment, deleteAttachment } from "../../api/attachments";
import { listMembers } from "../../api/members";
import { useAuthStore } from "../../store/auth";
import { useStudyStore } from "../../store/study";
import { isSystemAdmin } from "../../utils/roles";
import { usePermission } from "../../utils/permission";
import { formatFileSize } from "../attachments/attachmentUtils";
import { displayUser, getMemberDisplayName, getUserDisplayName } from "../../utils/display";
import { getAttachmentPermissionKey } from "../../utils/attachmentPermissions";
import { isApiPermissionAllowed } from "../../utils/apiPermissionValue";
import StateEmpty from "../StateEmpty.vue";
import StateLoading from "../StateLoading.vue";
import { TEXT } from "../../locales";
@@ -111,7 +113,6 @@ const grouped = reactive<Record<string, any[]>>({});
const progressMap = reactive<Record<string, number>>({});
const auth = useAuthStore();
const study = useStudyStore();
const permission = usePermission();
const members = ref<any[]>([]);
const previewVisible = ref(false);
const previewUrl = ref("");
@@ -123,6 +124,20 @@ const previewLoading = ref(false);
const isUploading = (key: string) => (progressMap[key] || 0) > 0 && (progressMap[key] || 0) < 100;
const currentRolePermissions = computed(() => {
const role = study.currentStudyRole || (study.currentStudy as any)?.role_in_study;
return role ? study.currentPermissions?.[role] : null;
});
const canUseAttachmentPermission = (action: "create" | "read" | "delete") => {
if (isSystemAdmin(auth.user)) return true;
const operationKey = getAttachmentPermissionKey(`${props.entityType}_contract`, action);
if (!operationKey) return false;
return isApiPermissionAllowed(currentRolePermissions.value?.[operationKey]);
};
const canCreate = computed(() => !props.readonly && canUseAttachmentPermission("create"));
const loadMembers = async () => {
const studyId = study.currentStudy?.id;
if (!studyId) return;
@@ -271,7 +286,7 @@ const download = (row: any) => {
const canDelete = (row: any) => {
if (props.readonly) return false;
return isSystemAdmin(auth.user) || permission.can("fees.attachment.delete");
return canUseAttachmentPermission("delete");
};
const remove = async (row: any) => {