需求
最终成果
过程
- 最开始是准备通过自定义预览样式,通过 preview-cover 插槽可以自定义覆盖在预览区域上方的内容。但问题是会修改每一个上传的图片和视频,都添加上播放视频的图片,不能实现直接预览图片的效果
- 最终采用自定义单个图片预览
<van-uploader
accept="*"
v-model="imgList"
:after-read="afterRead"
:before-read="beforeRead"
preview-size='25vw'
@click-preview="handleclicksc"
:before-delete="afterDelete"
:preview-full-image="false"
:disabled="isUploading?true:false"
/>
<van-overlay :show="show" @click="show = false">
<div class="wrapper" >
<div class="img-block">
<img v-if="urlType==='image'" :src="url">
<video autoplay class="video" v-if="urlType==='video'" :src="url" controls></video>
</div>
<img v-if="urlType==='video'"
@click="show=false"
class="video-delete"
src="./close.png"
/>
</div>
</van-overlay>
data(){
return {
isUploading:false,
allInfoList:[],
url:'',
urlType:'',
}
},
watch: {
'allInfoList' () {
this.imgList = []
for (let item of this.allInfoList) {
let data = {
type: item.type,
name: item.originalName,
url: item.type === 'video' ? 'https://replacement.png' : 'https://' + item.fileUri
}
this.imgList.push(data)
}
}
},
methods:{
beforeRead (file) {
if (!file.type.startsWith('image') && !file.type.startsWith('video')) {
this.$toast('请上传图片或视频')
return false
}
return true
},
afterRead (file) {
file.status = 'uploading'
file.message = '上传中...'
this.isUploading = true
fileApi
.uploadFile(file.file)
.then(res => {
if (res.data.status === 'success') {
let fileDTO = response.data.fileDTO
if (file.file.type.startsWith('video')) {
fileDTO.type = 'video'
}
if (file.file.type.startsWith('image')) {
fileDTO.type = 'image'
}
this.allInfoList.push(fileDTO)
} else {
this.handleDelete(file.file.name)
}
file.status = ''
file.message = ''
this.isUploading = false
})
.catch((error) => {
console.log(error)
this.handleDelete(file.file.name)
file.status = ''
file.message = ''
this.isUploading = false
})
},
handleDelete (name) {
this.imgList.forEach((item, index) => {
if (item.file.name === name) {
this.imgList.splice(index, 1)
}
})
},
afterDelete (file) {
let name = file.name
this.allInfoList.forEach((item, index) => {
if (item.originalName === name) {
this.allInfoList.splice(index, 1)
}
})
return true
},
}
handleclicksc (file) {
let name = file.name
for (let item of this.allInfoList) {
if (item.type === 'video' && item.originalName === name) {
this.url = this.getUrl(item.fileUri)
this.urlType = 'video'
this.show = true
}
if (item.type === 'image' && item.originalName === name) {
this.url = this.getUrl(item.fileUri)
this.urlType = 'image'
this.show = true
}
}
},
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.img-block {
position: relative;
img{
z-index: 99;
max-width: 100%;
height: auto;
object-fit: cover;
}
video{
width: 100%;
max-height: 100vh;
}
}
.video-delete{
width: 45px;
position: absolute;
top: 60px;
left: calc(100vw - 60px);
}