默認(rèn)ElmentUI的文件列表只有一個刪除按鈕,我需要加預(yù)覽、下載、編輯等,就需要優(yōu)化顯示結(jié)果。
優(yōu)化后沒用上傳進度條,又加了一個進度條效果文章來源:http://www.zghlxwxcb.cn/news/detail-701440.html
代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-701440.html
<template>
<div>
<el-upload
class="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以內(nèi))</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
},
// 業(yè)務(wù)主建
ywbs: {
required: true,
type: String
},
},
created(){
this.initData();
},
data() {
return {
fileUploadChunkQueue:{},
lastUploadedSize:0,// 上次斷點續(xù)傳時上傳的總大小
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(
'確認(rèn)刪除該附件?',
"警告",
{
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);
})
},
/**
* 獲取一個上傳任務(wù),沒有則初始化一個
*/
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 = data
if (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
},
// 獲取從開始上傳到現(xiàn)在的平均速度(byte/s)
getSpeed(){
// 已上傳的總大小 - 上次上傳的總大?。〝帱c續(xù)傳)= 本次上傳的總大小(byte)
const intervalSize = this.uploadedSize - this.lastUploadedSize
const nowMs = new Date().getTime()
// 時間間隔(s)
const intervalTime = (nowMs - this.startMs) / 1000
return 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 為已上傳的進度增加的字節(jié)量
*/
updateProcess(increment){
increment = new Number(increment)
const { onProgress } = this.options
let factor = 1000; // 每次增加1000 byte
let from = 0;
// 通過循環(huán)一點一點的增加進度
while (from <= increment) {
from += factor
this.uploadedSize += factor
const 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('當(dāng)前速度:', (speed / 1024 / 1024).toFixed(2), 'mbps');
console.log('預(yù)計完成:', remainingTime);
},
handleUpload(file, taskRecord){
this.lastUploadedSize = 0; // 上次斷點續(xù)傳時上傳的總大小
this.uploadedSize = 0 // 已上傳的大小
this.totalSize = file.size || 0 // 文件總大小
this.startMs = new Date().getTime(); // 開始上傳的時間
this.taskRecord = taskRecord;
const { exitPartList, chunkNum} = taskRecord
return 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] = queue
for (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.file
const task = await this.getTaskInfo(file)
const that = this;
if (task) {
const { finished, path, taskRecord } = task
const {fileIdentifier,fjxxbs } = taskRecord
if (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: '獲取上傳任務(wù)失敗',
type: 'error',
duration: 2000
})
}
},
/**
* 重復(fù)上傳
* @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>
到了這里,關(guān)于優(yōu)化VUE Element UI的上傳插件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!