vue-图片/视频上传组件封装
封装代码:
<!-- * @Descripttion:上传组件--> <template> <div class='YxkUpload'> <div :class="[{ 'YxkUpload__slot': dataBind.isSlot}]"> <el-upload :before-upload="beforeUpload" :on-exceed="onExceed" :on-error="onError" :on-success="onSuccess" :on-remove="onRemove" v-bind="dataBind"> <i class="el-icon-plus"></i> <slot></slot> <slot name="tip"></slot> <slot name="trigger"></slot> </el-upload> </div> </div> </template> <script> import Bucket from '../../api/modules/Qiniu/Bucket' import QiniuBucket from '../../api/modules/Qiniu/QiniuConstant' export default { name: 'YxkUpload', componentName: 'YxkUpload', props: { url: { type: String, default: '' }, bucket: { type: String, default: '' }, uploadObj: { type: Object } }, components: {}, data() { return { dataBind: {}, // 上传参数 isSuccess: true, // 符合上传规则 number: 0, // 上传数量 times: 0 // 防止多文件上传失败 } }, methods: { // 上传成功后数据处理 changeUrl(file, fileList) { let urlObj = { file: {}, // 当前上传文件数据 fileList: [], // 上传文件所有数据 originName: [], // 原文件名称 convertName: [], // 私有化文件名 uploadUrl: [], // 可视化文件数据 } urlObj.file = file fileList.forEach(item => { let key = item.response || '' let imageUrl = key ? `${this.dataBind.linkUrl}${key.key}` : item.url urlObj.originName.push(item.name ? item.name.slice(0, item.name.lastIndexOf('.')) : '') urlObj.fileList.push(item) urlObj.convertName.push(key.key) urlObj.uploadUrl.push({ name: key.key, url: imageUrl, }) }) this.clearFileSet() this.$emit('change', urlObj) }, // 上传前校验 beforeUpload(file) { // 文件类型校验 if (this.dataBind.acceptArr.indexOf(file.type) == -1) { this.$message.error(`只能是${this.dataBind.accept}格式`) this.backTop() return false } // 文件大小判断 const isLt = file.size / 1024 / 1024 < this.dataBind.size if (!isLt) { const show = this.dataBind.size < 1 ? `${this.dataBind.size * 1024}KB` : `${this.dataBind.size}MB` this.$message.error(`大小不能超过 ${show}!`); this.backTop() return false } // 文件尺寸大小判断 if (this.dataBind.imgSize) { let isSize = true const {isRange, width, height} = this.dataBind.imgSize const imgRule = new Promise((resolve, reject) => { const img = new Image() const _URL = window.URL || window.webkitURl img.onload = () => { file.width = img.width file.height = img.height const isValid = isRange ? (img.width <= width && img.height <= height) : (img.width == width && img.height == height); isValid ? resolve(file) : reject(); } img.src = _URL.createObjectURL(file) }).then(file => { isSize = true this.setPathName(file) return file }, () => { this.$message.error(`上传图片尺寸必须为${width}*${height}!`) this.backTop() isSize = false return Promise.reject() }).finally(() => { this.isSuccess = isSize }) return imgRule } else { this.setPathName(file) } }, // 文件数目超出 onExceed() { this.$message.error(`当前限制 ${this.dataBind.limit} 数量,如需更换,请删除其它再重新选择!`) this.backTop() }, // 上传失败 onError(err, file, fileList) { this.dataBind.pathName = this.uploadObj.pathName // 防止token失效 this.getQiNiu() this.$message.error(`上传出错,重新上传或刷新页面试试!Error:${err}`) this.backTop() this.$emit('onError', {err: err, file: file, fileList: fileList}) }, // 上传成功 onSuccess(res, file, fileList) { this.times += 1 if (this.times != fileList.length - this.number) { // 防止多文件上传失败 return false } else { this.times = 0 this.number = fileList.length } this.isSuccess && this.changeUrl(file, fileList) }, // 文件删除 onRemove(file, fileList) { if (file && file.status === "success") { this.number = fileList.length this.changeUrl(file, fileList); this.$emit('onRemove', {file: file, fileList: fileList}) } }, // 文件类型 fileTypeSet() { let acceptArr = this.dataBind.accept.split(',') this.dataBind.acceptArr = [] acceptArr.forEach(item => { switch (item) { case '.png': this.dataBind.acceptArr.push('image/png') break; case '.jpg': this.dataBind.acceptArr.push('image/jpg', 'image/jpeg') break; case '.gif': this.dataBind.acceptArr.push('image/gif') break; case '.mp4': this.dataBind.acceptArr.push('video/mp4') break; case '.pdf': this.dataBind.acceptArr.push('application/pdf') break; case '.xls': this.dataBind.acceptArr.push('application/vnd.ms-excel') break; case '.xlsx': this.dataBind.acceptArr.push('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') break; case '.doc': this.dataBind.acceptArr.push('application/msword') break; case '.docx': this.dataBind.acceptArr.push('application/vnd.openxmlformats-officedocument.wordprocessingml.document') break; } }) }, // 设置文件存储 setPathName(file) { let pathName = `${this.dataBind.pathName}`//获取文件后缀 let suffix = file.name.substring(file.name.lastIndexOf("."), file.name.length)// 设置存储到七牛云文件名称 let fileName = new Date().getTime(); // 时间戳 this.dataBind.data.key = `${pathName}${fileName + suffix}`; // 文件夹/文件名称/时间戳/.格式 }, // 其它参数设置 paramsSet() { // 是否含有插槽 this.dataBind.isSlot = this.$slots.default if (this.dataBind.isSlot) { this.dataBind['show-file-list'] = false } // 初始化多文件上传 if(this.dataBind['file-list']) { this.number = this.dataBind['file-list'].length } }, // 清空已上传文件列表 clearFileSet() { if (this.dataBind.clearFiles) { this.times = 0 this.number = 0 this.dataBind['show-file-list'] = false this.$refs[this.dataBind.ref].clearFiles() } }, // 返回顶部 backTop() { if (!this.dataBind.backTop) return // 限于iframe嵌入页 window.parent.scrollTo({ top: 0, behavior: 'smooth' }) }, // default 初始化 initialSet(obj) { let uploadDefault = { ref: 'YxkUpload', action: 'https://up.qiniup.com/', limit: 999, size: 3, accept: '.png,.jpg', pathName: 'product', bucket: QiniuBucket.PUBLIC_GALLERY, multiple: true, backTop: false, drag: true, 'show-file-list': true, 'list-type': 'picture-card' } this.dataBind = {...uploadDefault, ...this.dataBind, ...obj} this.fileTypeSet() this.paramsSet() }, // el-upload 参数 dataBindSet() { return this.deleteParams(this.dataBind, ['size', 'pathName', 'avator', 'acceptArr', 'linkUrl']) }, // delete deleteParams(obj, arr) { let params = JSON.parse(JSON.stringify(obj)) arr.forEach(item => { delete params[item] }) return params }, // 获取七牛token getQiNiu() { if (this.dataBind.token) { this.$set(this.dataBind, 'data', {token: this.dataBind.token}) return false } const bucketApi = new Bucket(this.bucket || QiniuBucket.PUBLIC_GALLERY, { url: this.url || this.dataBind.url }) bucketApi.getBucketToken({ bucket: this.dataBind.bucket, moduleName: this.dataBind.pathName, path_prefix: this.dataBind.pathName }).then((res) => { if (res.code == 200) { this.dataBind.action = res.data.domain || res.data.upDomain // 七牛存储域 this.dataBind.linkUrl = res.data.cdnDomain // 文件展示地址 this.dataBind.pathName = res.data.path // 文件存储地址 this.$set(this.dataBind, 'data', {token: res.data.token}) // token } else { this.$message.error(res.msg); } }) } }, computed: {}, watch: { uploadObj: { handler(n) { this.initialSet(n) }, deep: true, immediate: true } }, created() {}, mounted() { this.getQiNiu() } } </script> <style lang='scss'> .YxkUpload{ .el-upload-list{ .el-upload-list__item{ width: 100px; height: 100px; } } .el-upload{ width: 100px; height: 100px; line-height: 100px; .el-upload-dragger{ width: auto; height: auto; border: none; background: none; } } .YxkUpload__slot{ .el-upload{ width: auto; height: auto; line-height: 0; border: none; .el-icon-plus{ display: none; } } } } </style>
参数说明: