自定义批量上传一些逻辑
<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>