<template>
<div class="minioBox">
<el-button
v-if="model === 'button' && fileList.length < maxLen"
style="
margin-right: 10px;
color: #3f51b5;
font-size: 14px;
line-height: 20px;
"
:disabled="disabled"
@click="getFileName"
size="mini"
type="text"
>+上传</el-button
>
<el-button
v-if="model === 'text' && fileList.length < maxLen"
style="
marginleft: 20px;
color: #909399;
font-size: 13px;
line-height: 20px;
"
:disabled="disabled"
@click="getFileName"
class="el-icon-circle-plus-outline"
size="mini"
type="text"
>上传文件</el-button
>
<input
:accept="fileTypeList.join(',')"
type="file"
multiple="multiple"
ref="minIoFile"
v-show="false"
@change="getFile"
/>
<ul class="uploadFileList">
<li v-for="(item, index) of fileList" :key="index" style="display: flex">
<span>{{ index + 1 }}.</span>
<el-select
v-model="item.dataStream"
size="mini"
style="width: 100px; margin: 0 20px"
v-if="updateComponent && isUpDataStream"
placeholder="数据流"
@change="changeItem"
>
<el-option
v-for="(stream, key) in streamList"
:key="stream + key"
:label="stream"
:value="stream"
>
</el-option>
</el-select>
<span class="subString">{{
item.name.length > 10 ? item.name.substring(0, 10) + "..." : item.name
}}</span
>
<span>({{ (item.size / 1024 / 1024).toFixed(2) }}M)</span>
<span v-if="item.percent === 100" style="color: #4052b5"
><i class="el-icon-success"></i>上传成功</span
>
<div v-if="!isUpload" class="floatRight" style="float: right">
<i
class="el-icon-close"
style="cursor: pointer"
@click="deleteMinioFile(index)"
></i>
</div>
</li>
</ul>
</div>
</template>
<script>
import AWS from "aws-sdk";
export default {
props: {
model: {
type: String,
default: "button",
},
maxLen: {
type: Number,
default: 2,
},
progress: {
type: Boolean,
default: false,
},
fileTypeList: {
type: Array,
default: [".*"],
},
disabled: {
type: Boolean,
default: false,
},
isUpDataStream: {
type: Boolean,
default: false,
},
},
data() {
return {
streamList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
fileList: [],
fileCopyList: [],
fileUp: false,
isUpload: false,
updateComponent: true,
uploadList: [],
timer: null,
updateObject: {},
usedTime: 0,
uploadTimer: null,
loadedTotal: 0,
fileTotal: 0,
s3: {},
dataInfo: {
accessKeyId: JSON.parse(localStorage.getItem("dataInfo")).ak,
secretAccessKey: JSON.parse(localStorage.getItem("dataInfo")).sk,
endpoint: JSON.parse(localStorage.getItem("dataInfo")).point,
s3ForcePathStyle: JSON.parse(localStorage.getItem("dataInfo"))
.s3ForcePathStyle,
signatureVersion: "v4",
},
};
},
created() {},
methods: {
changeItem(item, index) {
this.updateComponent = false;
setTimeout(() => {
this.updateComponent = true;
}, 0);
},
selectLen() {
let _vm = this;
return new Promise((resolve, reject) => {
resolve(_vm.fileList.length);
});
},
upload(obj) {
if (this.isUpDataStream) {
let hasStream = true;
this.fileList.forEach((item) => {
if (!item.dataStream) {
hasStream = false;
}
});
if (!hasStream) {
this.$message.warning("请选择数据流");
this.$emit("hasStream", true);
return;
}
}
this.dataInfo = {
accessKeyId: JSON.parse(localStorage.getItem("dataInfo")).ak,
secretAccessKey: JSON.parse(localStorage.getItem("dataInfo")).sk,
endpoint: JSON.parse(localStorage.getItem("dataInfo")).point,
s3ForcePathStyle: JSON.parse(localStorage.getItem("dataInfo"))
.s3ForcePathStyle,
signatureVersion: "v4",
};
this.s3 = new AWS.S3(this.dataInfo);
if (this.fileList.length === 0) {
let nullFile = {
type: obj,
list: false,
};
this.$emit("uploadSuccess", nullFile);
}
this.updateObject = obj;
this.uploadList = [];
this.isUpload = true;
this.timer = setInterval(() => {
this.fileUp = !this.fileUp;
}, 0);
this.fileList.forEach((item) => {
this.fileTotal += item.size;
});
this.fileList.map((item, index) => {
this.uploadMinIo(item, index);
});
},
clearfield() {
this.fileList = [];
this.uploadList = [];
this.isUpload = false;
},
deleteMinioFile(index) {
this.fileList.splice(index, 1);
this.$refs.minIoFile.value = "";
},
getFileName() {
let inputDOM = this.$refs.minIoFile;
inputDOM.click();
},
getFile(event) {
let files = this.$refs.minIoFile.files;
let fileSwitch = true;
if (files.length > 0) {
for (let i = 0; i < files.length; i++) {
if ((files[i].size / 1024 / 1024 / 1024).toFixed(2) > 6400) {
this.$message({
message: `${files.name}超过文件的最大长度`,
type: "warning",
});
fileSwitch = false;
}
}
if (fileSwitch) {
for (let i = 0; i < files.length; i++) {
if (this.fileList.length < this.maxLen) {
this.fileList.push(files[i]);
// let obj = {
// name: files[i].name,
// dataStream: "",
// percent: 0,
// size: files[i].size,
// };
// this.fileCopyList.push(obj);
this.$emit("fileList", this.fileList);
} else {
if (this.maxLen != 1 && this.maxLen != 6) {
this.$message.warning(`最多只能够添加6个文件`);
return;
} else {
this.$message.warning(`最多只能够添加${this.maxLen}个文件`);
return;
}
}
}
}
}
},
uploadMinIo(file, index) {
let vm = this;
vm.uploadTimer = setInterval(() => {
vm.usedTime += 1;
}, 1000);
vm.fileUp = true;
let YY = new Date().getFullYear();
let MM = new Date().getMonth() + 1;
let DD = new Date().getDate();
let fileName = file.name;
let uuid = vm.generateUUID();
if (file) {
let params = {
Bucket: JSON.parse(localStorage.getItem("dataInfo"))
.bucketName /* required */,
Key: `${YY}/${MM}/${DD}/${uuid}/${fileName}` /* required */,
Body: file,
};
this.s3
.upload(params, function (err, data) {
clearInterval(vm.uploadTimer);
if (err) {
vm.$emit("uploadFail", err);
} else {
let fileObj = {
dataFile: file.name,
dataType: file.type,
dataAddr: data.Location,
dataKey: data.Key,
bucket: data.Bucket,
dataSize: file.size,
dataStream: file.dataStream,
};
vm.uploadList.push(fileObj);
if (vm.uploadList.length === vm.fileList.length) {
let time = setTimeout(() => {
clearInterval(vm.timer);
vm.fileUp = true;
clearTimeout(time);
}, 500);
let obj = {
type: vm.updateObject,
list: vm.uploadList,
};
vm.$emit("uploadSuccess", obj);
}
}
})
.on("httpUploadProgress", (e) => {
let per = parseInt(e.loaded, 10) / parseInt(e.total, 10);
per = Number((per * 100).toFixed(0));
file.percent = per;
file.loaded = e.loaded;
let uploadData = {
per: per,
time: vm.usedTime,
};
file.uploadData = uploadData;
vm.getUploadTime();
});
}
},
getUploadTime() {
this.loadedTotal = 0;
this.fileList.forEach((item) => {
if (item.loaded) {
this.loadedTotal += parseInt(item.loaded);
}
});
let need = 0;
let per = (this.loadedTotal / this.fileTotal).toFixed(2) * 100;
need = ((this.usedTime / (per / 100)) * (1 - per / 100)).toFixed(2);
let neew = this.getRevTime(parseInt(need));
let obj = {
per: parseInt(per),
needTime: neew,
};
this.$emit("uploadProgress", obj);
},
getRevTime(time) {
if (time / 3600 > 24) {
return `大于一天`;
} else if (time / 3600 > 1) {
let hh = Math.floor(time / 3600);
let mm = Math.floor((time % 3600) / 60);
return `大约需要${hh}时${mm}分`;
} else if (time / 60 > 1) {
let mm = Math.floor(time / 60);
let ss = Math.floor(time % 60);
return `大约需要${mm}分${ss}秒`;
} else {
return `大约需要${time}秒`;
}
},
generateUUID() {
var d = new Date().getTime();
if (window.performance && typeof window.performance.now === "function") {
d += performance.now(); // use high-precision timer if available
}
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
/[xy]/g,
function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
}
);
return uuid;
},
},
};
</script>
<style lang="scss" scoped>
.minioBox {
color: #000000;
padding: 0px;
width: 90%;
line-height: 20px;
min-height: 40px;
.uploadFileList {
width: 100%;
list-style: none;
margin-top: 5px;
padding: 0;
li {
height: 40px;
line-height: 26px;
margin: 0px !important;
span {
vertical-align: top;
}
.subString {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 40%;
display: inline-block;
}
i {
margin: 5px 5px 0 0;
}
.el-icon-close,
.el-icon-upload-success {
float: right;
}
.upload-success {
color: green;
}
.upload-fail {
color: red;
}
}
li:hover {
background-color: #f5f7fa;
}
li:first-child {
margin-top: 10px;
}
/deep/ .progress {
margin-top: 2px;
width: 200px;
height: 14px;
margin-bottom: 10px;
overflow: hidden;
background-color: #f5f5f5;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
display: inline-block;
.progress-bar {
background-color: rgb(92, 184, 92);
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.14902) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.14902) 50%,
rgba(255, 255, 255, 0.14902) 75%,
transparent 75%,
transparent
);
background-size: 40px 40px;
box-shadow: rgba(0, 0, 0, 0.14902) 0px -1px 0px 0px inset;
box-sizing: border-box;
color: rgb(255, 255, 255);
display: block;
float: left;
font-size: 12px;
height: 20px;
line-height: 20px;
text-align: center;
transition-delay: 0s;
transition-duration: 0.6s;
transition-property: width;
transition-timing-function: ease;
width: 266.188px;
}
}
}
}
</style>