天天看點

vue-自己封裝一個多檔案上傳元件

作者:愛折騰的仙劍迷

最近在做項目,需要檔案上傳,但是ant design vue自帶當上傳元件中當多檔案上傳進度的UI不太滿意,太小了,于是乎,本着沒有就造一個當原則,封裝一個多檔案上傳元件。

首先我們來說一下元件的檔案結構:元件和一個普通當VUE頁面相比,多了兩個屬性:name和props。 name屬性辨別着這個元件的名稱,當我們在其他元件調用的時候會用得到。props屬性的格式和data相似,他用來接收從父元件傳過來當資料,并且還可以對該資料進行校檢。

然後,讓我們直接用代碼來說明,上代碼。

<template>
<div>
  //這裡我采用彈窗的形式來加載多檔案上傳元件,符合大多數人的思想。
<a-modal v-model="uploadModal" title="選擇檔案并上傳,支援批量" centered :closable="false" :footer="null">
//采用清單元件展示多檔案資訊
  <a-list item-layout="horizontal" :data-source="fileList">
<a-list-item slot="renderItem" slot-scope="item, index">
<a-list-item-meta>
<a slot="title">{{ item.name }}</a>
<a slot="description">
  //通過進度條展示檔案上傳進度
<a-progress v-if="!item.backStatus" :percent="item.percent" />
  //檔案上傳伺服器後,伺服器會有一個存盤當過程,展示出來。
<a-spin v-if="item.backStatus">伺服器進行中。。。</a-spin>
</a>
</a-list-item-meta>
</a-list-item>
</a-list>
<a-row type="flex" align="middle" justify="center">
<a-col>
  //ant design vue的上傳元件,這裡隻用它當按鈕樣式
<a-upload
:customRequest="customRequest"
:multiple="true"
:showUploadList="false"
name="file"
:fileList="fileList"
v-if="hasPerm('sysFileInfo:upload')">
<a-button>
<a-icon type="upload" />上傳檔案
</a-button>
</a-upload>
</a-col>
<a-col offset="2">
<a-button @click="ConfirmResult" type="primary">
<a-icon type="check"></a-icon> 确定
</a-button>
</a-col>
</a-row>
</a-modal>
</div>
</template>
<script>
  //導入當檔案上傳API,這個下篇檔案再講,很簡單。
import {
sysFileInfoUpload
} from '@/api/modular/system/fileManage'
//封裝的檔案大小格式化工具,總不能一個幾百兆當檔案展示幾十萬KB,多難看。
import {
FormatFileSize
} from '../../utils/util.js'
export default {
name: 'UploadUI',//元件當名稱
props: {//父元件傳過來當參數,實際上我沒用到,用了另外當方法。
url: {
type: String,
default: ''
},
isShow: {
type: Boolean,
default: false
},
fileGroup: {
type: String,
default: ''
},
fileType: {
type: String,
default: ''
}
},
data() {
return {
fileList: [],
uploadModal: false
}
},
created() {
// this.uploadModal = true
},
methods: {
  //這個函數是為了通知父元件,我完成了,你可以重新整理頁面了
ConfirmResult() {
this.uploadModal = false
this.$emit('complete', '200')
},
  //父元件調用這個函數顯示彈窗
ShowUploadModal() {
this.fileList = []
this.uploadModal = true
},
  //真正當檔案上傳函數
customRequest(data) {
var size = FormatFileSize((Number(data.file.size) / 1024).toFixed(2))
//檔案清單,用上傳當UID來唯一區分檔案
this.fileList.push({
uid: data.file.uid,
name: data.file.name,
size: size,
percent: 0,
backStatus: false,
uploadStatus: 0 // 0上傳中,1成功,2失敗
})
// 關閉檔案類型選擇提示框
this.pophover = false
// 檔案上傳前檢測
// console.log(this.queryParam.LabFileGroup)
// console.log(this.queryParam.LabFileType)
if (this.fileType == '' || this.fileGroup == '') {
// this.$message.warning('檔案類型和分組均不能為空,請選擇後再上傳');
this.$message.warning({
content: '檔案類型和分組均不能為空,請選擇後再上傳',
key: '1'//加這個key是為了當多個檔案校檢時,隻提示一次
})
return;
}
const formData = new FormData()
formData.append('file', data.file)
formData.append('group', this.fileGroup)
formData.append('fileType', this.fileType)
sysFileInfoUpload(formData, (res) => { // 上傳進度回調函數
this.uploadModal = true
var loaded = res.loaded
var total = res.total
// var percent = (loaded / total).toFixed(2) * 100--會出錯
var percent = ((loaded / total) * 100).toFixed(2) // 不會出錯
var uid = data.file.uid
for (var i = 0; i < this.fileList.length; i++) {
this.fileList[i].uid == uid ? this.fileList.uid = this.fileList[i].percent = percent : ''
}
if (percent == 100) {
for (var i = 0; i < this.fileList.length; i++) {
  //通過uid回寫檔案進度
if (this.fileList[i].uid == uid) {
this.fileList[i].backStatus = true
}
}
}
}).then((res) => {
// this.uploadModal = false
if (res.success) {
this.$message.success('上傳成功')
console.log(res)
for (var i = 0; i < this.fileList.length; i++) {
if (this.fileList[i].uid == data.file.uid) {
this.fileList[i].backStatus = false
}
}
// this.$refs.table.refresh()
} else {
this.$message.error('上傳失敗:' + res.message)
}
})
}
}
}
</script>
<style>
</style>           

效果圖:

vue-自己封裝一個多檔案上傳元件

沒有選擇檔案時的狀态

vue-自己封裝一個多檔案上傳元件

檔案上傳中的狀态

vue-自己封裝一個多檔案上傳元件

檔案完全上傳完成後的狀态

繼續閱讀