zy-vue-library/components/upload/index.vue

151 lines
4.6 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<el-upload
ref="uploadRef"
style="width: 100%"
:file-list="modelValue"
:action="action"
multiple
:limit="limit"
:list-type="listType"
:auto-upload="autoUpload"
:disabled="disabled"
:accept="accept"
:on-remove="onRemove"
:before-remove="beforeRemove"
:on-change="onChange"
:on-exceed="onExceed"
:on-preview="onPreview"
:http-request="httpRequest"
:show-file-list="showFileList"
:class="{ hide: modelValue.length === limit }"
>
<el-icon v-if="listType === 'picture-card'" size="32"><plus /></el-icon>
<el-button v-else type="primary">点击选择文件上传</el-button>
<template #tip>
<div class="mt-10 text-red">
<slot name="tip">
<div>{{ tip.join("") }}。</div>
</slot>
</div>
</template>
</el-upload>
<el-dialog v-model="visible" title="查看图片">
<img :src="imageUrl" alt="Preview Image" style="width: 100%; object-fit: scale-down" />
</el-dialog>
</template>
<script setup>
import { computed, ref, useTemplateRef } from "vue";
import { ElMessage, ElMessageBox, ElUpload, ElIcon, ElButton, ElDialog } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import "element-plus/es/components/upload/style/css";
import "element-plus/es/components/icon/style/css";
import "element-plus/es/components/button/style/css";
import "element-plus/es/components/dialog/style/css";
defineOptions({
name: "AppUpload",
});
const props = defineProps({
autoUpload: { type: Boolean, default: false },
action: { type: String, default: "" },
limit: { type: Number, default: 1 },
listType: { type: String, default: "text" },
accept: { type: String, default: "" },
ratio: { type: String, default: "" },
disabled: { type: Boolean, default: false },
deleteToServer: { type: Boolean, default: false },
showFileList: { type: Boolean, default: true },
httpRequest: { type: Function },
size: { type: Number, default: 0 },
beforeRemove: { type: Function, default: () => {} },
});
const visible = ref(false);
const imageUrl = ref("");
const modelValue = defineModel({ type: Array, required: true });
const deleteFiles = defineModel("deleteFiles", {
type: Array,
default: () => [],
});
const emits = defineEmits(["preview", "delete"]);
const uploadRef = useTemplateRef("uploadRef");
const tip = computed(() =>
[
`最多上传${props.limit}个文件`,
props.accept
? `并且只能上传${props.accept
.replaceAll(".", "")
.split(",")
.join("、")}格式的文件`
: "可以上传任意格式的文件",
props.size ? `文件大小不能超过${props.size}M` : "",
props.ratio ? `只能上传${props.ratio}分辨率的图片` : "",
].filter(Boolean)
);
const onExceed = () => {
ElMessage.warning(`最多上传${props.limit}个文件`);
};
const beforeRemove = async (uploadFile) => {
if (props.deleteToServer && uploadFile.imgFilesId) {
await ElMessageBox.confirm("确定要删除吗?", {
type: "warning",
});
await props.beforeRemove(uploadFile);
}
};
const onRemove = (uploadFile, uploadFiles) => {
modelValue.value = uploadFiles;
deleteFiles.value.push(uploadFile);
emits("delete", uploadFile);
};
const onChange = (uploadFile, uploadFiles) => {
const accept = props.accept && props.accept.split(",");
const ratio = props.ratio && props.ratio.split("*");
const suffix = uploadFile.raw.name.substring(
uploadFile.raw.name.lastIndexOf("."),
uploadFile.raw.name.length
);
const size = props.size * 1024 * 1024;
if (ratio) {
const img = new Image();
img.src = uploadFile.url;
img.onload = () => {
if (img.width !== +ratio[0] && img.height !== +ratio[1]) {
ElMessage.warning(`只能上传${props.ratio}分辨率的图片`);
uploadRef.value.handleRemove(uploadFile.raw);
}
};
}
if (size) {
if (uploadFile.size > size) {
ElMessage.warning(`文件大小不能超过${props.size}M`);
uploadRef.value.handleRemove(uploadFile.raw);
}
}
if (accept) {
if (accept.includes(suffix)) {
modelValue.value = uploadFiles;
} else {
ElMessage.warning(`只能上传${props.accept}格式的文件`);
uploadRef.value.handleRemove(uploadFile.raw);
}
} else {
modelValue.value = uploadFiles;
}
};
const onPreview = (uploadFile) => {
if (props.listType === "picture-card") {
visible.value = true;
imageUrl.value = uploadFile.url;
} else {
emits("preview", uploadFile);
}
};
</script>
<style scoped lang="scss">
.hide :deep(.el-upload--picture-card) {
display: none;
}
</style>