<template> <div class="upload-file"> <el-upload multiple :action="uploadFileUrl" :before-upload="handleBeforeUpload" :file-list="fileList" :limit="limit" :disabled="disabled" :on-error="handleUploadError" :on-exceed="handleExceed" :on-success="handleUploadSuccess" :show-file-list="false" :headers="headers" class="upload-file-uploader" ref="upload"> <!-- 上传按钮 --> <el-button size="mini" type="primary" :disabled="disabled">{{ $t("选取文件") }}</el-button> <!-- 上传提示 --> <div class="el-upload__tip" slot="tip" v-if="showTip"> 请上传 <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template> <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template> 的文件 </div> </el-upload> <!-- 文件列表 --> <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> <li :key="index" v-for="(file, index) in fileList"> <div class="imgItem" v-if="checkFileIsImage(file.url)"> <el-image style="width: 200px; height: 100px" :src="file.url" :preview-src-list="[file.url]"> </el-image> <div class="ele-upload-list__item-content-action"> <el-button size="mini" type="danger" :disabled="disabled" @click="handleDelete(index)">删除</el-button> </div> </div> <div class="el-upload-list__item ele-upload-list__item-content" v-else> <el-link :href="`${file.url}`" :underline="false" target="_blank"> <span class="el-icon-document"> {{ getFileName(file.name) }} </span> </el-link> <div class="ele-upload-list__item-content-action"> <el-button size="mini" type="danger" :disabled="disabled" @click="handleDelete(index)">删除</el-button> </div> </div> </li> </transition-group> </div> </template> <script> import { getToken } from "@/utils/auth" export default { name: "FileUpload", props: { // 值 value: [String, Object, Array], // 数量限制 limit: { type: Number, default: 5 }, // 大小限制(MB) fileSize: { type: Number, default: 5 }, // 文件类型, 例如['png', 'jpg', 'jpeg'] fileType: { type: Array, default: () => ["doc", "xls", "ppt", "txt", "pdf"] }, disabled: { type: Boolean, default: false }, // 是否显示提示 isShowTip: { type: Boolean, default: true } }, data() { return { number: 0, uploadList: [], baseUrl: process.env.VUE_APP_BASE_API, uploadFileUrl: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 上传的文件服务器地址 headers: { Authorization: "Bearer " + getToken() }, fileList: [] } }, watch: { value: { handler(val) { if (val) { let temp = 1 // 首先将值转为数组 const list = Array.isArray(val) ? val : this.value.split(",") // 然后将数组转为对象数组 this.fileList = list.map((item) => { if (typeof item === "string") { item = { name: item, url: item } } item.uid = item.uid || new Date().getTime() + temp++ return item }) } else { this.fileList = [] return [] } }, deep: true, immediate: true } }, computed: { // 是否显示提示 showTip() { return this.isShowTip && (this.fileType || this.fileSize) } }, methods: { // 上传前校检格式和大小 handleBeforeUpload(file) { // 校检文件类型 if (this.fileType) { let fileExtension = "" if (file.name.lastIndexOf(".") > -1) { fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1).toLowerCase() } const isTypeOk = this.fileType.some((type) => { if (file.type.indexOf(type) > -1) return true if (fileExtension && fileExtension.indexOf(type) > -1) return true return false }) if (!isTypeOk) { 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++ return true }, // 文件个数超出 handleExceed() { this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`) }, // 上传失败 handleUploadError(err) { this.$modal.msgError("上传文件失败,请重试") this.$modal.closeLoading() }, // 上传成功回调 handleUploadSuccess(res) { // todo 接口返回值没有文件名 this.uploadList.push({ name: res.data, 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() } }, // 删除文件 handleDelete(index) { this.fileList.splice(index, 1) this.$emit("input", this.listToString(this.fileList)) }, // 获取文件名称 getFileName(name) { if (name.lastIndexOf("/") > -1) { return name.slice(name.lastIndexOf("/") + 1) } else { return "" } }, // 对象转成指定字符串分隔 listToString(list, separator) { let strs = "" separator = separator || "," for (let i in list) { strs += list[i].url + separator } return strs != "" ? strs.substr(0, strs.length - 1) : "" }, checkFileIsImage(filePath) { const fileExtension = filePath.slice(filePath.lastIndexOf(".") + 1).toLowerCase() const fileTypes = ["png", "jpg", "jpeg", "gif"] if (fileTypes.includes(fileExtension)) { return true } return false } } } </script> <style scoped lang="scss"> .upload-file-uploader { margin-bottom: 5px; } .upload-file-list .el-upload-list__item { border: 1px solid #e4e7ed; line-height: 2; margin-bottom: 10px; position: relative; } .upload-file-list .ele-upload-list__item-content { display: flex; justify-content: space-between; align-items: center; color: inherit; } .ele-upload-list__item-content-action .el-link { margin-right: 10px; } .imgItem { display: flex; align-items: center; } </style>