feat(documents): refresh detail pages and attachment cards
This commit is contained in:
@@ -55,19 +55,28 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<div v-else class="upload-grid">
|
||||
<div v-for="group in uploadGroups" :key="group.key" class="attachment-upload-card">
|
||||
<div v-if="showUploadCardLabels" class="upload-card-label">{{ group.label }}</div>
|
||||
<div v-else class="upload-grid" :class="{ 'upload-grid--three': uploadCardColumns === 3 }">
|
||||
<div v-for="group in uploadGroups" :key="group.key" class="attachment-upload-item">
|
||||
<el-upload
|
||||
class="attachment-card-upload"
|
||||
:show-file-list="false"
|
||||
multiple
|
||||
:disabled="!canUploadGroup(group) || isUploading(group.key)"
|
||||
:auto-upload="false"
|
||||
:on-change="(file: any) => queuePendingUpload(group.key, file)"
|
||||
>
|
||||
<div class="upload-trigger" :class="{ 'is-disabled': !canUploadGroup(group) }">
|
||||
<el-icon class="upload-icon"><Document /></el-icon>
|
||||
<span class="upload-text">点击上传文件</span>
|
||||
<div
|
||||
class="attachment-upload-card"
|
||||
:class="{
|
||||
'is-disabled': !canUploadGroup(group),
|
||||
'attachment-upload-card--centered': centerUploadCardContent,
|
||||
}"
|
||||
>
|
||||
<div v-if="showUploadCardLabels" class="upload-card-label">{{ group.label }}</div>
|
||||
<div class="upload-trigger">
|
||||
<el-icon class="upload-icon"><UploadFilled /></el-icon>
|
||||
<span class="upload-text">{{ group.uploadText || "点击上传文件" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div v-if="pendingMap[group.key]?.length" class="pending-list">
|
||||
@@ -112,7 +121,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Document } from "@element-plus/icons-vue";
|
||||
import { UploadFilled } from "@element-plus/icons-vue";
|
||||
import { fetchAttachments, deleteAttachment, uploadAttachment } from "../../api/attachments";
|
||||
import { formatFileSize } from "./attachmentUtils";
|
||||
import { useAuthStore } from "../../store/auth";
|
||||
@@ -126,12 +135,14 @@ import { TEXT } from "../../locales";
|
||||
type AttachmentEntityGroup = {
|
||||
entityType: string;
|
||||
label: string;
|
||||
uploadText?: string;
|
||||
};
|
||||
|
||||
type UploadGroup = {
|
||||
key: string;
|
||||
label: string;
|
||||
entityType: string;
|
||||
uploadText?: string;
|
||||
};
|
||||
|
||||
type PendingUploadStatus = "pending" | "uploading" | "failed";
|
||||
@@ -153,6 +164,9 @@ const props = defineProps<{
|
||||
mode?: "table" | "upload";
|
||||
maxSizeMb?: number;
|
||||
refreshKey?: number;
|
||||
hideUploadCardLabels?: boolean;
|
||||
centerUploadCardContent?: boolean;
|
||||
uploadCardColumns?: 2 | 3;
|
||||
}>();
|
||||
|
||||
const attachments = ref<any[]>([]);
|
||||
@@ -178,11 +192,13 @@ const uploadGroups = computed<UploadGroup[]>(() => {
|
||||
key: group.entityType,
|
||||
label: group.label,
|
||||
entityType: group.entityType,
|
||||
uploadText: group.uploadText,
|
||||
}));
|
||||
}
|
||||
return [{ key: props.entityType, label: headerTitle.value, entityType: props.entityType }];
|
||||
});
|
||||
const showUploadCardLabels = computed(() => uploadGroups.value.length > 1);
|
||||
const showUploadCardLabels = computed(() => !props.hideUploadCardLabels && uploadGroups.value.length > 1);
|
||||
const uploadCardColumns = computed(() => props.uploadCardColumns || 2);
|
||||
|
||||
const currentRolePermissions = computed(() => {
|
||||
const role = study.currentStudyRole || (study.currentStudy as any)?.role_in_study;
|
||||
@@ -494,20 +510,64 @@ defineExpose({
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.upload-grid--three {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.attachment-upload-item {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.attachment-card-upload,
|
||||
.attachment-card-upload :deep(.el-upload) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.attachment-upload-card {
|
||||
min-height: 72px;
|
||||
padding: 14px 16px;
|
||||
border: 1px dashed #d0dced;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
transition: border-color 0.2s ease, background-color 0.2s ease;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.attachment-upload-card:hover {
|
||||
.attachment-upload-card:hover,
|
||||
.attachment-upload-card:focus-within {
|
||||
border-color: var(--ctms-primary);
|
||||
background: #f8faff;
|
||||
}
|
||||
|
||||
.attachment-upload-card.is-disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.62;
|
||||
}
|
||||
|
||||
.attachment-upload-card--centered {
|
||||
min-height: 112px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.attachment-upload-card--centered .upload-card-label {
|
||||
align-self: flex-start;
|
||||
margin-bottom: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.attachment-upload-card--centered .upload-trigger {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.upload-card-label {
|
||||
margin-bottom: 10px;
|
||||
color: #4a6283;
|
||||
@@ -520,25 +580,22 @@ defineExpose({
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-height: 34px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.upload-trigger.is-disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.62;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 18px;
|
||||
font-size: 22px;
|
||||
line-height: 1;
|
||||
color: #314a6b;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
color: var(--ctms-text-secondary);
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.upload-trigger:not(.is-disabled):hover .upload-text {
|
||||
.attachment-upload-card:not(.is-disabled):hover .upload-text,
|
||||
.attachment-upload-card:not(.is-disabled):hover .upload-icon {
|
||||
color: var(--ctms-primary);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user