<template>
<div
class="file-upload"
>
<el-upload
:class="{ disabled: value }"
action=""
:multiple="false"
:limit="1"
:file-list="fileList"
:on-remove="handleImageRemove"
:http-request="handleUploadImage"
:on-preview="handleImagePreview"
:accept="accept"
:list-type="fileType==='img'?'picture-card':'text'"
>
<i v-if="fileType==='img'" class="el-icon-plus avatar-uploader-icon" />
<el-button v-else size="small" type="primary">
点击上传
</el-button>
</el-upload>
<preview-image v-if="fileType==='img'" ref="previewImageRef" :images="previewImageList" :thumbnail="false" />
</div>
</template>
<script>
/**
* 只支持一个文件上传
*/
import PreviewImage from "@/components/PreviewImage"
export default {
name: "FileUpload",
components: { PreviewImage },
props: {
// url
value: {
type: String,
default: ""
},
// 文件类型,'video','img'
fileType: {
type: String,
default: null
},
// 文件名, 用sync修饰符
fileName: {
type: String,
default: ""
}
},
data() {
return {
}
},
computed: {
// 上传格式
accept() {
return this.fileType === "video" ? ".avi,.wmv,.mpg,.mov,.rm,.ram,.swf,.flv,.mp4" : this.fileType === "img" ? ".jpg,.jpeg,.png" : null
},
// 预览图片列表
previewImageList() {
return this.fileList.map(v => v.url)
},
fileList() {
return this.value ? [{ url: this.value, name: this.fileName || "" }] : []
}
},
methods: {
// 点击下载
handleImagePreview() {
if (this.fileType === "img") {
this.$refs.previewImageRef.show(0)
} else {
const downloadElement = document.createElement("a")
downloadElement.href = this.value
downloadElement.download = this.fileName // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click()
document.body.removeChild(downloadElement) // 下载完成移除元素
}
},
/**
* @description: 删除图片
*/
handleImageRemove() {
this.$emit("input", "")
this.$emit("update:fileName", "")
},
/**
* @description: 上传
*/
handleUploadImage(fileInfo) {
const loading = this.$loading()
console.log("上传", fileInfo)
const formData = new FormData()
formData.append("file", fileInfo.file)
this.$axios({
url: "-------------------",
method: "post",
data: formData
}).then(response => {
this.$emit("input", response.data)
this.$emit("update:fileName", fileInfo.file.name)
loading.close()
}).catch(error => {
console.error("上传失败:" + error)
loading.close()
})
}
}
}
</script>
<style lang="scss">
.file-upload .disabled .el-upload--text {
display: none;
}
/*去除upload组件过渡效果*/
.file-upload .el-upload-list__item {
transition: none !important;
}
.file-upload .el-upload-list__item-thumbnail {
/* 图片在方框内显示长边 */
object-fit: scale-down !important;
}
.file-upload .el-upload-list__item:first-child {
margin-top: 5px !important;
}
.file-upload .disabled .el-upload--picture-card {
display: none;
}
</style>
选择图片或者视频或其他文件,只能上传一张,上传后无上传按钮,但会闪一下,预览图片组件也是二次封装v-viewer,视频和其他文件点击下载。
<template>
<div class="viewer-component">
<viewer
class="viewer"
:options="allOptions"
:images="images"
:rebuild="false"
@inited="inited"
>
<template slot-scope="scope">
<div v-show="thumbnail" class="image-box">
<img
v-for="(src, index) in scope.images"
:key="index"
:src="src"
:width="size ? size : width"
:height="size ? size : height"
:style="{ borderRadius: `${ borderRadius }px` }"
class="pic"
>
</div>
</template>
</viewer>
</div>
</template>
<script>
import "viewerjs/dist/viewer.css"
import VueViewer from "v-viewer"
import Vue from "vue"
Vue.use(VueViewer)
export default {
name: "PreviewImage",
props: {
options: {
type: Object,
default: () => ({})
},
// 图片列表
images: {
type: Array,
required: true
},
// 是否显示缩略图
thumbnail: {
type: Boolean,
default: true
},
// 设置缩略图尺寸,size优先级高于width 和 height
size: {
type: String,
default: ""
},
// 设置缩略图宽度
width: {
type: String,
default: "148px"
},
// 设置缩略图宽度
height: {
type: String,
default: "148px"
},
// 设置缩略图圆角
borderRadius: {
type: Number,
default: 6
}
},
data() {
return {
$viewer: null,
currentIndex: -1,
defaultOptions: {
inline: false,
button: true,
navbar: false,
title: false,
toolbar: true,
tooltip: true,
movable: true,
zoomable: true,
rotatable: true,
scalable: true,
transition: true,
fullscreen: true,
keyboard: true,
zIndex: 9999
}
}
},
computed: {
allOptions() {
return { ...this.defaultOptions, ...this.options }
}
},
methods: {
/**
* @description: 预览图片组件初始化完成
* @param {any} viewer
* @return {void}
*/
inited(viewer) {
this.$viewer = viewer
// this.$nextTick(() => {
// this.currentIndex > -1 && this.$viewer.view(this.currentIndex)
// })
},
/**
* @description: 显示预览图片组件
* @param {number} index
* @return {void}
*/
show(index = 0) {
this.$viewer.view(index)
// this.currentIndex = index
},
/**
* @description: 关闭预览图片组件
* @return {void}
*/
close() {
this.$viewer.close()
}
}
}
</script>
<style lang="scss" scoped>
.viewer-component {
.image-box {
display: flex;
flex-wrap: wrap;
}
.pic {
margin: 0 8px 8px 0;
}
}
</style>