<template>
<!-- 上传弹窗 -->
<el-dialog title="上传文档" width="648px"
:close-on-press-escape="false"
:close-on-click-modal="false"
:visible.sync="uploadDialogVisible"
:before-close="uploadCancel">
<el-upload
class="upload-component-content"
drag
action=""
:http-request="uploadToServer"
ref="upload"
:auto-upload="false"
:show-file-list="false"
:on-progress="handleUploadProgress"
:on-change="handleUploadChange"
accept=".ppt,.pptx"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖拽至此处,或<em>点击选择文件</em></div>
<div class="el-upload__tip" slot="tip">支持上传100MB以内的ppt、pptx文档格式,一次最多上传5个文件</div>
</el-upload>
<div class="upload-list-info" v-if="uploadListData.length>0">
共{{uploadListData.length}}个:上传成功 {{uploadSuccessCount}} 上传失败 {{uploadFailCount}} 上传中 {{uploadingCount}}
</div>
<div class="upload-list" v-if="uploadListData.length>0 && !isNetworkDisconnect">
<el-table :data="uploadListData" max-height="200" v-loading.body="uploadListLoading" element-loading-text="Loading">
<el-table-column prop="name" width="200" :show-overflow-tooltip="true" label="文件名"></el-table-column>
<el-table-column prop="size" label="大小">
<template slot-scope="scope">
{{scope.row.size | sizeFilter}}
</template>
</el-table-column>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
<span v-if="scope.row.status === 'uploading'">{{scope.row.percent}}%</span>
<span v-else :class="{
'error-color': scope.row.status === 'fail' || scope.row.status.includes('error'),
'success-color': scope.row.status === 'success'}">
{{scope.row.status | statusFilter()}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-link v-if="scope.row.status==='uploading'" type="danger" @click="cancelUploading(scope.row)" class="error-color" :underline="false">取消上传</el-link>
<el-link v-else title="移除" icon="el-icon-delete" @click="removeUploadFile(scope)" type="danger"
:underline="false">
</el-link>
</template>
</el-table-column>
</el-table>
</div>
<div class="upload-warning" v-if="uploadListData.length>0">
<i class="el-icon-warning"></i>上传期间请勿关闭本页面,否则会上传失败。
</div>
<div slot="footer" class="dialog-footer" v-if="!uploadConfirmed">
<el-button @click="uploadCancel()">取 消</el-button>
<el-button type="primary" @click="uploadConfirm">确认上传</el-button>
</div>
</el-dialog>
</template>
<script>
import { uploadShareDoc } from '@/api/document'
import axios from 'axios'
export default {
name: 'UploadDialog',
props: ['visible','type','userId','conferenceId','conferenceNo'],
data() {
return {
uploadDialogVisible:false,
uploadListData:[],
uploadListLoading:false,
uploadConfirmed:false,
cancelSourceData:[],
}
},
watch: {
visible: {
handler(value) {
this.uploadDialogVisible = value
if(value)
this.uploadConfirmed = false
},
immediate: true
}
},
computed: {
isNetworkDisconnect () {
return this.$store.state.network.isNetworkDisconnect
},
uploadFailCount() {
return this.uploadListData.filter(
item => item.status === 'fail').length
},
uploadSuccessCount() {
return this.uploadListData.filter(
item => item.status === 'success').length
},
uploadingCount() {
return this.uploadListData.filter(
item => item.status === 'uploading').length
},
uploadTypeErrorCount() {
return this.uploadListData.filter(
item => item.status === 'type_error').length
},
uploadSizeErrorCount() {
return this.uploadListData.filter(
item => item.status === 'size_error').length
}
},
filters: {
sizeFilter(size) {
if (size < 1024) {
return size + 'B'
} else if (size >= 1024 && size < Math.pow(1024, 2)) {
return parseFloat(size / 1024).toFixed(2) + 'KB'
} else if (size >= Math.pow(1024, 2) && size < Math.pow(1024, 3)) {
return parseFloat(size / Math.pow(1024, 2)).toFixed(2) + 'MB'
} else if (size > Math.pow(1024, 3)) {
return parseFloat(size / Math.pow(1024, 3)).toFixed(2) + 'GB'
} else {
return 0 + 'B'
}
},
statusFilter(status,) {
if (status === 'success') {
return '上传成功'
} else if (status === 'fail') {
return '上传失败'
} else if (status === 'type_error') {
return '格式错误'
} else if (status === 'size_error') {
return '超出规定文件大小'
} else {
return '——'
}
}
},
methods: {
/********************* 上传处理 ***********************************/
//上传前文件格式、大小等校验
//上传100MB以内的ppt、pptx文档格式
validUploadFiles(file) {
const fileType = file.type || file.raw.type
const isType = fileType.includes('application/vnd.ms-powerpoint') || fileType.includes('application/vnd.openxmlformats-officedocument.presentationml.presentation');
const validResult = { status: 'success' }
if (!isType) {
if(file.name){
let fileNameSplit = file.name.split('.');
let suffix = fileNameSplit[ fileNameSplit.length - 1 ];
if(!suffix.includes('pptx')){
validResult.status = 'type_error'
}
}else{
validResult.status = 'type_error'
}
}
const isLt100M = file.size / 1024 / 1024
if (isLt100M > 100) {
validResult.status = 'size_error'
}
return validResult
},
uploadCancel() {
if(this.uploadListData.length === 0) {
this.$refs.upload.clearFiles()
this.$emit('close')
return
}
this.$confirm(`当前有文档正在上传,确认取消吗?`, '上传提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//取消上传
this.$refs.upload.abort()
this.$refs.upload.clearFiles()
this.cancelSourceData.forEach(
item => item.source.cancel()
)
if(this.uploadSuccessCount>0) {
this.$emit('upload-complete')
}
this.uploadListData = []
this.cancelSourceData = []
this.$emit('close')
}).catch(() => {
})
},
//上传中取消
cancelUploading(row) {
this.cancelSourceData.forEach((item,idx) => {
if (item.uid === row.uid) {
item.source.cancel('cancel')
row.status = 'ready'
this.updateUploadFile(row)
this.cancelSourceData.splice(idx,1)
}
}
)
},
//移除准备上传的文件
removeUploadFile(scope) {
const choiceIndex = scope.$index
if (choiceIndex > -1) this.uploadListData.splice(choiceIndex, 1)
},
uploadConfirm() {
//上传前网络校验
if (this.isNetworkDisconnect) {
this.$message.error('网络异常,请检测网络后重新上传')
return
}
const uploadReadyCount = this.uploadListData.filter(
item => item.status === 'ready').length
if(this.uploadListData.length === 0 || uploadReadyCount === 0) {
this.$message.error('没有待上传的文件,请添加')
return
}
//文件添加文件数量校验 一次最多上传5个文件
if(this.uploadListData.length > 5) {
this.$message.error('添加文件数量超出限制')
return
}
//校验文件 添加文件大小超出限制 添加文件格式错误
this.uploadListData.map(fileItem => {
const { status } = this.validUploadFiles(fileItem)
if (status === 'type_error' || status === 'size_error') {
fileItem.status = status
}
return fileItem
}
)
if (this.uploadTypeErrorCount > 0) {
this.$message.error('添加文件格式错误');
return
}
if (this.uploadSizeErrorCount > 0) {
this.$message.error('添加文件大小超出限制');
return
}
this.uploadConfirmed = true
this.$refs.upload.submit()
},
//更新列表数据
updateUploadFile(file) {
const idx = this.uploadListData.findIndex(item => item.uid === file.uid)
this.uploadListData[idx] = file
this.$set(this.uploadListData,idx,file)
},
//上传 回调
handleUploadProgress(val, file, fileList) {
file.percent = val
this.updateUploadFile(file)
},
handleUploadChange(file, fileList) {
if (file && file.status === 'ready') {
this.uploadListData.push(file)
}
},
//上传到服务器
uploadToServer(params) {
if(params.file.status
&& params.file.status !== 'ready') return
const formData = new FormData();
const materialParam = {
******
}
const json = JSON.stringify(materialParam);
const blob = new Blob([json], {type: 'application/json'});
formData.append('fileUpload', blob);
formData.append('files', params.file)
//进度条处理
const uploadProgressHandler = ({ total, loaded }) => {
const percent = (loaded / total) * 100
params.onProgress(percent.toFixed(0))
}
//cancelToken处理
let CancelToken = axios.CancelToken;
let source = CancelToken.source();
this.cancelSourceData.push({ source, uid: params.file.uid })
api(formData, uploadProgressHandler,source.token).then(res => {
if (res.code === 200) {
params.file.status = 'success'
this.updateUploadFile(params.file)
this.uploadConfirmed = false
if(this.uploadSuccessCount === this.uploadListData.length) {
this.$message.success('上传文档完成')
this.$emit('close')
this.uploadListData = []
this.$emit('upload-complete')
}
} else{
params.file.status = 'fail'
this.updateUploadFile(params.file)
this.uploadConfirmed = false
this.$message.error(res.msg || '上传文档失败')
}
})
.catch(err => {
if (!err.message || err.message !== 'cancel') {
params.file.status = 'fail'
this.updateUploadFile(params.file)
this.$message.error('上传文档失败')
}
this.uploadConfirmed = false
console.error(err)
})
},
}
}
</script>