默认ElmentUI的文件列表只有一个删除按钮,我需要加预览、下载、编辑等,就需要优化显示结果。
优化后没用上传进度条,又加了一个进度条效果
代码
<template><div><el-uploadclass="upload-demo"action="/":file-list="fileList":disabled="isUpLoading":before-upload="beforeUpload":http-request="handleHttpRequest":on-remove="handleRemoveFile":on-progress="handleLoading":on-success="handleUploadSuccess"><el-button size="small" :loading="isUpLoading" type="primary">{{this.isUpLoading?"附件上传中...":"点击上传"}} </el-button><div slot="tip" class="el-upload__tip">(建议上传附件大小在5M以内)</div></el-upload><div id="file-list"><el-progress v-if="isUpLoading" :percentage="uploadingProgress"></el-progress><div v-for="(file,index) in fileList" :key="file.fileIdentifier" style="display: flex;justify-content: space-between;line-height: 25px;"><div>{{index+1}}、{{file.name}} </div><div style="padding-right: 20px;"><a href="javascript:void(0)" style="cursor:pointer;" @click="fileOption(file,'down')">下载</a><a href="javascript:void(0)" v-if = "officeFileType.includes(file.wjhz.toLowerCase())" style="margin-left: 10px;cursor:pointer;" @click="fileOption(file,'show')">查看</a><a href="javascript:void(0)" v-if = "officeFileType.includes(file.wjhz.toLowerCase())" style="margin-left: 10px;cursor: pointer;" @click="fileOption(file,'edit')">编辑</a><a href="javascript:void(0)" style="margin-left: 10px;cursor: pointer;" @click="fileOption(file,'del')">删除</a></div></div></div></div>
</template><style lang="scss" scoped>
::v-deep .el-upload-list{display: none;
}
</style><script>
import md5 from "@/api/file/md5";
import { taskInfo, initTask, preSignUrl, merge, del, getFileList} from '@/api/file/api';
import Queue from 'promise-queue-plus';
import axios from 'axios'
import VXETable from 'vxe-table'
import { changeUserStatus } from '@/api/system/user'export default {name: 'upload-page',props: {// 文件类型fjlxdm: {required: true,type: String},// 业务主建ywbs: {required: true,type: String},},created(){this.initData();},data() {return {fileUploadChunkQueue:{},lastUploadedSize:0,// 上次断点续传时上传的总大小uploadedSize:0,// 已上传的大小totalSize:0,// 文件总大小startMs:'',// 开始上传的时间taskRecord:{},options:{},fileList:[],officeFileType:['.ppt', '.pptx', '.doc', '.docx', '.xls', '.xlsx','.pdf'],isUpLoading:false,uploadingProgress:0,uploadTime:null,}},methods: {handleLoading(event, file, fileList){if(this.uploadTime!=null){clearInterval(this.uploadTime);this.uploadTime=null;}this.uploadingProgress=parseFloat(event.percent);},fileOption(file,type){if(type=="down"){//下载window.open(file.url, "_blank");return;}if(type=="show"){//查看const { href } = this.$router.resolve({name: 'office',query: {fjxxbs: file.fjxxbs,viewUrl: file.viewUrl,ot: 'detail'}})window.open(href, '_blank')return;}if(type=="edit"){//编辑const { href } = this.$router.resolve({name: 'office',query: {fjxxbs: file.fjxxbs,viewUrl: file.viewUrl,ot: 'edit'}})window.open(href, '_blank')return;}if(type=="del"){//删除this.$confirm('确认删除该附件?',"警告",{confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then( () => {del(file.fjxxbs).then(ret => {const index = this.fileList.findIndex((item) => item.fjxxbs === file.fjxxbs);this.fileList.splice(index, 1);this.msgSuccess("删除成功");});})return;}},/*** 获取附件列表*/initData(){this.uploadingProgress=100;getFileList(this.ywbs,this.fjlxdm).then(ret => {this.fileList = ret.data;setTimeout(()=>{this.isUpLoading=false;},500);})},/*** 获取一个上传任务,没有则初始化一个*/async getTaskInfo(file){let task;const identifier = await md5(file)const { code, data, msg } = await taskInfo(identifier,this.ywbs,this.fjlxdm);if (code === 200) {task = dataif (task===undefined) {const initTaskData = {identifier,fileName: file.name,totalSize: file.size,chunkSize: 5 * 1024 * 1024,ywbs:this.ywbs,fjlxdm:this.fjlxdm}const { code, data, msg } = await initTask(initTaskData)if (code === 200) {task = data} else {this.$notify({title:'提示',message: '文件上传错误',type: 'error',duration: 2000})}}} else {this.$notify({title:'提示',message: '文件上传错误',type: 'error',duration: 2000})}return task},// 获取从开始上传到现在的平均速度(byte/s)getSpeed(){// 已上传的总大小 - 上次上传的总大小(断点续传)= 本次上传的总大小(byte)const intervalSize = this.uploadedSize - this.lastUploadedSizeconst nowMs = new Date().getTime()// 时间间隔(s)const intervalTime = (nowMs - this.startMs) / 1000return intervalSize / intervalTime},async uploadNext(partNumber){const {chunkSize,fileIdentifier} = this.taskRecord;const start = new Number(chunkSize) * (partNumber - 1)const end = start + new Number(chunkSize)const blob = this.options.file.slice(start, end)const { code, data, msg } = await preSignUrl({ identifier: fileIdentifier, partNumber: partNumber , ywbs:this.ywbs , fjlxdm:this.fjlxdm} )if (code === 200 && data) {await axios.request({url: data,method: 'PUT',data: blob,headers: {'Content-Type': 'application/octet-stream'}})return Promise.resolve({ partNumber: partNumber, uploadedSize: blob.size })}return Promise.reject(`分片${partNumber}, 获取上传地址失败`)},/*** 更新上传进度* @param increment 为已上传的进度增加的字节量*/updateProcess(increment){increment = new Number(increment)const { onProgress } = this.optionslet factor = 1000; // 每次增加1000 bytelet from = 0;// 通过循环一点一点的增加进度while (from <= increment) {from += factorthis.uploadedSize += factorconst percent = Math.round(this.uploadedSize / this.totalSize * 100).toFixed(2);onProgress({percent: percent})}const speed = this.getSpeed();const remainingTime = speed != 0 ? Math.ceil((this.totalSize - this.uploadedSize) / speed) + 's' : '未知'console.log('剩余大小:', (this.totalSize - this.uploadedSize) / 1024 / 1024, 'mb');console.log('当前速度:', (speed / 1024 / 1024).toFixed(2), 'mbps');console.log('预计完成:', remainingTime);},handleUpload(file, taskRecord){this.lastUploadedSize = 0; // 上次断点续传时上传的总大小this.uploadedSize = 0 // 已上传的大小this.totalSize = file.size || 0 // 文件总大小this.startMs = new Date().getTime(); // 开始上传的时间this.taskRecord = taskRecord;const { exitPartList, chunkNum} = taskRecordreturn new Promise(resolve => {const failArr = [];const queue = Queue(5, {"retry": 3, //Number of retries"retryIsJump": false, //retry now?"workReject": function(reason,queue){failArr.push(reason)},"queueEnd": function(queue){resolve(failArr);}})this.fileUploadChunkQueue[file.uid] = queuefor (let partNumber = 1; partNumber <= chunkNum; partNumber++) {const exitPart = (exitPartList || []).find(exitPart => exitPart.partNumber == partNumber)if (exitPart) {// 分片已上传完成,累计到上传完成的总额中,同时记录一下上次断点上传的大小,用于计算上传速度this.lastUploadedSize += new Number(exitPart.size)this.updateProcess(exitPart.size)} else {queue.push(() => this.uploadNext(partNumber).then(res => {// 单片文件上传完成再更新上传进度this.updateProcess(res.uploadedSize)}))}}if (queue.getLength() == 0) {// 所有分片都上传完,但未合并,直接return出去,进行合并操作resolve(failArr);return;}queue.start()})},async handleHttpRequest(options){this.options = options;const file = options.fileconst task = await this.getTaskInfo(file)const that = this;if (task) {const { finished, path, taskRecord } = taskconst {fileIdentifier,fjxxbs } = taskRecordif (finished) {return {fileIdentifier,fjxxbs}} else {const errorList = await this.handleUpload(file, taskRecord)if (errorList.length > 0) {this.$notify({title:'文件上传错误',message: '部分分片上传失败,请尝试重新上传文件',type: 'error',duration: 2000})return;}const { code, data, msg } = await merge(fileIdentifier,that.ywbs,that.fjlxdm)if (code === 200) {return {fileIdentifier,fjxxbs};} else {this.$notify({title:'提示',message: '文件上传错误',type: 'error',duration: 2000})}}} else {this.$notify({title:'文件上传错误',message: '获取上传任务失败',type: 'error',duration: 2000})}},/*** 重复上传* @param {} file*/beforeUpload(file){return new Promise((resolve, reject) => {md5(file).then(result => {const index = this.fileList.findIndex((item) => item.fileIdentifier === result);if(index==-1){this.isUpLoading=true;this.uploadingProgress=0;this.uploadTime=setInterval(()=>{this.uploadingProgress+=1;},500)return resolve(true);}else{return reject(false);}})});},handleRemoveFile(uploadFile, uploadFiles){const queueObject = this.fileUploadChunkQueue[uploadFile.uid]if (queueObject) {queueObject.stop()this.fileUploadChunkQueue[uploadFile.uid] = undefined;}if(uploadFile.fjxxbs != undefined){del(uploadFile.fjxxbs).then(ret => {const index = this.fileList.findIndex((item) => item.fjxxbs === uploadFile.fjxxbs);this.fileList.splice(index, 1);})}},/*** 上传成功*/handleUploadSuccess(res, file, fileList) {// file.fileIdentifier = res.fileIdentifier;// file.fjxxbs = res.fjxxbs;// this.fileList.push(file);this.initData();}}
}</script>