Files
ctms/frontend/src/components/attachments/AttachmentUploader.vue
T
2026-01-12 11:14:04 +08:00

69 lines
1.7 KiB
Vue

<template>
<div class="uploader">
<el-upload
:http-request="doUpload"
:show-file-list="false"
:limit="1"
:disabled="loading"
:auto-upload="true"
>
<el-button type="primary" :loading="loading">{{ TEXT.common.actions.upload }}</el-button>
</el-upload>
<el-progress v-if="progress > 0 && progress < 100" :percentage="progress" :stroke-width="6" />
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { uploadAttachment } from "../../api/attachments";
import { TEXT } from "../../locales";
const props = defineProps<{
studyId: string;
entityType: string;
entityId: string;
maxSizeMb?: number;
}>();
const emit = defineEmits(["uploaded"]);
const progress = ref(0);
const loading = ref(false);
const maxSize = props.maxSizeMb ?? 50;
const doUpload = async (options: any) => {
const file: File = options.file;
if (!file) return;
if (file.size > maxSize * 1024 * 1024) {
ElMessage.error(`${TEXT.common.messages.fileTooLarge} ${maxSize}MB`);
return;
}
progress.value = 0;
loading.value = true;
try {
await uploadAttachment(props.studyId, props.entityType, props.entityId, file, {
onUploadProgress: (evt: ProgressEvent) => {
if (evt.total) {
progress.value = Math.round((evt.loaded / evt.total) * 100);
}
},
});
ElMessage.success(TEXT.common.messages.uploadSuccess);
emit("uploaded");
} catch (e: any) {
ElMessage.error(e?.response?.data?.message || TEXT.common.messages.uploadFailed);
} finally {
progress.value = 0;
loading.value = false;
}
};
</script>
<style scoped>
.uploader {
display: flex;
gap: 8px;
align-items: center;
}
</style>