这里写自定义目录标题
- 采用的dom结构是input file,label事件绑定,一下为代码
-
采用的dom结构是input file,label事件绑定,一下为代码
传入参数为uploadNum
<template>
<div class="my-img-upload">
<van-space wrap>
<!-- 图片列表 -->
<div
class="uploader-upload uploader-upload-list"
v-for="(imgItem, index) in imgArr"
:key="index"
>
<label class="uploader-icon-wrap">
<van-icon name="photograph" color="#dcdee0" />
</label>
<div v-if="imgItem.status != 'success'" class="loading-wrap">
<van-loading color="#ffffff" size="22" />
<div class="text">上传中{{ imgItem.progress }}%</div>
</div>
<div class="img-wrap" v-else @click="preImg(index)">
<img :src="imgItem.url" alt="" style="width: 100%" />
<div class="del-icon" @click.stop="delImg(index)">
<van-icon name="cross" size="12px" color="#ffffff" />
</div>
</div>
</div>
<!-- 上传的操作 -->
<div class="uploader-upload">
<label class="uploader-icon-wrap" for="uploader-ipt">
<van-icon name="photograph" color="#dcdee0" />
</label>
<input
type="file"
id="uploader-ipt"
class="uploader-input"
accept="image/*"
@change="changeFileInfo"
/>
</div>
</van-space>
</div>
</template>
<script setup>
import axios from "axios";
import xToast from "@/util/toast.js";
import { showImagePreview } from "vant";
import { ref } from "vue";
const props = defineProps({
uploadNum: {
type: Number,
default() {
return 10;
},
},
});
const imgArr = ref([]);
function preImg(index) {
const imgUrlList = imgArr.value.map((item) => item.url);
showImagePreview({
images: imgUrlList,
startPosition: index,
});
}
function delImg(index) {
imgArr.value.splice(index, 1);
}
function changeFileInfo(e) {
if (imgArr.value.length >= props.uploadNum) {
xToast.show({
type: "error",
content: `最多上传${props.uploadNum}张图片`,
});
return false;
}
const files = e.target.files;
const oFile = files[0];
if (!isImageFile(files[0].name)) {
xToast.show({
type: "error",
content: "请选择图片文件",
time: 3000,
});
return false;
}
let objImage = {
url: URL.createObjectURL(oFile),
name: oFile.name,
status: "uploading",
statusbar: "上传中...",
progress: 0,
};
imgArr.value.push(objImage);
upLoadRequest(oFile);
}
function upLoadRequest(file) {
const dataFile = new FormData();
dataFile.append("file", file);
return new Promise((resolve, reject) => {
axios({
method: "post",
url: "/api/upload",
headers: {
"Content-Type": "multipart/form-data",
},
data: dataFile,
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
imgArr.value[imgArr.value.length - 1].progress = percentCompleted;
},
})
.then((res) => {
if (res.code == 200) {
imgArr.value[imgArr.value.length - 1] = {
progress: 100,
url: res.data.fileId,
status: "success",
message: "上传成功",
};
resolve();
} else {
imgArr.value.splice(imgArr.value.length - 1, 1);
xToast.show({
type: "error",
content: "上传失败",
time: 3000,
});
reject(new Error("上传失败"));
}
})
.catch((error) => {
imgArr.value.splice(imgArr.value.length - 1, 1);
console.error("上传过程中发生错误:", error);
xToast.show({
type: "error",
content: "上传过程中发生错误",
time: 3000,
});
reject(error);
});
});
}
function isImageFile(filename) {
const imageExtensions = [
".jpg",
".jpeg",
".png",
".gif",
".bmp",
".webp",
".svg",
".tiff",
".ico",
];
const extension = filename.split(".").pop().toLowerCase();
return imageExtensions.includes(`.${extension}`);
}
</script>
<style lang="less" scoped>
.my-img-upload {
display: flex;
margin-bottom: 20px;
.uploader-upload {
width: 80px;
height: 80px;
background: #fff;
position: relative;
.img-wrap {
position: absolute;
left: 0;
top: 0;
z-index: 100;
width: 100%;
height: 100%;
font-size: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffffff;
overflow: hidden;
img {
max-width: 100%;
max-height: 100%;
}
.del-icon {
position: absolute;
right: 0;
top: 0;
z-index: 100;
background-color: rgba(0, 0, 0, 0.7);
border-radius: 0 0 0 12px;
width: 15px;
height: 15px;
text-align: right;
}
}
.loading-wrap {
position: absolute;
left: 0;
top: 0;
z-index: 100;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(50, 50, 51, 0.88);
flex-direction: column;
.text {
font-size: 0.32rem;
color: #fff;
margin-top: 4px;
}
}
.uploader-icon-wrap {
position: absolute;
z-index: 10;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.uploader-input {
width: 100%;
opacity: 0;
}
}
}
</style>
实现效果如图
上传中,图片1
上传成功,图片2