话不多说, 直接上代码:
视图层:
客服上传图片:
客服上传视频:
逻辑层:
// 监听附件相关数据
watch: {
// 新增图片
fileList: {
async handler(newList) {
this.fileData.imgFiles = []
if (newList.length) {
let fileObj = {}
await newList.map(file => {
// 上传的文件流转为base64格式
if (file.raw) {
getBase64File(file.raw).then(res => {
fileObj = {
fileName: file.name,
fileBase64: res
}
this.fileData.imgFiles.push(fileObj)
})
} else {
fileObj = {
fileBase64: file.fileBase64,
fileName: file.name,
type: file.type
}
this.fileData.imgFiles.push(fileObj)
}
})
}
}
},
// 删除已上传图片时
newImgList: {
handler: function(list) {
let obj = {
fileBase64: '',
fileName: '',
type: ''
}
list.map(file => {
obj = {
fileBase64: file.fileBase64,
fileName: file.name,
type: file.type
}
})
this.fileData.imgFiles.push(obj)
}
},
//添加视频
videoList: {
async handler(newList) {
this.fileData.videoFiles = []
if (newList.length) {
let fileObj = {}
await newList.map(file => {
// 上传的文件流转为base64格式
if (file.raw) {
getBase64File(file.raw).then(res => {
fileObj = {
fileName: file.name,
fileBase64: res
}
this.fileData.videoFiles.push(fileObj)
})
} else {
fileObj = {
fileBase64: file.fileBase64,
fileName: file.name,
type: file.type
}
this.fileData.videoFiles.push(fileObj)
}
})
}
}
},
// 删除已上传视频时
newVideoList: {
handler: function(list) {
let obj = {
fileBase64: '',
fileName: '',
type: ''
}
list.map(file => {
obj = {
fileBase64: file.fileBase64,
fileName: file.name,
type: file.type
}
})
this.fileData.videoFiles.push(obj)
}
}
},
// 添加图片文件
fileChange(file, fileList) {
this.fileList = fileList
this.fileList.map((item, index) => {
const fileSize = item.size / 1024 / 1024
if (fileSize > 20) {
this.$message.error('单个附件大小不能超过20M')
this.fileList.splice(index, 1)
}
})
setTimeout(() => {
this.editFile('image')
}, 1000)
},
// 添加视频文件
changeUploadVideo(file, fileList) {
const fileSize = file.size / 1024 / 1024 <= 50
if (
['video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb', 'video/mov'].indexOf(
file.raw.type
) == -1 // 控制格式
) {
this.$message.error('请上传正确的视频格式')
return false
}
if (!fileSize) {
this.$message.error('视频大小不能超过50MB')
return false
}
this.videoList = fileList
setTimeout(() => {
this.editFile('video')
}, 1000)
},
// 移除图片文件
handleRemoveImg(file) {
this.fileList.map((item, index) => {
if (item.name === file.name) {
// 回显图片时
if (item.type === 2) {
item.type = 1 // 2 保留 1 删除
this.newImgList = this.fileList.splice(index, 1)
setTimeout(() => {
this.editFile('image')
}, 500)
} else {
// 新增图片时
this.fileList.splice(index, 1)
}
}
})
},
// 移除视频文件
handleRemoveVideo(file) {
this.videoList.map((item, index) => {
if (item.name === file.name) {
// 回显视频时
if (item.type === 2) {
item.type = 1 // 2 保留 1 删除
this.newVideoList = this.videoList.splice(index, 1)
setTimeout(() => {
this.editFile('video')
}, 500)
} else {
// 新增视频时
this.videoList.splice(index, 1)
}
}
})
},
// 预览图片
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.$alert(`
`, {
dangerouslyUseHTMLString: true,
callback: () => {}
})
},
// 编辑附件
editFile(type) {
const params = {
imgFiles: this.fileData.imgFiles,
videoFiles: this.fileData.videoFiles,
csClass: this.summaryDetail.csClassIds[this.summaryDetail.csClassIds.length - 1],
csFeedbackDescribe: this.summaryDetail.csFeedbackDescribe,
id: this.summaryDetail.id,
role: 1,
appPhone: this.summaryDetail.appPhone,
sn: this.summaryDetail.sn,
qrCode: this.summaryDetail.qrCode,
iscallBack: 1 // 是否编辑回电 1否 2是
}
this.$confirm('确认修改?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
this.loading = true
addSummary(params) // 后端接口
.then(res => {
if (res.code === 0) {
this.getSummaryList(this.activeName)
this.$message.success(res.msg)
}
})
.catch(() => {
this.loading = false
// 添加修改失败,恢复原有数据
if (type === 'image') {
this.csImages = handleFileFormat(this.summaryDetail.csImgFiles)
} else {
this.csVideos = handleFileFormat(this.summaryDetail.csVideoFiles)
}
})
})
.catch(() => {
// 取消添加修改,恢复原有数据
if (type === 'image') {
this.csImages = handleFileFormat(this.summaryDetail.csImgFiles)
} else {
this.csVideos = handleFileFormat(this.summaryDetail.csVideoFiles)
}
})
}
上传附件没有使用单独的上传接口,是调用添加记录接口时,统一传参保存。添加接口请求成功后再回显。
因为我们的需求是在详情页面也能编辑图片和视频,所以加了`type`字段,1代表删除,2代表保留,添加的话就不传。如果你们的需求没有在详情编辑的功能,相关的逻辑可以不用管。
添加失败或取消添加时,恢复原有数据。
视频的时候需要注意:video标签的层级比较高,鼠标hover时上面的删除图标显示不出来,手动修改它们的`z-index`,比如:
删除图标的容器宽度也修改下,否则会覆盖视频播放按钮。
样式设置:
/deep/ .el-upload--picture-card {
width: 80px;
height: 80px;
}
/deep/ .el-upload-list__item {
width: 80px;
height: 80px;
}
.avatar-uploader {
/deep/ .el-upload--picture-card {
display: inline-block;
width: 200px;
height: 120px;
}
/deep/ .el-upload-list__item {
display: inline-block;
width: 200px;
height: 120px;
}
}
video {
display: inline-block;
position: relative;
z-index: 100;
}
/deep/ .el-icon-plus {
position: relative;
top: -35%;
}
.avatar-uploader {
/deep/ .el-icon-plus {
position: relative;
top: -6%;
}
}
上传前:
上传后: