<template> <div class="component-upload-image"> <div style="display: flex;flex-wrap: wrap "> <div v-for="(item, index) in fileList " :key="index" style="height: 148px; width:148px; margin:5px 10px;position: relative;box-sizing: border-box;"> <el-image @click="dialogImageUrl = item.url; dialogVisible = true; " style="height: 148px; width:148px;" fit="fit" :src="item.url"> <video controls width="148px" height="148px" slot="error" :src="item.url" ></video> </el-image> <div @click="handleRemove(index)" class="el-icon-error" style="font-size: 25px;cursor: pointer;position: absolute;right: -10px; top: -10px" ></div> </div> <div> <el-upload multiple :action="uploadImgUrl" list-type="picture-card" :on-success="handleUploadSuccess" :before-upload="handleBeforeUpload" :on-error="handleUploadError" name="file" :show-file-list="false" :headers="headers" :on-preview="handlePictureCardPreview" > <i class="el-icon-plus"></i> </el-upload> <!-- 上传提示 --> <div class="el-upload__tip" slot="tip" v-if="showTip"> 请上传 <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template> <br> <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template> 的文件 </div> </div> </div> <el-dialog :visible.sync="dialogVisible" title="预览" width="800" append-to-body > <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" /> </el-dialog> </div> </template> <script> import { getToken } from "@/utils/auth"; export default { props: { value: [Array], // 大小限制(MB) fileSize: { type: Number, default: 30, }, // 文件类型, 例如['png', 'jpg', 'jpeg'] fileType: { type: Array, default: () => ["png", "jpg", "jpeg" ,"mp4","m4v" ], }, // 是否显示提示 isShowTip: { type: Boolean, default: true } }, data() { return { number: 0, uploadList: [], dialogImageUrl: "", dialogVisible: false, hideUpload: false, baseUrl: process.env.VUE_APP_BASE_API, uploadImgUrl: process.env.VUE_APP_BASE_API + "/app-api/file/upload", // 上传的图片服务器地址 headers: { Authorization: "Bearer " + getToken(), }, fileList: [], }; }, watch: { value: { handler(val) { if (val) { // 首先将值转为数组 const list = Array.isArray(val) ? val : this.value.split(','); // 然后将数组转为对象数组 this.fileList = list.map(item => { if (typeof item === "string") { if (item.indexOf(this.baseUrl) === -1) { item = { name: item, url: item }; } else { item = { name: item, url: item }; } } return item; }); } else { this.fileList = []; return []; } }, deep: true, immediate: true, } }, computed: { // 是否显示提示 showTip() { return this.isShowTip && (this.fileType || this.fileSize); }, }, methods: { // 删除图片 handleRemove(index) { this.fileList.splice(index, 1); this.$emit("input", this.listToString(this.fileList)); }, // 上传成功回调 handleUploadSuccess(res) { if(res.code === 0){ this.uploadList.push({ name: res.data.split('/').pop(), url: res.data }); if (this.uploadList.length === this.number) { this.fileList = this.fileList.concat(this.uploadList); this.uploadList = []; this.number = 0; this.$emit("input", this.listToString(this.fileList)); this.$modal.closeLoading(); } }else { this.handleUploadError(); } }, // 上传前loading加载 handleBeforeUpload(file) { let isImg = false; if (this.fileType.length) { let fileExtension = ""; if (file.name.lastIndexOf(".") > -1) { fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); } isImg = this.fileType.some(type => { if (file.type.indexOf(type) > -1) return true; if (fileExtension && fileExtension.indexOf(type) > -1) return true; return false; }); } else { isImg = file.type.indexOf("image") > -1; } if (!isImg) { this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}的图片或视频文件!`); return false; } if (this.fileSize) { const isLt = file.size / 1024 / 1024 < this.fileSize; if (!isLt) { this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`); return false; } } this.$modal.loading("正在上传图片或视频,请稍候..."); this.number++; }, // 上传失败 handleUploadError() { this.$modal.msgError("上传图片或视频失败,请重试"); this.$modal.closeLoading(); }, // 预览 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, // 对象转成指定字符串分隔 listToString(list) { return list.map(e => e.url); } } }; </script> <style scoped lang="scss"> // .el-upload--picture-card 控制加号部分 ::v-deep.hide .el-upload--picture-card { display: none; } // 去掉动画效果 ::v-deep .el-list-enter-active, ::v-deep .el-list-leave-active { transition: all 0s; } ::v-deep .el-list-enter, .el-list-leave-active { opacity: 0; transform: translateY(0); } </style>