173 lines
4.7 KiB
Vue
173 lines
4.7 KiB
Vue
|
<!--
|
|||
|
* @Author: Billy
|
|||
|
* @Date: 2020-09-30 08:54:15
|
|||
|
* @LastEditors: Billy
|
|||
|
* @LastEditTime: 2021-06-06 02:21:47
|
|||
|
* @Description: 文件上传组件(部分接口仿照Element的Upload组件)
|
|||
|
-->
|
|||
|
|
|||
|
<template>
|
|||
|
<div>
|
|||
|
<div class="upload" @click="handleBtnFileUpload">
|
|||
|
<slot></slot>
|
|||
|
</div>
|
|||
|
<input
|
|||
|
type="file"
|
|||
|
name="resource"
|
|||
|
:multiple="multiple"
|
|||
|
ref="resource"
|
|||
|
@change="handleFileInputChange"
|
|||
|
/>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
<script>
|
|||
|
import UploadAxios from "../../api/Disk/_UploadAxios.js";
|
|||
|
|
|||
|
export default {
|
|||
|
props: {
|
|||
|
disabled: { type: Boolean, default: false }, // 是否不可用
|
|||
|
beforeUploadAll: Function, // 上传所有文件之前的钩子,返回false将会中止所有文件上传
|
|||
|
beforeUpload: Function, // 上传单个文件之前的钩子,返回false将会中止单个文件上传
|
|||
|
onBegin: Function, // 开始上传单个文件时的钩子,后于beforeUpload,文件必定会开始上传
|
|||
|
onChange: Function,
|
|||
|
onSuccess: Function,
|
|||
|
onProgress: Function,
|
|||
|
onError: Function,
|
|||
|
onExceed: Function,
|
|||
|
autoUpload: { type: Boolean, default: true },
|
|||
|
multiple: { type: Boolean, default: false },
|
|||
|
limit: { type: Number },
|
|||
|
action: { type: String, required: true },
|
|||
|
extraData: Object,
|
|||
|
fileSizeAttrName: String, // 文件大小 字段对应的字段名(如果不传,则每个文件的大小不会上传服务器)
|
|||
|
fileNameAttrName: String // 文件名 字段对应的字段名(如果不传,则每个文件的文件名不会上传服务器)
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
fileInput: null
|
|||
|
};
|
|||
|
},
|
|||
|
mounted() {
|
|||
|
this.fileInput = this.$refs["resource"];
|
|||
|
this.fileInput.style.display = "none";
|
|||
|
},
|
|||
|
methods: {
|
|||
|
setFiles(files) {
|
|||
|
if (this.fileInput) {
|
|||
|
this.fileInput.files = files;
|
|||
|
} else {
|
|||
|
throw new Error("fileInput 未初始化");
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 清空选择的所有文件(恢复input的初始状态,目的是使onChange事件在选择同一文件时也会触发)
|
|||
|
clearFiles() {
|
|||
|
this.fileInput.value = null;
|
|||
|
},
|
|||
|
|
|||
|
// 上传按钮被物理点击
|
|||
|
handleBtnFileUpload() {
|
|||
|
if (!this.disabled) this.fileInput && this.fileInput.click();
|
|||
|
},
|
|||
|
|
|||
|
// 选择要上传的文件时
|
|||
|
handleFileInputChange(event) {
|
|||
|
let files = event.target.files;
|
|||
|
this.onChange && this.onChange(files);
|
|||
|
if (this.autoUpload) {
|
|||
|
this.upload(files);
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 上传文件
|
|||
|
upload(files) {
|
|||
|
let _files = files ? files : this.fileInput.files;
|
|||
|
if (this.beforeUploadAll) {
|
|||
|
const beforeAll = this.beforeUploadAll(_files);
|
|||
|
if (beforeAll && beforeAll.then) {
|
|||
|
beforeAll
|
|||
|
.then(result => {
|
|||
|
if (result !== false) {
|
|||
|
this.$$_upload(_files);
|
|||
|
}
|
|||
|
})
|
|||
|
.catch(err => {
|
|||
|
// console.log("err :>> ", err);
|
|||
|
});
|
|||
|
} else if (beforeAll !== false) {
|
|||
|
this.$$_upload(_files);
|
|||
|
}
|
|||
|
} else {
|
|||
|
this.$$_upload(_files);
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* @description 上传多个文件
|
|||
|
* @param {Array.<File>} files 表单文件对象数组
|
|||
|
*/
|
|||
|
$$_upload(files) {
|
|||
|
if (this.beforeUpload) {
|
|||
|
for (const file of files) {
|
|||
|
const before = this.beforeUpload(file, files);
|
|||
|
if (before && before.then) {
|
|||
|
before.then(result => {
|
|||
|
if (result !== false) {
|
|||
|
this.$_upload(file, files);
|
|||
|
}
|
|||
|
});
|
|||
|
} else if (before !== false) {
|
|||
|
this.$_upload(file, files);
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
for (const file of files) {
|
|||
|
this.$_upload(file, files);
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* @description 上传单个文件
|
|||
|
* @param {File} file 表单文件对象
|
|||
|
* @param {Array.<File>} files 表单文件对象数组
|
|||
|
* @returns {Function} 用于中止上传的函数
|
|||
|
*/
|
|||
|
$_upload(file, files) {
|
|||
|
if (this.limit && this.limit > 0) {
|
|||
|
if (files.length > this.limit) {
|
|||
|
this.onExceed && this.onExceed(files);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
let extraData = JSON.parse(JSON.stringify(this.extraData));
|
|||
|
|
|||
|
extraData[this.fileSizeAttrName] = file.size;
|
|||
|
extraData[this.fileNameAttrName] = file.name;
|
|||
|
|
|||
|
// let slicedBlob = file.slice(start);
|
|||
|
|
|||
|
return UploadAxios.upload(
|
|||
|
this.action,
|
|||
|
file,
|
|||
|
// slicedBlob,
|
|||
|
extraData,
|
|||
|
this.onBegin,
|
|||
|
this.onSuccess,
|
|||
|
this.onProgress,
|
|||
|
this.onError,
|
|||
|
"file"
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
};
|
|||
|
</script>
|
|||
|
<style lang="scss" scoped>
|
|||
|
.upload {
|
|||
|
display: inline-block;
|
|||
|
text-align: center;
|
|||
|
cursor: pointer;
|
|||
|
outline: 0;
|
|||
|
}
|
|||
|
</style>
|