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>
参数说明:





浙公网安备 33010602011771号