Files
vue3-element-admin/src/components/Upload/ImageUpload.vue
2024-07-23 10:43:25 +08:00

215 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 多图上传组件 -->
<template>
<el-upload
v-model:file-list="fileList"
list-type="picture-card"
:class="
fileList.length >= props.limit || !props.showUploadBtn ? 'hide' : 'show'
"
:before-upload="handleBeforeUpload"
:http-request="handleUpload"
:on-remove="handleRemove"
:accept="accept"
:limit="props.limit"
>
<i-ep-plus />
<template #file="{ file }">
<div>
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="previewImg(file)">
<el-icon><zoom-in /></el-icon>
</span>
<span
v-if="props.showDelBtn"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<el-icon><Delete /></el-icon>
</span>
</span>
</div>
</template>
</el-upload>
<el-image-viewer
v-if="viewVisible"
:zoom-rate="1.2"
@close="closePreview"
:initialIndex="initialIndex"
:url-list="viewFileList"
/>
</template>
<script setup lang="ts">
import {
UploadRawFile,
UploadRequestOptions,
UploadUserFile,
UploadFile,
UploadProps,
} from "element-plus";
import FileAPI from "@/api/file";
const emit = defineEmits(["update:modelValue"]);
const props = defineProps({
/**
* 文件路径集合
*/
modelValue: {
type: Array<string>,
default: () => [],
},
/**
* 文件上传数量限制
*/
limit: {
type: Number,
default: 10,
},
/**
* 是否显示删除按钮
*/
showDelBtn: {
type: Boolean,
default: true,
},
/**
* 是否显示上传按钮
*/
showUploadBtn: {
type: Boolean,
default: true,
},
/**
* 单张图片最大大小
*/
uploadMaxSize: {
type: Number,
default: 2 * 1048 * 1048,
},
/**
* 上传文件类型
*/
accept: {
type: String,
default: "image/*",
},
});
const viewVisible = ref(false);
const initialIndex = ref(0);
const fileList = ref([] as UploadUserFile[]);
const viewFileList = ref([] as string[]);
watch(
() => props.modelValue,
(newVal: string[]) => {
const filePaths = fileList.value.map((file) => file.url);
// 监听modelValue文件集合值未变化时跳过赋值
if (
filePaths.length > 0 &&
filePaths.length === newVal.length &&
filePaths.every((x) => newVal.some((y) => y === x)) &&
newVal.every((y) => filePaths.some((x) => x === y))
) {
return;
}
if (newVal.length <= 0) {
fileList.value = [];
return;
}
fileList.value = newVal.map((filePath) => {
return { url: filePath } as UploadUserFile;
});
},
{ immediate: true }
);
/**
* 自定义图片上传
*
* @param options
*/
async function handleUpload(options: UploadRequestOptions): Promise<any> {
// 上传API调用
const data = await FileAPI.upload(options.file);
// 上传成功需手动替换文件路径为远程URL否则图片地址为预览地址 blob:http://
const fileIndex = fileList.value.findIndex(
(file) => file.uid == (options.file as any).uid
);
fileList.value.splice(fileIndex, 1, {
name: data.name,
url: data.url,
} as UploadUserFile);
emit(
"update:modelValue",
fileList.value.map((file) => file.url)
);
}
/**
* 删除图片
*/
function handleRemove(removeFile: UploadFile) {
const filePath = removeFile.url;
if (filePath) {
FileAPI.deleteByPath(filePath).then(() => {
// 删除成功回调
emit(
"update:modelValue",
fileList.value.map((file) => file.url)
);
});
}
}
/**
* 限制用户上传文件的格式和大小
*/
function handleBeforeUpload(file: UploadRawFile) {
if (file.size > props.uploadMaxSize) {
let mUploadMaxSize = props.uploadMaxSize / 1048 / 1048;
ElMessage.warning("上传图片不能大于" + mUploadMaxSize + "M");
return false;
}
return true;
}
/**
* 预览图片
*/
const previewImg: UploadProps["onPreview"] = (uploadFile: UploadFile) => {
viewFileList.value = fileList.value.map((file) => file.url!);
initialIndex.value = fileList.value.findIndex(
(file) => file.url === uploadFile.url
);
viewVisible.value = true;
};
/**
* 关闭预览
*/
const closePreview = () => {
viewVisible.value = false;
};
</script>
<style lang="scss" scoped>
.hide {
:deep(.el-upload--picture-card) {
display: none;
}
}
.show {
:deep(.el-upload--picture-card) {
display: flex;
}
}
</style>