工作需要,要实现图片文档的上传查看下载等功能,于是就基于ele的upload组件做了封装,途中爬过几次坑,给大家做一次分享,共勉之!
1、打开弹窗页面时,获取上传列表
要在页面打开时请求列表接口,获取数据(若是页面建议放在mounted里面,若是弹框建议watch参数:visible.sync==true时),请求方法如下
// 获取列表
findLists() {
const tbJson = JSON.stringify({
length: 10,
start: 1,
searchBy: [],
orderBy: {}
})
this.$axios.post('/api/files/list', {
//获取列表需要参数
tbJson,
fid: this.pId
}).then(res => {
if (res.status === 200) {
this.fileList = Object.assign([], [])
//后台返回数据需要做处理,才能正常展示
res.data.list.forEach((l) => {
const obj = {
name: l.fname,
url: process.env.VUE_APP_BASE_API + '/' + l.fpath
}
this.fileList.push(obj)
})
this.defaultfileList = Object.assign([], res.data.list)
} else {
this.$mess.messagePrompt(res.message, 'error', true, false)
}
}).catch(() => {
})
},
2、上传图片或者文档
上传时,需要上传地址,头信息,额外参数等信息带给后台,这些参数之类的还好ele都给封装过了,基于组件就能完成
<el-upload
:accept="accept"//接受上传的[文件类型]
:action="upload"//必选参数,上传的地址
:data="datas()"// 上传时附带的额外参数
:headers="headers()"// 设置上传的请求头部
:multiple="multiple"
:on-remove="handleRemove"//文件列表移除文件时的钩子
:on-success="handleSuccess"//文件上传成功时的钩子
:on-preview="handlePictureCardPreview"//点击文件列表中已上传的文件时的钩子
:disabled="disabledInput"
list-type="picture"//文件列表的类型
:before-remove="beforeRemove"//删除文件之前的钩子
:file-list.sync="fileList"//上传的文件列表,
>
<el-button v-if="!isRead" size="small" type="primary" icon="el-icon-upload" :plain="plain" style="float: left">
新增附件
</el-button>
</el-upload>
3、删除爬坑(方法很笨,不建议学习,有好的办法多多交流)
测试发现,upload几个事件的返回值是组件处理后的数据(数据格式不是列表的数据格式)。接下来就要忙着找ID找下标来做删除.....
思路:因为uid是数据的唯一标识,渲染列表后将列表数据存起来,点击删除某一项时取其uid进行匹配,从而删除。
4、附上完整组件(部分是因为业务需求,可忽略....)
<template>
<div>
<el-dialog
v-if="dialogVisible"
:close-on-click-modal="false"
:visible.sync="dialogVisible"
width="550px"
title="附件列表"
>
<div class="upload-container" style="max-height:500px;overflow-y:auto;">
<el-dialog :close-on-click-modal="false" :visible.sync="dialogVisibleImg" :title="ImgName" append-to-body>
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<el-upload
class="uploadShow"
:accept="accept"
:action="upload"
:data="datas()"
:headers="headers()"
:multiple="multiple"
:on-remove="handleRemove"
:on-success="handleSuccess"
:on-preview="handlePictureCardPreview"
:disabled="disabledInput"
list-type="picture"
:before-remove="beforeRemove"
:file-list.sync="fileList"
>
<el-button v-if="!isRead" size="small" type="primary" icon="el-icon-upload" :plain="plain" style="float: left">
新增附件
</el-button>
</el-upload>
</div>
</el-dialog>
</div>
</template>
<script>
import dialogMixins from '@/mixins/diolog'
import { getToken } from '@/utils/auth'
export default {
components: {
},
mixins: [dialogMixins],
props: {
multiple: {
type: Boolean,
default: true
},
isRead: {
type: Boolean,
default: false
},
disabledInput: {
type: Boolean,
default: false
},
accept: {
type: String,
default: ''
},
pId: {
type: String,
default: ''
},
plain: {
type: Boolean,
default: false
}
},
data() {
return {
defaultfileList: [],
innerfileList: [], // 删除之前数据
fileList: [], // 删除之后数据(渲染数据)
dialogVisibleImg: false,
dialogImageUrl: '',
ImgName: ''
}
},
computed: {
upload() {
return `${process.env.VUE_APP_BASE_API}/api/files/upload`
// return (process.env.NODE_ENV === 'production' ? process.env.BASE_URL : '/api') + '/api/files/upload'
}
},
watch: {
dialogVisible(e) {
if (e) {
this.findLists()
}
}
},
methods: {
// 获取列表
findLists() {
const tbJson = JSON.stringify({
length: 10,
start: 1,
searchBy: [],
orderBy: {}
})
this.$axios.post('/api/files/list', {
tbJson,
fid: this.pId
}).then(res => {
if (res.status === 200) {
this.fileList = Object.assign([], [])
res.data.list.forEach((l) => {
const obj = {
name: l.fname,
url: process.env.VUE_APP_BASE_API + '/' + l.fpath
}
this.fileList.push(obj)
})
this.defaultfileList = Object.assign([], res.data.list)
} else {
this.$mess.messagePrompt(res.message, 'error', true, false)
}
}).catch(() => {
})
},
headers() {
const object = {
Authorization: getToken('token')
}
return object
},
datas() {
const pId = {
fid: this.pId
}
return pId
},
beforeRemove(file, fileList) {
// 删除提醒
return this.$mess.confirm().then(() => {
this.innerfileList = JSON.parse(JSON.stringify(fileList))
})
},
handleSuccess(res, file, fileList) {
this.defaultfileList.push({ id: res.data })
this.fileList = Object.assign([], fileList)
this.innerfileList = Object.assign([], fileList)
this.$emit('update:fileList', fileList)
},
handleRemove(file, fileList) {
const index = this.innerfileList.findIndex(el => {
return file.uid === el.uid
})
this.$axios.post('/api/files/del', {
ids: this.defaultfileList[index].id
}).then(res => {
if (res.status === 200) {
this.innerfileList.splice(index, 1)
this.defaultfileList.splice(index, 1)
this.fileList.splice(index, 1)
this.$message({
type: 'success',
message: '操作成功'
})
} else {
this.$mess.messagePrompt(res.message, 'error', true, false)
}
}).catch(() => {
})
},
handlePictureCardPreview(file) {
const arr = ['gif', 'jpg', 'jpeg', 'png', 'PNG', 'JPG', 'GIF']
const s = arr.filter(el => {
return file.url.includes(el)
})
if (s.length) {
this.dialogImageUrl = file.url
this.dialogVisibleImg = true
} else {
window.open(file.url)
}
}
}
}
</script>
<style scoped>
.uploadShow{
}
</style>