【sgUploadTray】上传托盘自定义组件,可实时查看上传列表进度
特性:
- 可以全屏
- 可以还原尺寸
- 可以最小化
- 可以回到右下角默认位置
- 支持删除队列数据
sgUploadTray源码
<template>
<div :class="$options.name" :show="show" :size="traySize">
<div class="upload-list">
<div class="header" ref="header" @dblclick.stop.prevent="dblclickHeader">
<div class="left">
<div class="title"><span>上传队列:{{ uploadList.length }}个文件</span></div>
</div>
<div class="right">
<div v-if="traySize !== 'lg' && showRightBottomBtn" @click.stop="toRightBottomPosition" title="回到原来的位置">
<i class="el-icon-bottom-right"></i>
</div>
<div v-if="traySize !== 'mn'" @click.stop="traySize = 'mn'" title="最小化">
<i class="el-icon-minus"></i>
</div>
<div v-if="traySize !== 'md'" @click.stop="traySize = 'md'" title="还原">
<i :class="traySize === 'lg' ? 'el-icon-copy-document' : 'el-icon-d-caret'"></i>
</div>
<div v-if="traySize !== 'lg'" @click.stop="traySize = 'lg'" title="全屏">
<i class="el-icon-full-screen"></i>
</div>
<div @click.stop="close">
<i class="el-icon-close"></i>
</div>
</div>
</div>
<div class="file-list">
<ul>
<li v-for="(a, i) in uploadList" :key="i">
<div class="left">
<span class="name" :title="a.name">{{ a.name }}</span>
<el-tag class="size" size="mini">{{ getSize(a.size) }}</el-tag>
<el-progress class="progress" :percentage="a.percent"></el-progress>
</div>
<div class="right">
<span class="tip" :color="a.color">{{ a.tip }}</span>
<el-button class="remove-icon-btn" type="primary" icon="el-icon-close" size="mini" plain circle
@click.stop="remove(a)"></el-button>
</div>
</li>
</ul>
</div>
</div>
<sgDragMove :data="dragMoveDoms" nearPadding="50" :disabled="traySize === 'lg'"
@dragStart="$emit(`dragStart`, dragMoveDoms)"
@dragging="showRightBottomBtn = true; $emit(`dragging`, dragMoveDoms)"
@dragEnd="$emit(`dragEnd`, dragMoveDoms)" />
</div>
</template>
<script>
import sgDragMove from "@/vue/components/admin/sgDragMove";
export default {
name: 'sgUploadTray',
components: {
sgDragMove
},
data() {
return {
show: false,
showRightBottomBtn: false,
traySize: 'md',//lg全屏、md普通、mn最小
uploadList: [],
dragMoveDoms: [
/* {
canDragDom: elementDOM,//可以拖拽的位置元素
moveDom: elementDOM,//拖拽同步移动的元素
} */
],//可以拖拽移动的物体
}
},
props: ["data", "value"],
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,
},
},
mounted() {
this.dragMoveDoms = [
{
canDragDom: this.$refs.header,//托盘的头部可以拖拽
moveDom: this.$el,//拖拽的时候,整个上传列表一起跟随移动
}
];
},
methods: {
toRightBottomPosition(d) {
this.showRightBottomBtn = false;
let rect = this.$el.getBoundingClientRect();
this.$el.style = {
left: innerWidth - rect.width + "px",
top: innerHeight - rect.height + "px",
}
},
dblclickHeader(d) {
switch (this.traySize) {
case 'lg':
this.traySize = 'md'
break;
case 'md':
this.traySize = 'mn'
break;
case 'mn':
this.traySize = 'md'
break;
default:
}
},
close(d) {
let stopUploadList = this.uploadList.filter(v => v.percent < 100 && (v.type !== 'error' && v.type !== 'success'));
if (stopUploadList && stopUploadList.length) {
this.$confirm(`您还有正在上传中的文件,确定要取消吗?`, `提示`, { dangerouslyUseHTMLString: true, confirmButtonText: `确定`, cancelButtonText: `取消`, type: "warning" }).then(() => {
this.show = false;
this.$emit(`stopUpload`, stopUploadList);
}).catch(() => {
});
} else {
this.show = false;
}
},
remove(d) {
if (d.type === 'error' || d.type === 'success') {
this.uploadList.splice(this.uploadList.findIndex(v => v.uid == d.uid), 1)
} else if (d.percent < 100) {
this.$confirm(`${d.name}正在上传中,确定要取消吗?`, `提示`, { dangerouslyUseHTMLString: true, confirmButtonText: `确定`, cancelButtonText: `取消`, type: "warning" }).then(() => {
this.$emit(`stopUpload`, [d]);
}).catch(() => {
});
} else {
this.uploadList.splice(this.uploadList.findIndex(v => v.uid == d.uid), 1)
}
},
getSize(d) {
let r = '';
d < 1024 && (r = d + 'B');
d > 1024 && (r = (d / 1024).toFixed(2) + 'KB');
d > 1024 * 1024 && (r = (d / (1024 * 1024)).toFixed(2) + 'MB');
d > 1024 * 1024 * 1024 && (r = (d / (1024 * 1024 * 1024)).toFixed(2) + 'GB');
return r
},
}
};
</script>
<style lang="scss" scoped>
.sgUploadTray {
$width: 600px; //托盘宽度
$listMaxHeight: $width; //托盘宽度
$rightWidth: 200px; //右侧宽度
$sizeWidth: 100px; //文件大小宽度宽度
$progressWidth: 50px; //进度条宽度
$tipWidth: 100px; //提示文本宽度
// ----------------------------------------
position: fixed;
z-index: 2;
right: 10px;
bottom: 10px;
width: $width;
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;
}
&[size="md"] {
width: $width;
height: revert;
}
&[size="mn"] {
width: $width;
height: 56px;
}
.upload-list {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding-bottom: 20px;
width: 100%;
.header {
flex-shrink: 0;
font-size: 16px;
font-weight: bold;
width: 100%;
box-sizing: border-box;
padding: 20px;
/*从上往下线性渐变背景*/
background: linear-gradient(#743a7211, white);
color: #743a72;
display: flex;
justify-content: space-between;
align-items: center;
.left {
flex-grow: 1;
.title {}
}
.right {
display: flex;
align-items: center;
justify-content: flex-end;
flex-shrink: 0;
&>* {
margin-left: 10px;
cursor: pointer;
pointer-events: auto;
&:hover {
opacity: 0.618;
}
}
}
}
.file-list {
width: 100%;
flex-grow: 1;
overflow-y: auto;
max-height: $listMaxHeight;
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 {
display: flex;
align-items: center;
.name {
margin-right: 10px;
max-width: $width - $sizeWidth - $progressWidth - $rightWidth - 20px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.size {
margin-right: 10px;
max-width: $sizeWidth;
/*单行省略号*/
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.progress {
max-width: $progressWidth;
}
}
.right {
display: flex;
align-items: center;
justify-content: flex-end;
max-width: $rightWidth;
.tip {
margin-right: 10px;
max-width: $tipWidth;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
&[color="red"] {
color: #F56C6C;
}
&[color="green"] {
color: #67C23A;
}
&[color="blue"] {
color: #409EFF;
}
}
.btns {
.remove-icon-btn {
width: 20px;
height: 20px;
}
}
}
// cursor: pointer;
&:hover {
background-color: #743a7211;
color: #743a72;
}
}
}
}
}
}
</style>
这里面用到的sgDragMove组件在这里【sgDragMove】自定义拖拽组件,仅支持拖拽、设置吸附屏幕边界距离_你挚爱的强哥的博客-CSDN博客【sgDragMove】自定义拖拽组件,仅支持拖拽、设置吸附屏幕边界距离。https://blog.csdn.net/qq_37860634/article/details/131721634