文件附件的预览、下载和动态删除组件(仅查看无上传)
需求
需求是从后端拿到了一个数组的图片,文档,视频或者音频的数组
最后的使用样式截图放最后了
比如
fileList: [
'/upload/332131.png',
'/upload/sale?filename=csdacsa.pdf',
'/upload/sale?filename=才能打死啊.xlx',
'/upload/sale?filename=3.png',
'/upload/sale?filename=吃的啥.gif',
'/upload/sale?filename=除非是打完钱.zip',
'/upload/等我if差动.mp4',
'/upload/sale?filename=从电脑哦vcdai.mp3'
]
需要能够渲染到页面上后,能够预览,包括mp4,png,mp3,jpg等,其中的视频和音频的播放都是写死的,从网上找的测试的文件,如果是后端有具体的返回的话自己进行拼接一下即可
文件list列表显示组件代码
其中需要安装视频播放的插件,在项目根目录终端运行
npm install --save video.js
在当前需要使用的页面导入,这里就不使用全局了(绝不是因为我使用全局一直报错 /(ㄒoㄒ)/~~)
import 'video.js/dist/video-js.css'
当前代码的import VideoJs from './VideoJs.vue'
指的是在同级目录下的组件,也就是下面的VideoJs.vue
文件
file-list.vue文件代码
<template>
<div class="file-list">
<div v-for="(item, index) in fileLists" :key="index" class="file">
<div class="icon">
<img v-if="getFileType(item) === 'xls' || getFileType(item) === 'xlsx'" src="@/static/file-icon/xls.png">
<img v-else-if="getFileType(item) === 'doc' || getFileType(item) === 'docx'" src="@/static/file-icon/doc.png">
<img v-else-if="getFileType(item) === 'mp3'" src="@/static/file-icon/mp3.png">
<img v-else-if="getFileType(item) === 'mp4'" src="@/static/file-icon/mp4.png" @click="seeMp4(item)">
<img v-else-if="getFileType(item) === 'pdf'" src="@/static/file-icon/pdf.png">
<img v-else-if="getFileType(item) === 'ppt' || getFileType(item) === 'pptx'" src="@/static/file-icon/ppt.png">
<img v-else-if="getFileType(item) === 'txt'" src="@/static/file-icon/txt.png">
<img
v-else-if="getFileType(item) === '7z' || getFileType(item) === 'zip' || getFileType(item) === 'rar'"
src="@/static/file-icon/package.png"
>
<template v-else-if="getFileType(item) === 'jpg' || getFileType(item) === 'png' || getFileType(item) === 'gif'">
<viewer>
<img :src="baseUrl + item">
</viewer>
</template>
<img v-else src="@/static/file-icon/other.png">
</div>
<el-button type="text" class="name" @click="check(item)">
{{ item }}
</el-button>
<div class="action">
<a class="action-download" :href="baseUrl + item" download="" target="_self">下载</a>
<span class="del" @click="handleDelete(index)">删除</span>
</div>
<!-- 弹窗预览文件 -->
<el-dialog
v-if="accessoryVisble"
:visible.sync="accessoryVisble"
:show.sync="accessoryVisble"
width="60%"
class="accessoryVisble"
:before-close="cancel"
top="40px"
:title="checkFile"
append-to-body
>
<div class="dialog">
<div v-if="fileType === 1">
<img :src="baseUrl + checkFile" width="100%" />
</div>
<div v-else-if="fileType === 2" class="audio-mp3">
<audio controls ref="audio" class="aud">
<source src="http://music.163.com/song/media/outer/url?id=447925558.mp3" />
</audio>
</div>
<div class="videoArea" v-else-if="fileType === 3">
<video-js :options="videoOptions" class="video-css" />
</div>
<div v-else-if="fileType === 5">
<!-- <iframe :src="baseUrl + checkFile" frameborder="e" width="100%" height="600" /> -->
<!-- 测试链接 -->
<iframe :src="'http://www.leomay.com/upload/file/mmo-20170707165001.pdf'" frameborder="e" width="100%" height="600" />
</div>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
// 视频播放插件
import VideoJs from './VideoJs.vue'
import 'video.js/dist/video-js.css'
export default {
name: 'fileList',
props: {
list: {
type: [Array],
default: () => []
}
},
components: {
VideoJs
},
data() {
return {
baseUrl: '/upload/sale?filename=', // 这里需要使用自己的后端的基础地址
fileLists: [],
accessoryVisble: false,
checkFile: '',
fileType: null,
/**
*播放器配置,如果还需要其他的则再加
*/
videoOptions: {
controls: true, // 开启交互,即是用户可控。
muted: true, // 开启视频时是否静音
fluid: true, // 根据外层css样式大小,自动填充宽高!比较实用,可搭配响应式
reload: 'auto', // 重载
// 其余设置根据需求添加!
poster: require('@/static/file-icon/mp4.png'), // 视频封面
sources: [ // 视频播放源,建议本地
{
// 测试地址网上找的
src: 'http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4',
type: 'video/mp4'
}
]
}
}
},
created() {
// 获取文件名字格式列表
for (let i = 0; i < this.list.length; i++) {
console.log(this.getFileName(this.list[i]))
this.fileLists.push(this.getFileName(this.list[i]))
console.log(this.fileLists)
}
},
methods: {
// 获取文件名字(分情况获取)
getFileName(val) {
if (val && val.indexOf('?filename=') !== -1) {
console.log(val.substr(val.indexOf('?filename=') + 10))
return val.substr(val.indexOf('?filename=') + 10)
} else if (val && val.indexOf('upload/') !== 0) {
const url = val.split('?')[0] // 只要?号前的
const urlSlashCount = url.split('/').length // 统计斜杠
console.log(url.split('/')[urlSlashCount - 1].toLowerCase())
return url.split('/')[urlSlashCount - 1].toLowerCase() // 获取数组最后一个
// return val
} else {
return val
}
},
handleDelete(index) {
console.log('删除', index)
this.list.splice(index, 1)
},
handleDownload(index) {
console.log('下载', index)
},
check(item) {
console.log('预览', this.getFileType(item))
this.checkFile = item
this.accessoryVisble = true
if (this.getFileType(item) === 'jpg' || this.getFileType(item) === 'png' || this.getFileType(item) === 'gif') {
this.fileType = 1
console.log('图片')
} else if (this.getFileType(item) === 'mp3') {
console.log('音频')
this.fileType = 2
} else if (this.getFileType(item) === 'mp4') {
console.log('视频', this.videoOptions.sources[0].src)
this.fileType = 3
// this.videoOptions.sources.src[0] = this.baseUrl + item
} else if (this.getFileType(item) === '7z' || this.getFileType(item) === 'zip' || this.getFileType(item) === 'rar') {
console.log('压缩文件')
this.checkFile = '该文件不可预览'
} else {
console.log('其他文件')
this.fileType = 5
}
},
cancel() {
this.accessoryVisble = false
this.otherFile = false
this.isImage = false
this.fileType = null
this.checkFile = ''
},
// 获取文件格式
getFileType(val) {
const list = val.split('.')
const type = list[list.length - 1]
return type.toLowerCase()
},
seeMp4(item) {
window.open(this.$settings.apiUrl + item)
}
}
}
</script>
<style lang="scss" scoped>
.file {
display: flex;
height: 48px;
line-height: 48px;
margin-bottom: 10px;
.icon {
margin-right: 10px;
cursor: pointer;
img {
height: 48px;
width: 36px;
object-fit: cover;
}
}
.name {
flex: 1;
display: flex;
justify-content: flex-start;
}
.action {
.del {
color: red;
cursor: pointer;
}
a {
text-decoration-line: none;
margin-right: 20px;
}
a:hover {
text-decoration-line: underline;
}
}
}
.dialog {
width: 100%;
// margin: auto;
// display: flex;
justify-content: center;
align-items: center;
margin-right: 20px;
// height: auto;
.videoArea {
height: 100%;
}
.audio-mp3 {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>
<style>
单独给视频的播放按钮键设置位置
.video-js .vjs-big-play-button {
top: 45%;
left: 45%;
}
</style>
视频播放组件VideoJs.vue
<template>
<div>
<video ref="videoPlayer" class="video-js"></video>
</div>
</template>
<script>
import 'video.js/dist/video-js.css'
import videojs from 'video.js'
export default {
// name: 'VideoJs',
props: {
options: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
player: null
}
},
mounted() {
this.player = videojs(this.$refs.videoPlayer, this.options, function onPlayerReady() {
console.log('onPlayerReady', this)
})
},
beforeDestroy() {
if (this.player) {
this.player.dispose()
}
}
}
</script>
<style scoped>
</style>
父组件引用
传入最上面的fileList数组即可
<template>
<div>
<file-list :list="fileList" />
</div>
</template>
<script>
import fileList from './file-list.vue'
export default {
components: {
fileList
},
data() {
return {
fileList: [
'/upload/332131.png',
'/upload/sale?filename=csdacsa.pdf',
'/upload/sale?filename=才能打死啊.xlx',
'/upload/sale?filename=3.png',
'/upload/sale?filename=吃的啥.gif',
'/upload/sale?filename=除非是打完钱.zip',
'/upload/等我if差动.mp4',
'/upload/sale?filename=从电脑哦vcdai.mp3'
'从电脑哦vcdai.mp3'
]
}
}
}
</script>
<style>
</style>
音频播放
视频播放
文件查看
文件查看没有仔细调整,可自己测试测试