[sgUploadTray] componente personalizado de la bandeja de carga, puede ver el progreso de la lista de carga en tiempo real

 [sgUploadTray] componente personalizado de la bandeja de carga, puede ver el progreso de la lista de carga en tiempo real

característica:

  1. Puede ser pantalla completa
  2. puede restaurar el tamaño
  3. se puede minimizar
  4. Puede volver a la posición predeterminada en la esquina inferior derecha
  5. Soporte para eliminar datos de la cola

Código fuente de 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)"
            mouseupNearSide />
    </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; //提示文本宽度
    // ----------------------------------------
    z-index: 1000; //根据情况自己拿捏
    position: fixed;
    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>

El componente sgDragMove utilizado aquí está aquí [sgDragMove] componente personalizado de arrastrar y soltar, solo admite arrastrar y soltar, y establece la distancia del límite de la pantalla de adsorción_El blog de su amado hermano fuerte-CSDN blog [sgDragMove] componente personalizado de arrastrar y soltar, solo admite arrastrar y soltar, y establece la distancia del límite de la pantalla de adsorción . https://blog.csdn.net/qq_37860634/article/details/131721634

Supongo que te gusta

Origin blog.csdn.net/qq_37860634/article/details/131721614
Recomendado
Clasificación