1000 lines
30 KiB
Vue
1000 lines
30 KiB
Vue
<template>
|
||
<div :class="$options.name" :show="show" :size="size" :style="style">
|
||
<div class="upload-list-tray">
|
||
<!-- 托盘头部 -->
|
||
<div class="header" ref="header" @dblclick.stop.prevent="dblclickHeader">
|
||
<div class="left">
|
||
<div class="title">
|
||
<span class="upload-count" slot="reference">上传队列</span>
|
||
<div class="upload-info" v-if="liveSpeed && liveSpeed > 0">
|
||
<el-divider :direction="`vertical`" />
|
||
<div class="info-item live-speed">
|
||
<label>速度</label>
|
||
<span>{{ $g.getSize(liveSpeed) }}/s</span>
|
||
</div>
|
||
<div class="info-item taken-time" v-if="takenTime && takenTime > 0">
|
||
<label>已耗时</label>
|
||
<span>{{
|
||
$g.date.toHourMinuteSecondByMillisecond(takenTime * 1000, {
|
||
zh: true,
|
||
hideMilliSecond: true,
|
||
hideZero: true,
|
||
})
|
||
}}</span>
|
||
</div>
|
||
<div class="info-item remain-time" v-if="remainTime && remainTime > 0">
|
||
<label>剩余</label
|
||
><span>{{
|
||
$g.date.toHourMinuteSecondByMillisecond(remainTime * 1000, {
|
||
zh: true,
|
||
hideMilliSecond: true,
|
||
hideZero: true,
|
||
})
|
||
}}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="right" @mousedown.stop>
|
||
<!-- 控制文件的图标按钮 -->
|
||
<div class="file-btns" v-if="showDelSuccessIconBtn || showErrorIconBtn">
|
||
<div
|
||
class="icon-btn"
|
||
v-if="showDelSuccessIconBtn"
|
||
@click.stop="clearAllSuccessFile"
|
||
title="清除所有已经成功的上传记录"
|
||
>
|
||
<i class="el-icon-delete" style="color: #67c23a"></i>
|
||
</div>
|
||
<div
|
||
class="icon-btn"
|
||
v-if="showErrorIconBtn"
|
||
@click.stop="clearAllErrorFile"
|
||
title="清除所有失败的上传记录"
|
||
>
|
||
<i class="el-icon-delete-solid" style="color: #f56c6c"></i>
|
||
</div>
|
||
<div
|
||
class="icon-btn"
|
||
v-if="showErrorIconBtn"
|
||
@click.stop="uploadAllErrorFile"
|
||
title="重新上传所有失败的文件"
|
||
>
|
||
<i class="el-icon-upload2" style="color: #409eff"></i>
|
||
</div>
|
||
<template v-if="uploadList.length > maxShowUploadFileCount">
|
||
<div
|
||
class="icon-btn"
|
||
v-if="expandAllUploadList"
|
||
@click.stop="expandAllUploadList = false"
|
||
title="折叠只显示前10条上传记录"
|
||
>
|
||
<i class="el-icon-folder" style="color: #409eff"></i>
|
||
</div>
|
||
<el-tooltip
|
||
v-else
|
||
:content="`请谨慎展开列表,这将导致您的网页很卡!`"
|
||
:effect="`dark`"
|
||
:enterable="false"
|
||
:placement="`top-start`"
|
||
:popper-class="`sg-el-tooltip`"
|
||
:transition="`none`"
|
||
:disabled="uploadList.length < 200"
|
||
>
|
||
<div
|
||
class="icon-btn"
|
||
@click.stop="expandAllUploadList = true"
|
||
title="展开所有上传记录"
|
||
>
|
||
<i class="el-icon-folder-opened" style="color: #409eff"></i>
|
||
</div>
|
||
</el-tooltip>
|
||
</template>
|
||
</div>
|
||
<!-- 控制托盘的图标按钮 -->
|
||
<div class="tray-btns">
|
||
<div
|
||
class="icon-btn"
|
||
v-if="size !== 'lg' && showRightBottomBtn"
|
||
@click.stop="toRightBottomPosition"
|
||
title="回到原来的位置"
|
||
>
|
||
<i class="el-icon-bottom-right"></i>
|
||
</div>
|
||
<div
|
||
class="icon-btn"
|
||
v-if="size !== 'mn'"
|
||
@click.stop="size = 'mn'"
|
||
title="最小化"
|
||
>
|
||
<i class="el-icon-minus"></i>
|
||
</div>
|
||
<div
|
||
class="icon-btn"
|
||
v-if="size !== 'md'"
|
||
@click.stop="size = 'md'"
|
||
title="还原"
|
||
>
|
||
<i :class="size === 'lg' ? 'el-icon-copy-document' : 'el-icon-d-caret'"></i>
|
||
</div>
|
||
<div
|
||
class="icon-btn"
|
||
v-if="size !== 'lg'"
|
||
@click.stop="size = 'lg'"
|
||
title="全屏"
|
||
>
|
||
<i class="el-icon-full-screen"></i>
|
||
</div>
|
||
<div class="icon-btn" @click.stop="close">
|
||
<i class="el-icon-close"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 上传中的文件列表 -->
|
||
<div class="upload-file-list">
|
||
<ul>
|
||
<li
|
||
v-for="(a, i) in expandAllUploadList ? uploadList : uploadList.slice(0, 10)"
|
||
:key="i"
|
||
:title="
|
||
a.size > 1024 * 1024 * 500
|
||
? `超大文件上传中,请耐心等待,切勿关闭或刷新浏览器!`
|
||
: ''
|
||
"
|
||
>
|
||
<div class="left">
|
||
<div class="icon-btns">
|
||
<el-button
|
||
title="移出上传队列"
|
||
:show="a.status === 'error'"
|
||
class="remove-icon-btn icon-btn"
|
||
type="danger"
|
||
icon="el-icon-delete-solid"
|
||
size="mini"
|
||
plain
|
||
circle
|
||
@click.stop="removeUploadFile(a)"
|
||
></el-button>
|
||
</div>
|
||
<!-- 动画加载旋转 -->
|
||
<div
|
||
class="fileLoading"
|
||
v-loading="a.percent < 100"
|
||
v-if="a.percent < 100 && a.status !== 'error'"
|
||
></div>
|
||
<!-- 上传成功icon -->
|
||
<div class="loadingSuccessIcon" v-if="a.percent === 100">
|
||
<i class="el-icon-success" style="color: #67c23a"></i>
|
||
</div>
|
||
<!-- 上传失败icon -->
|
||
<div class="loadingEorrorIcon" v-if="a.status === 'error'">
|
||
<i class="el-icon-error" style="color: #f56c6c"></i>
|
||
</div>
|
||
<span class="name" :title="a.filePath || a.name">
|
||
{{ a.filePath || a.name }}
|
||
<!-- {{ a.filePath && a.filePath.includes(`/`) ? `[路径:${a.filePath}]` : "" }} -->
|
||
</span>
|
||
<el-tag class="size" size="mini"
|
||
>{{ $g.getSize(a.size * (a.percent / 100)) }}/{{
|
||
$g.getSize(a.size)
|
||
}}</el-tag
|
||
>
|
||
<!-- <el-progress class="progress" :percentage="a.percent"></el-progress> -->
|
||
<el-progress
|
||
class="progress"
|
||
style="width: 100%"
|
||
type="line"
|
||
:percentage="parseInt(a.percent)"
|
||
:show-text="true"
|
||
:stroke-width="10"
|
||
:text-inside="false"
|
||
:color="'#409EFF'"
|
||
:define-back-color="'#eee'"
|
||
/>
|
||
</div>
|
||
<div class="right">
|
||
<span class="tip" :color="a.color">{{ a.tip }}</span>
|
||
<div class="icon-btns">
|
||
<el-button
|
||
:show="a.status === 'error'"
|
||
title="重新上传"
|
||
class="upload-icon-btn icon-btn"
|
||
type="primary"
|
||
icon="el-icon-upload2"
|
||
size="mini"
|
||
plain
|
||
circle
|
||
@click.stop="startUploadFile(a)"
|
||
></el-button>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<!-- 折叠按钮 -->
|
||
<sgCollapseBtn
|
||
style="z-index: 1"
|
||
:collapseLabel="`上传记录`"
|
||
v-model="expandAllUploadList"
|
||
v-if="uploadList.length > maxShowUploadFileCount"
|
||
/>
|
||
<div class="footer">
|
||
<div class="text" v-html="popoverContent"></div>
|
||
<div class="progress" v-if="uploadList.length > 1 && totalPercentage < 100">
|
||
<label>。总进度</label>
|
||
<el-progress
|
||
style="width: 100%"
|
||
type="line"
|
||
:percentage="parseInt(totalPercentage)"
|
||
:show-text="true"
|
||
:stroke-width="10"
|
||
:text-inside="false"
|
||
:color="'#409EFF'"
|
||
:define-back-color="'#eee'"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 拖拽移动窗体 -->
|
||
<sgDragMove
|
||
:data="dragMoveDoms"
|
||
:cursor="{
|
||
grab: 'default',
|
||
grabbing: 'default',
|
||
}"
|
||
nearPadding="10"
|
||
:disabled="size === 'lg' && disabledDragMove"
|
||
@dragStart="$emit(`dragStart`, dragMoveDoms)"
|
||
@dragging="
|
||
showRightBottomBtn = true;
|
||
$emit(`dragging`, dragMoveDoms);
|
||
"
|
||
@dragEnd="$emit(`dragEnd`, dragMoveDoms)"
|
||
mousemoveNearSide
|
||
/>
|
||
|
||
<!-- 拖拽改变窗体尺寸 -->
|
||
<sgDragSize
|
||
v-if="resizeable_"
|
||
:disabled="size === 'lg'"
|
||
@dragStart="disabledDragMove = true"
|
||
@dragging="draggingSize"
|
||
@dragEnd="disabledDragMove = false"
|
||
:minWidth="minWidth"
|
||
:minHeight="minHeight"
|
||
/>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import sgCollapseBtn from "./sgCollapseBtn";
|
||
import sgDragMove from "./sgDragMove";
|
||
import sgDragSize from "./sgDragSize";
|
||
export default {
|
||
name: "sgUploadTray",
|
||
components: {
|
||
sgCollapseBtn,
|
||
sgDragMove,
|
||
sgDragSize,
|
||
},
|
||
data() {
|
||
return {
|
||
maxShowUploadFileCount: 10, //默认展示上传数量
|
||
expandAllUploadList: false, //默认折叠
|
||
|
||
minWidth: 800,
|
||
minHeight: 40,
|
||
style_bk: null,
|
||
style: {},
|
||
resizeable_: true,
|
||
disabledDragMove: false, //屏蔽移动
|
||
show: false,
|
||
showRightBottomBtn: false,
|
||
size: "md", //lg全屏、md普通、mn最小
|
||
uploadList: [],
|
||
dragMoveDoms: [
|
||
/* {
|
||
canDragDom: elementDOM,//可以拖拽的位置元素
|
||
moveDom: elementDOM,//拖拽同步移动的元素
|
||
} */
|
||
], //可以拖拽移动的物体
|
||
|
||
lastUploadedTotalSize: 0, //记录上次已经下载完成的总大小
|
||
liveSpeed: 0, //瞬时下载速度(单位B)
|
||
takenTime: 0, //已耗时
|
||
remainTime: 0, //剩余下载时长
|
||
interval: null,
|
||
second: 1, //轮训间隔秒钟
|
||
|
||
successFileList: [], //成功文件列表
|
||
errorFileList: [], //失败文件列表
|
||
remainFileList: [], //剩余文件列表
|
||
};
|
||
},
|
||
props: ["data", "value", "resizeable", "position"],
|
||
watch: {
|
||
value: {
|
||
handler(d) {
|
||
this.show = d;
|
||
},
|
||
deep: true,
|
||
immediate: true,
|
||
},
|
||
show: {
|
||
handler(d) {
|
||
this.$emit(`input`, d);
|
||
},
|
||
deep: true,
|
||
immediate: true,
|
||
},
|
||
data: {
|
||
handler(d) {
|
||
this.uploadList = d || [];
|
||
},
|
||
deep: true,
|
||
immediate: true,
|
||
},
|
||
uploadList: {
|
||
handler(newValue, oldValue) {
|
||
if (newValue && Object.keys(newValue).length) {
|
||
this.interval || this.startUploadCalcLiveSpeed();
|
||
this.successFileList = newValue.filter((v) => v.percent == 100);
|
||
this.errorFileList = newValue.filter((v) => v.status === "error");
|
||
this.remainFileList = newValue.filter(
|
||
(v) => v.status !== "error" && v.status !== "success"
|
||
);
|
||
} else {
|
||
this.successFileList = [];
|
||
this.errorFileList = [];
|
||
this.remainFileList = [];
|
||
}
|
||
},
|
||
deep: true, //深度监听
|
||
immediate: true, //立即执行
|
||
},
|
||
resizeable: {
|
||
handler(newValue, oldValue) {
|
||
this.resizeable_ = newValue === "" || newValue;
|
||
},
|
||
deep: true, //深度监听
|
||
immediate: true, //立即执行
|
||
},
|
||
size: {
|
||
handler(newValue, oldValue) {
|
||
switch (newValue) {
|
||
case "lg":
|
||
case "mn":
|
||
this.style_bk = JSON.parse(JSON.stringify(this.style));
|
||
delete this.style.width, delete this.style.height;
|
||
break;
|
||
case "md":
|
||
this.style_bk && (this.style = JSON.parse(JSON.stringify(this.style_bk)));
|
||
break;
|
||
}
|
||
},
|
||
deep: true, //深度监听
|
||
immediate: true, //立即执行
|
||
},
|
||
},
|
||
computed: {
|
||
showDelSuccessIconBtn(d) {
|
||
return this.uploadList.some((v) => v.percent == 100);
|
||
},
|
||
showErrorIconBtn(d) {
|
||
return this.uploadList.some((v) => v.status == "error");
|
||
},
|
||
popoverContent(d) {
|
||
let r = [];
|
||
this.successFileList.length &&
|
||
r.push(
|
||
`已上传成功<span style="color: #67C23A;">${this.successFileList.length}</span>个`
|
||
);
|
||
this.errorFileList.length &&
|
||
r.push(`失败<span style="color: #F56C6C;">${this.errorFileList.length}</span>个`);
|
||
this.remainFileList.length &&
|
||
r.push(
|
||
`剩余<span style="color: #409EFF;">${this.remainFileList.length}</span>个`
|
||
);
|
||
if (this.uploadList.length) {
|
||
return `共计${this.uploadList.length}个文件,${
|
||
r.length ? `${r.join(",")}文件` : ``
|
||
}`;
|
||
} else {
|
||
return `暂无待上传文件`;
|
||
}
|
||
},
|
||
// 总体进度
|
||
totalPercentage() {
|
||
if (this.uploadList.length) {
|
||
return parseFloat(
|
||
((this.successFileList.length / this.uploadList.length) * 100).toFixed(2)
|
||
);
|
||
} else {
|
||
return 0;
|
||
}
|
||
},
|
||
// 真正上传中的文件对象数组
|
||
uploadingFiles(d) {
|
||
let uploadingFiles_ = (this.uploadList || []).filter(
|
||
(v) => v.percent < 100 && v.status !== "error" && v.status !== "success"
|
||
);
|
||
if (uploadingFiles_.length) {
|
||
this.$emit(`changeUploadingListClose`, {
|
||
path: this.position,
|
||
close: this.close,
|
||
});
|
||
} else {
|
||
this.$emit(`changeUploadingListClose`, null);
|
||
}
|
||
return uploadingFiles_;
|
||
},
|
||
},
|
||
mounted() {
|
||
this.$el.style.setProperty("--minWidth", `${this.minWidth}px`); //js往css传递局部参数
|
||
this.$el.style.setProperty("--minHeight", `${this.minHeight}px`); //js往css传递局部参数
|
||
this.dragMoveDoms = [
|
||
{
|
||
canDragDom: this.$refs.header, //托盘的头部可以拖拽
|
||
moveDom: this.$el, //拖拽的时候,整个上传列表一起跟随移动
|
||
},
|
||
];
|
||
},
|
||
destroyed() {
|
||
clearInterval(this.interval);
|
||
},
|
||
methods: {
|
||
// 开始计算瞬时下载速度
|
||
startUploadCalcLiveSpeed() {
|
||
clearInterval(this.interval);
|
||
this.interval = setInterval(() => {
|
||
this.calcLiveSpeed();
|
||
}, 1000 * this.second);
|
||
},
|
||
// 结束计算瞬时下载速度
|
||
endUploadCalcLiveSpeed(d) {
|
||
clearInterval(this.interval);
|
||
this.interval = null;
|
||
this.liveSpeed = 0;
|
||
this.takenTime = 0;
|
||
this.remainTime = 0;
|
||
},
|
||
// 没有上传进程文件才结束计算速度
|
||
ifNoUploadingFile_EndCalcLiveSpeed(d) {
|
||
this.uploadingFiles.length || this.endUploadCalcLiveSpeed();
|
||
},
|
||
// 计算瞬时下载速度
|
||
calcLiveSpeed(d) {
|
||
this.takenTime++;
|
||
let uploadList = this.uploadList;
|
||
if (uploadList.length) {
|
||
let totalSize = uploadList.reduce(
|
||
(prevResult, current) => prevResult + current.size,
|
||
0
|
||
); //求和需要上传的文件总大小
|
||
let uploadedTotalSize = uploadList.reduce(
|
||
(prevResult, current) => prevResult + current.size * (0.01 * current.percent),
|
||
0
|
||
); //求和已经上传的文件总大小
|
||
let remainTotalSize = totalSize - uploadedTotalSize; //剩余需要上传的文件
|
||
if (this.lastUploadedTotalSize) {
|
||
this.liveSpeed = (uploadedTotalSize - this.lastUploadedTotalSize) / this.second; //瞬时速度
|
||
this.remainTime = remainTotalSize / this.liveSpeed; //瞬时剩余时长
|
||
} else {
|
||
this.liveSpeed = 0;
|
||
}
|
||
this.lastUploadedTotalSize = uploadedTotalSize; //记录本次已经上传的总大小
|
||
} else {
|
||
this.endUploadCalcLiveSpeed();
|
||
}
|
||
},
|
||
clearAllSuccessFile() {
|
||
let successFileList = this.uploadList.filter((v) => v.percent == 100);
|
||
if (successFileList.length === 0)
|
||
return this.$message(`暂无可以移除的成功记录,请稍后再试!`);
|
||
this.$emit(`clearAllSuccessFile`, successFileList);
|
||
this.$nextTick(() => {
|
||
successFileList.forEach((file) => {
|
||
file.removeFile(); //移除原始队列
|
||
});
|
||
this.uploadList = this.uploadList.filter((v) => v.percent < 100);
|
||
});
|
||
},
|
||
clearAllErrorFile() {
|
||
let errorFileList = this.uploadList.filter((v) => v.status == "error");
|
||
if (errorFileList.length === 0)
|
||
return this.$message(`暂无可以移除的失败记录,请稍后再试!`);
|
||
this.$emit(`clearAllErrorFile`, errorFileList);
|
||
this.$nextTick(() => {
|
||
errorFileList.forEach((file) => {
|
||
file.removeFile(); //移除原始队列
|
||
});
|
||
this.uploadList = this.uploadList.filter((v) => v.status !== "error");
|
||
});
|
||
},
|
||
uploadAllErrorFile(d) {
|
||
let errorFileList = this.uploadList.filter((v) => v.status == "error");
|
||
errorFileList.forEach((fileData) => this.startUploadFile(fileData));
|
||
if (errorFileList.length === 0) return this.$message(`暂无失败记录,请稍后再试!`);
|
||
this.$emit(`uploadAllErrorFile`, errorFileList);
|
||
},
|
||
draggingSize({ style }) {
|
||
this.disabledDragMove = true;
|
||
this.style = style;
|
||
},
|
||
toRightBottomPosition(d) {
|
||
this.showRightBottomBtn = false;
|
||
let rect = this.$el.getBoundingClientRect();
|
||
this.$el.style.left = `${innerWidth - rect.width}px`;
|
||
this.$el.style.top = `${innerHeight - rect.height}px`;
|
||
// 用下面的写法会清除掉setProperty属性
|
||
/* this.$el.style = {
|
||
left: innerWidth - rect.width + "px",
|
||
top: innerHeight - rect.height + "px",
|
||
}; */
|
||
},
|
||
dblclickHeader(d) {
|
||
switch (this.size) {
|
||
case "lg":
|
||
this.size = "md";
|
||
break;
|
||
case "md":
|
||
this.size = "mn";
|
||
break;
|
||
case "mn":
|
||
this.size = "md";
|
||
break;
|
||
default:
|
||
}
|
||
},
|
||
removeAllFilesFromList() {
|
||
this.uploadList.forEach((file) => {
|
||
file.removeFile(); //移除原始队列
|
||
});
|
||
this.uploadList = []; //移除托盘队列
|
||
},
|
||
removeFileFromList(d) {
|
||
let file = this.uploadList.find((v) => v.uid == d.uid);
|
||
file.removeFile(); //移除原始队列
|
||
this.uploadList.splice(
|
||
this.uploadList.findIndex((v) => v.uid == d.uid),
|
||
1
|
||
); //移除托盘队列
|
||
},
|
||
// 重新上传失败的记录
|
||
startUploadFile(fileData) {
|
||
fileData.startUpload({ handleTrigger: true });
|
||
},
|
||
// 移出某一个队列文件
|
||
removeUploadFile(d) {
|
||
if (d.status === "error" || d.status === "success") {
|
||
this.removeFileFromList(d);
|
||
} else if (d.percent < 100) {
|
||
this.$confirm(`${d.name}正在上传中,确定要取消吗?`, `提示`, {
|
||
dangerouslyUseHTMLString: true,
|
||
confirmButtonText: `确定`,
|
||
cancelButtonText: `取消`,
|
||
type: "warning",
|
||
})
|
||
.then(() => {
|
||
this.$emit(`stopUpload`, [d]);
|
||
this.$nextTick(() => {
|
||
this.removeFileFromList(d);
|
||
this.ifNoUploadingFile_EndCalcLiveSpeed();
|
||
});
|
||
})
|
||
.catch(() => {});
|
||
} else {
|
||
this.removeFileFromList(d);
|
||
}
|
||
},
|
||
// 关闭托盘
|
||
close({ cb } = {}) {
|
||
let stopUploadList = this.uploadingFiles;
|
||
if (stopUploadList.length) {
|
||
this.$confirm(`您还有正在上传中的文件,确定要取消吗?`, `提示`, {
|
||
dangerouslyUseHTMLString: true,
|
||
confirmButtonText: `确定`,
|
||
cancelButtonText: `取消`,
|
||
type: "warning",
|
||
})
|
||
.then(() => {
|
||
this.show = false;
|
||
this.$emit(`stopUpload`, stopUploadList);
|
||
this.$nextTick(() => {
|
||
this.endUploadCalcLiveSpeed();
|
||
this.removeAllFilesFromList();
|
||
cb && cb(stopUploadList); //完成后回调
|
||
});
|
||
})
|
||
.catch(() => {});
|
||
} else {
|
||
this.show = false;
|
||
}
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.sgUploadTray {
|
||
$headerHeight: 40px; //头部高度
|
||
$footerHeight: 40px; //底部统计上传进度高度
|
||
$collapseBtnHeight: 30px; //折叠按钮高度
|
||
$minWidth: var(--minWidth); //托盘最小宽度
|
||
$minHeight: var(--minHeight); //托盘最小高度
|
||
$loadingWidth: 30px; //加载动画宽度(旋转全全)
|
||
$rightWidth: 200px; //右侧宽度
|
||
$sizeWidth: 200px; //文件大小宽度宽度
|
||
$progressWidth: 100px; //进度条宽度
|
||
$tipWidth: 100px; //提示文本宽度
|
||
// ----------------------------------------
|
||
z-index: 2001; //根据情况自己拿捏(太大了会遮住element的其他弹窗组件),v-loading默认是2000的z-index
|
||
user-select: none;
|
||
position: fixed;
|
||
right: 10px;
|
||
bottom: 10px;
|
||
width: $minWidth;
|
||
background-color: white;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
border: 1px solid #eee;
|
||
font-size: 14px;
|
||
display: none;
|
||
|
||
&[show] {
|
||
display: block;
|
||
}
|
||
|
||
&[size="lg"] {
|
||
left: 0 !important;
|
||
top: 0 !important;
|
||
width: 100vw;
|
||
height: 100vh;
|
||
transition: none;
|
||
.upload-file-list {
|
||
max-height: calc(100vh - 60px) !important;
|
||
}
|
||
}
|
||
|
||
&[size="md"] {
|
||
width: $minWidth;
|
||
height: revert;
|
||
}
|
||
|
||
&[size="mn"] {
|
||
width: $minWidth;
|
||
height: $minHeight;
|
||
}
|
||
|
||
.upload-list-tray {
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
padding-bottom: 20px;
|
||
width: 100%;
|
||
height: 100%;
|
||
position: relative;
|
||
|
||
.header {
|
||
flex-shrink: 0;
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
width: 100%;
|
||
height: $headerHeight;
|
||
box-sizing: border-box;
|
||
padding: 10px 20px;
|
||
/*从上往下线性渐变背景*/
|
||
background: linear-gradient(#409eff11, white);
|
||
color: #409eff;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.left {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-grow: 1;
|
||
|
||
.title {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: nowrap;
|
||
.upload-info {
|
||
display: flex;
|
||
align-items: center;
|
||
color: black;
|
||
flex-shrink: 0;
|
||
align-items: center;
|
||
font-weight: normal;
|
||
.info-item {
|
||
margin-right: 5px;
|
||
&:last-of-type {
|
||
margin-right: 0;
|
||
}
|
||
span {
|
||
font-family: DIN-Light;
|
||
color: #409eff;
|
||
}
|
||
&.live-speed {
|
||
span {
|
||
font-family: DIN-Black;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.icon-btns {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: nowrap;
|
||
.icon-btn {
|
||
cursor: pointer;
|
||
margin-right: 5px;
|
||
&:last-of-type {
|
||
margin-right: 0;
|
||
}
|
||
i {
|
||
pointer-events: none;
|
||
}
|
||
|
||
&:hover {
|
||
opacity: 0.618;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.right {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
flex-shrink: 0;
|
||
pointer-events: auto;
|
||
|
||
.icon-btn {
|
||
margin-left: 10px;
|
||
cursor: pointer;
|
||
|
||
i {
|
||
pointer-events: none;
|
||
}
|
||
|
||
&:hover {
|
||
opacity: 0.618;
|
||
}
|
||
&:first-of-type {
|
||
margin-left: 0;
|
||
}
|
||
}
|
||
|
||
.file-btns {
|
||
margin-left: 10px;
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
justify-content: flex-end;
|
||
box-sizing: border-box;
|
||
padding: 0 10px;
|
||
border-right: 1px solid #eee;
|
||
}
|
||
.tray-btns {
|
||
margin-left: 10px;
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
justify-content: flex-end;
|
||
}
|
||
}
|
||
}
|
||
|
||
.upload-file-list {
|
||
width: 100%;
|
||
flex-grow: 1;
|
||
overflow-y: auto;
|
||
height: max-content;
|
||
max-height: calc(
|
||
100vh - #{$headerHeight} - #{$footerHeight} - #{$collapseBtnHeight} - 40px
|
||
);
|
||
box-sizing: border-box;
|
||
padding: 0 20px;
|
||
|
||
ul {
|
||
width: 100%;
|
||
|
||
li {
|
||
line-height: 1.6;
|
||
box-sizing: border-box;
|
||
padding: 10px;
|
||
border-radius: 4px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
width: 100%;
|
||
|
||
.left {
|
||
width: calc(100% - #{$rightWidth});
|
||
display: flex;
|
||
align-items: center;
|
||
flex-grow: 1;
|
||
flex-shrink: 0;
|
||
// 上传队列记录左侧侧操作按钮
|
||
.icon-btns {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
.icon-btn {
|
||
display: none;
|
||
&[show] {
|
||
margin-right: 15px;
|
||
display: block;
|
||
}
|
||
}
|
||
}
|
||
.fileLoading {
|
||
flex-shrink: 0;
|
||
width: 30px;
|
||
margin-right: 5px;
|
||
height: 0;
|
||
transform: scale(0.5);
|
||
}
|
||
.loadingSuccessIcon,
|
||
.loadingEorrorIcon {
|
||
margin-right: 5px;
|
||
width: 30px;
|
||
height: 30px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
}
|
||
.name {
|
||
text-align: left;
|
||
margin-right: 10px;
|
||
width: calc(
|
||
100% - #{$loadingWidth} - #{$sizeWidth} - #{$progressWidth} - #{$rightWidth} -
|
||
20px
|
||
);
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
flex-shrink: 0;
|
||
flex-grow: 1;
|
||
}
|
||
|
||
.size {
|
||
margin-right: 10px;
|
||
max-width: $sizeWidth;
|
||
/*单行省略号*/
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.progress {
|
||
max-width: $progressWidth;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: nowrap;
|
||
flex-shrink: 0;
|
||
}
|
||
}
|
||
|
||
.right {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
width: $rightWidth;
|
||
|
||
.tip {
|
||
width: $tipWidth;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
flex-shrink: 0;
|
||
text-align: right;
|
||
|
||
&[color="red"] {
|
||
color: #f56c6c;
|
||
}
|
||
|
||
&[color="green"] {
|
||
color: #67c23a;
|
||
}
|
||
|
||
&[color="blue"] {
|
||
color: #409eff;
|
||
}
|
||
}
|
||
// 上传队列记录右侧操作按钮
|
||
.icon-btns {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
.icon-btn {
|
||
display: none;
|
||
&[show] {
|
||
margin-left: 15px;
|
||
display: block;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
&:hover {
|
||
background-color: #409eff11;
|
||
color: #409eff;
|
||
.left {
|
||
// 移入上传队列记录左侧操作按钮
|
||
.icon-btns {
|
||
.icon-btn {
|
||
display: block;
|
||
&:last-of-type {
|
||
margin-right: 10px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.right {
|
||
.tip {
|
||
margin-right: 15px;
|
||
}
|
||
// 移入上传队列记录右侧操作按钮
|
||
.icon-btns {
|
||
.icon-btn {
|
||
display: block;
|
||
&:first-of-type {
|
||
margin-left: 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.footer {
|
||
font-weight: normal;
|
||
flex-shrink: 0;
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
width: 100%;
|
||
height: $footerHeight;
|
||
box-sizing: border-box;
|
||
padding: 10px 20px;
|
||
margin-bottom: -20px;
|
||
background: linear-gradient(white, #eff2f7);
|
||
color: #909399;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: nowrap;
|
||
white-space: nowrap;
|
||
* {
|
||
font-weight: normal;
|
||
}
|
||
.text {
|
||
white-space: nowrap;
|
||
}
|
||
.progress {
|
||
max-width: 200px;
|
||
flex-grow: 1;
|
||
white-space: nowrap;
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: nowrap;
|
||
label {
|
||
white-space: nowrap;
|
||
flex-shrink: 0;
|
||
margin-right: 5px;
|
||
}
|
||
>>> .el-progress {
|
||
white-space: nowrap;
|
||
.el-progress__text {
|
||
font-weight: normal;
|
||
font-size: 14px !important;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|