<template>
|
<div>
|
<el-upload :class="['avatar-uploader customUploadImg diyUpload',fileList.length === limitNumber?'uploadTrigger':'']"
|
:headers="headers" action="api" :on-error="handleError" :http-request="handleRequrst"
|
:on-change="handleChange" :multiple="multiple" :auto-upload="false" :accept="accept"
|
v-customLoading="{isLoading:isLoading,percentage:percentage}"
|
:show-file-list="false">
|
<div class="upload-list__item" :draggable="draggable" @dragstart="dragstart(item)"
|
@dragenter="dragenter(item)" @dragend="dragend(item)" v-for="(item,index) in fileList"
|
:key="item.url">
|
<video v-if="getFileType(item.url) === 'video'" :src="item.url" />
|
<img v-else :src="item.url" />
|
<slot name="appendPart" :data="{item,index}"></slot>
|
<span class="el-upload-list__item-actions">
|
<span class="el-upload-list__item-preview">
|
<i class="el-icon-zoom-in" @click="handlePreview(item.url)"></i>
|
</span>
|
<span class="el-upload-list__item-delete">
|
<i class="el-icon-delete" @click="handleRemove(item)"></i>
|
</span>
|
</span>
|
</div>
|
<i slot="trigger" v-show="fileList.length !== limitNumber"
|
class="el-icon-plus avatar-uploader-icon"></i>
|
<div slot="tip" v-if="fileTip" class="el-upload__tip" style="color:#909399;" v-html="fileTip">
|
</div>
|
</el-upload>
|
<div v-if="isHot && fileList.length">
|
<el-checkbox @change="positionChange" v-model="form.fixedPosition">固定图片位置
|
<span class="itemTips">
|
图片会始终固定在用户当前屏幕,不随用户上下滑动而消失
|
</span>
|
</el-checkbox>
|
<br />
|
<el-checkbox v-model="form.closeBtn">显示关闭按钮
|
<span class="itemTips">
|
关闭按钮会出现在图片的右上方,用户可关闭此热区图片
|
</span>
|
</el-checkbox>
|
</div>
|
<el-dialog :visible.sync="dialogVisible" v-if="dialogVisible" :modal="isAppendToBady">
|
<video v-if='getFileType(imgShow) === "video"' autoplay controls="controls" :src="imgShow"
|
width="100%" />
|
<img v-else :src="imgShow" width="100%" />
|
</el-dialog>
|
</div>
|
</template>
|
<script>
|
import {
|
getUuid
|
} from '@/api/sm'
|
import { mapState, mapMutations } from 'vuex'
|
import uploadFile from '@/api/uploadFile'
|
|
export default {
|
props: {
|
fileList: {
|
type: Array,
|
default: function() {
|
return []
|
}
|
},
|
index: {
|
type: Number,
|
default: 0
|
},
|
keyImg: {
|
type: String,
|
default: undefined
|
},
|
isAppendToBady: {
|
type: Boolean,
|
default: true
|
},
|
accept: {
|
type: String,
|
default: '.jpg,.jpeg,.png,.gif'
|
},
|
// 图片接收类型
|
uploadPath: {
|
type: String,
|
default: 'diy'
|
},
|
// 表单数据
|
form: {
|
type: Object,
|
default: function() {
|
return {}
|
}
|
},
|
// 是否是热区图片
|
isHot: {
|
type: Boolean,
|
default: false
|
},
|
// 限制图片上传个数
|
limitNumber: {
|
type: Number,
|
default: 1
|
},
|
// 是否可拖拽
|
draggable: {
|
type: Boolean,
|
default: false
|
},
|
// 是否支持多选
|
multiple: {
|
type: Boolean,
|
default: false
|
},
|
/**
|
* 设置上传图片的大小(提示)
|
*/
|
fileTip: {
|
type: String,
|
default: null
|
}
|
},
|
created() {
|
this.businessId = getUuid().split('-').join('')
|
},
|
computed: {
|
...mapState(['token']),
|
headers() {
|
return {
|
Authorization: 'Bearer ' + this.token
|
}
|
}
|
},
|
data: function() {
|
return {
|
businessId: null,
|
imgShow: null,
|
dialogVisible: false,
|
oldNum: {},
|
newNum: {},
|
files: [],
|
count: 0,
|
percentage: null, // 进度条数值
|
isLoading: false// 是否展示进度条遮罩
|
}
|
},
|
watch: {
|
count(newValue, oldValue) {
|
if (newValue !== this.files.length) {
|
this.handleRequrst()
|
}
|
}
|
},
|
methods: {
|
...mapMutations(['updateCurrent']),
|
positionChange(val) {
|
const st = document.getElementById('diy-aside').scrollTop
|
if (val) {
|
this.updateCurrent({ y: this.form.y - st })
|
} else {
|
this.updateCurrent({ y: this.form.y + st })
|
}
|
// this.updateCurrent({ fixedPosition: val })
|
},
|
// 当文件改变时获取选中的文件
|
handleChange(file, fileList) {
|
if (!this.beforeAvatarUpload(file)) return // 限制图片上传
|
this.files.push(file.raw)
|
this.count = fileList.length
|
this.count++
|
},
|
/**
|
*上传图片
|
*/
|
async handleRequrst(param) {
|
if (this.files.length + this.fileList.length > this.limitNumber) {
|
this.$message.warning(`当前限制选择 ${this.limitNumber} 个文件,本次选择了 ${this.files.length} 个文件,请重新选择`)
|
this.files = []
|
return
|
}
|
const formData = new FormData()
|
this.files.forEach(item => {
|
formData.append('files', item)
|
})
|
formData.append('bizCode', this.businessId)
|
formData.append('path', this.uploadPath)
|
// 进度条配置
|
const config = {
|
onUploadProgress: ProgressEvent => {
|
const progressPercent = Math.round(ProgressEvent.loaded / ProgressEvent.total * 100 | 0)
|
this.percentage = progressPercent === 100 ? 99 : progressPercent
|
this.isLoading = true
|
}
|
}
|
try {
|
const res = await uploadFile.fileUpload(formData, config)
|
if (res.data instanceof Array) {
|
res.data.forEach(item => {
|
var param = {
|
url: item.like,
|
id: item.key,
|
businessId: item.bizCode
|
}
|
this.$emit('handle-success', param)
|
})
|
this.files = []
|
this.percentage = 100
|
this.isLoading = false
|
} else {
|
this.isLoading = false
|
this.files = []
|
}
|
} catch (error) {
|
this.$message.error('上传文件失败!请重新上传')
|
this.files = []
|
this.isLoading = false
|
}
|
},
|
// 记录初始拖拽信息
|
dragstart(value) {
|
this.oldNum = value
|
},
|
// 做最终操作
|
dragend(value) {
|
if (this.oldNum !== this.newNum) {
|
const oldIndex = this.fileList.indexOf(this.oldNum)
|
const newIndex = this.fileList.indexOf(this.newNum)
|
const newItems = [...this.fileList]
|
// 删除老的节点
|
newItems.splice(oldIndex, 1)
|
// 在列表中目标位置增加新的节点
|
newItems.splice(newIndex, 0, this.oldNum)
|
// 新数组顺序
|
this.fileList = [...newItems]
|
this.$emit('handle-file-data', this.fileList)
|
}
|
},
|
// 记录移动过程中信息
|
dragenter(value) {
|
this.newNum = value
|
},
|
/**
|
* 预览
|
*/
|
handlePreview(file) {
|
this.dialogVisible = true
|
this.imgShow = file
|
},
|
/**
|
* 删除图片
|
*/
|
handleRemove(file) {
|
this.$emit('handle-remove', file)
|
this.updateCurrent({ fixedPosition: false, closeBtn: false }) // 重置图片位置、关闭按钮
|
},
|
handleError(e, file, fileList) {
|
this.$message.error('上传文件失败')
|
},
|
// 获取文件类型
|
getFileType(file) {
|
var nameType = file.substring(file.lastIndexOf('.') + 1)
|
if (nameType === 'mp4') {
|
return 'video'
|
} else {
|
return 'img'
|
}
|
},
|
/**
|
* 设置上传图片大小
|
*/
|
beforeAvatarUpload(file) {
|
const nameType = file.name.substring(file.name.lastIndexOf('.') + 1)
|
const fileType = this.accept.toLowerCase().includes(nameType.toLowerCase())
|
const imgSize = file.raw.type.includes('image')
|
const videoSize = file.raw.type.includes('video')
|
if (!fileType) {
|
this.$message.error(`上传失败!仅支持${this.accept}格式,请重新上传`)
|
return false
|
}
|
if (imgSize) {
|
const fileSize = file.size / 1024 / 1024 < 5
|
if (!fileSize) {
|
this.$message.error('上传失败!图片大小不能超多 5MB!请重新上传')
|
return false
|
}
|
}
|
if (videoSize) {
|
const fileSize = file.size / 1024 / 1024 < 300
|
if (!fileSize) {
|
this.$message.error('上传失败!视频大小不能超多 300MB!请重新上传')
|
return false
|
}
|
}
|
return true
|
}
|
}
|
}
|
</script>
|
<style lang="scss">
|
.customUploadImg {
|
position: relative;
|
.aaaa {
|
display: inline-block;
|
position: absolute;
|
left: 0;
|
}
|
.upload-list__item {
|
position: relative;
|
display: inline-block;
|
// width: 148px;
|
// height: 148px;
|
overflow: hidden;
|
// border: 1px solid #c0ccda;
|
// border-radius: 6px;
|
box-sizing: border-box;
|
margin: 0 15px 15px 0;
|
img,
|
video {
|
width: 148px;
|
height: 148px;
|
border: 1px solid #c0ccda;
|
border-radius: 6px;
|
}
|
.el-upload-list__item-actions {
|
position: absolute;
|
width: 148px;
|
height: 148px;
|
left: 0;
|
top: 0;
|
cursor: default;
|
text-align: center;
|
color: #fff;
|
opacity: 0;
|
font-size: 20px;
|
background-color: rgba(0, 0, 0, 0.5);
|
transition: opacity 0.3s;
|
border-radius: 6px;
|
line-height: 148px;
|
span {
|
cursor: pointer;
|
}
|
.el-upload-list__item-delete {
|
position: static;
|
font-size: inherit;
|
color: inherit;
|
}
|
span + span {
|
margin-left: 15px;
|
}
|
}
|
.el-upload-list__item-actions:hover {
|
opacity: 1;
|
span {
|
display: inline;
|
}
|
}
|
}
|
// div+div{
|
// margin-left: 15px;
|
// }
|
.el-upload__tip {
|
position: absolute;
|
top: 148px;
|
}
|
}
|
.diyUpload {
|
.el-upload {
|
border: none !important;
|
display: block;
|
width: 150px;
|
margin-bottom: 15px;
|
.avatar-uploader-icon {
|
border: 1px dashed #d9d9d9;
|
border-radius: 6px;
|
}
|
}
|
}
|
.uploadTrigger {
|
.el-upload {
|
display: none;
|
}
|
}
|
|
</style>
|