policeSecurity/securityManagement/src/components/upload/SingleImageFileUpload.vue

130 lines
3.2 KiB
Vue
Raw Normal View History

2024-08-30 18:01:34 +08:00
<template>
<div class="simpleUploadDiv">
2025-01-03 11:36:46 +08:00
<a-progress v-if="uploading" type="circle" :percent="percent" />
2024-08-30 18:01:34 +08:00
<a-image
2025-01-03 11:36:46 +08:00
height="80%"
v-else
:src="minioBaseUrl + modelValue"
alt="avatar"
/>
2024-11-05 14:30:18 +08:00
2024-08-30 18:01:34 +08:00
<a-button class="btn-success" @click="selectFile">{{ btnLabel }}</a-button>
2025-01-03 11:36:46 +08:00
<input :id="id" type="file" style="display: none" ref="fileInput" />
2024-08-30 18:01:34 +08:00
</div>
</template>
<script setup lang="ts">
2025-01-03 11:36:46 +08:00
import { message } from "ant-design-vue";
import { onMounted, onUnmounted, ref } from "vue";
import {
generateSimpleObjectName,
getResignedObjectUrl,
} from "@/utils/minioUtil";
import axios, { CancelTokenSource } from "axios";
import { convertFileSizeToStr } from "@/utils/index.ts";
2024-08-30 18:01:34 +08:00
2025-01-03 11:36:46 +08:00
const minioBaseUrl = __APP_ENV.VITE_APP_MINIO_URL;
2024-08-30 18:01:34 +08:00
2025-01-03 11:36:46 +08:00
const modelValue = defineModel<string>("value");
const props = withDefaults(
defineProps<{
parentDir?: string;
allowedExtensions?: string[];
maxSize?: number;
width?: string | number;
height?: string | number;
btnLabel?: string;
id: string;
}>(),
{
parentDir: "",
allowedExtensions: () => ["jpg", "jpeg", "png", "gif"],
maxSize: 1024 * 1024 * 4,
width: "150px",
height: "150px",
btnLabel: "选择图片",
id: "myFileInput",
}
);
2024-08-30 18:01:34 +08:00
2025-01-03 11:36:46 +08:00
const uploading = ref(false);
const percent = ref(0);
let cancelToken: CancelTokenSource | null = null;
const uploadUrl = ref();
2024-09-11 09:22:00 +08:00
const fileInput = ref(null);
2024-08-30 18:01:34 +08:00
const selectFile = () => {
2025-01-03 11:36:46 +08:00
document.getElementById(props.id)?.click();
};
2024-08-30 18:01:34 +08:00
async function inputFileListener(this: HTMLInputElement) {
const selectedFile: File = this.files?.[0] as File;
2025-01-03 11:36:46 +08:00
const fileExtension = selectedFile.name
?.split(".")
.pop()
.toLowerCase() as string;
2024-08-30 18:01:34 +08:00
if (!props.allowedExtensions.includes(fileExtension)) {
2025-01-03 11:36:46 +08:00
return message.error(
`错误:不支持的文件格式,目前支持:【${props.allowedExtensions}`
);
2024-08-30 18:01:34 +08:00
}
const isMax = selectedFile.size > props.maxSize;
if (isMax) {
2025-01-03 11:36:46 +08:00
return message.error(
`文件大小超出限制,最大支持:【${convertFileSizeToStr(props.maxSize)}`
);
2024-08-30 18:01:34 +08:00
}
cancelToken?.cancel();
percent.value = 0;
uploading.value = true;
2025-01-03 11:36:46 +08:00
const objectName = generateSimpleObjectName(
selectedFile.name,
props.parentDir
);
uploadUrl.value = await getResignedObjectUrl(
__APP_ENV.VITE_APP_MINIO_BUCKET,
objectName
);
cancelToken = axios.CancelToken.source();
2024-09-11 09:22:00 +08:00
await axios.put(uploadUrl.value, selectedFile, {
2024-08-30 18:01:34 +08:00
cancelToken: cancelToken.token,
onUploadProgress: (progressEvent) => {
2025-01-03 11:36:46 +08:00
percent.value =
((progressEvent.loaded / (progressEvent.total as number)) * 100) | 0;
},
});
modelValue.value = "/" + __APP_ENV.VITE_APP_MINIO_BUCKET + objectName;
2024-08-30 18:01:34 +08:00
uploading.value = false;
}
2025-01-03 11:36:46 +08:00
const fileDelete = () => {
uploadUrl.value = "";
fileInput.value.value = "";
modelValue.value = "";
};
2024-08-30 18:01:34 +08:00
onMounted(() => {
2025-01-03 11:36:46 +08:00
document
.getElementById(props.id)
?.addEventListener("change", inputFileListener);
});
2024-08-30 18:01:34 +08:00
onUnmounted(() => {
2025-01-03 11:36:46 +08:00
document
.getElementById(props.id)
?.removeEventListener("change", inputFileListener);
});
defineExpose({ fileDelete });
2024-08-30 18:01:34 +08:00
</script>
<style scoped lang="scss">
.simpleUploadDiv {
width: v-bind(width);
height: v-bind(height);
display: flex;
flex-direction: column;
}
</style>