【sgUploadTray】上传托盘自定义组件,可实时查看上传列表进度

news2024/11/20 1:43:41

 【sgUploadTray】上传托盘自定义组件,可实时查看上传列表进度

特性:

  1. 可以全屏
  2. 可以还原尺寸
  3. 可以最小化
  4. 可以回到右下角默认位置
  5. 支持删除队列数据

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/755883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

架构训练营学习笔记3-5:消息队列备选架构设计实战

本文属于架构训练营学习笔记系列&#xff1a;模块3的案例讲解 总的来说&#xff0c;这篇从更高的维度去讲&#xff0c;而不是关注消息队列的常见问题&#xff1a;比如消息如何发送&#xff0c;消息如何不丢失 &#xff0c;消息如何不重复。总体上分为2部分&#xff1a;利益干系…

LaTex 1【字体、符号、表格】

​&#xff08;上一期已经安装完软件&#xff0c;但是突然出现了一点子问题不会解决&#xff0c;先用overleaf来学习吧&#xff0c;网站还是很给力的&#xff09; 关键字部分&#xff1a; \quad:代表空格【无论你打多少个空格都不是空格&#xff0c;要输入“\quad”】 字体部分…

github进不去的解决办法

github就凭运气进吧&#xff0c;偶尔能进去。 介绍几个可以快速进的办法&#xff1a; 第一个&#xff0c;安装插件&#xff1a;&#xff08;在microsoft搜索watt toolkit插件并安装&#xff09; 然后勾选github选项&#xff1a; 接着返回你github网站就可以了。 第二个&#…

简单工厂模式详解

文章目录 前言一、简单工厂模式定义二、举个例子三、简单工厂模式的缺点总结 前言 本篇我们了解一下简单工厂模式&#xff0c;它是设计模式的雏形&#xff0c;是学习设计模式的开端&#xff0c;我会结合案例说明它的设计思路。 一、简单工厂模式定义 简单工厂模式并不是GoF23…

JSX的基础使用

1. JSX嵌入变量作为子元素的使用 ①当变量是Number、String、Array类型时&#xff0c;可以直接显示&#xff1b; ②当变量是null、undefined、Boolean类型时&#xff0c;内容为空&#xff1b; 若想要展示nul、undefined、Boolean类型&#xff0c;转字符串&#xff1b;转换方式…

堆--二叉树的特有形式

目录 前言1.二叉树的顺序结构及实现1.1二叉树的顺序结构1.2堆的概念及结构 2.堆的功能函数的实现2.1堆结构体的定义2.2堆的初始化2.3堆的插入2.4 获取堆是否为空、堆大小、堆顶元素的函数2.5堆的销毁2.6对利用堆结构数组的数据建堆2.7堆的删除堆结构的源码 3.堆排序建堆的时间复…

2核4G服务器能安装多少个网站?亲测

2核4G服务器能安装多少个网站&#xff1f;2核4g配置能承载多少个网站&#xff1f;一台2核4G服务器可以安装多少个网站&#xff1f;阿腾云2核4G5M带宽服务器目前安装了14个网站&#xff0c;从技术角度是没有限制的&#xff0c;只要云服务器性能够用&#xff0c;想安装几个网站就…

AE关键帧

关键帧 根据上次说到的五大变换&#xff0c;找准起始时间点和起始动作再去找结束时间点和结束动作&#xff0c;其中包括可使用贝塞尔曲线对锚点进行拖拽&#xff0c;使其完成曲线运动 快捷键 n删除右侧&#xff0c;b删除左侧&#xff0c;ctrlshiftd裁剪&#xff0c;ctrld复制…

我记忆中的电脑城

目录 一、我记忆中的电脑城 二、电脑城衰退 三、拥抱趋势 在过去很长一段时间里&#xff0c;想要购买电子设备都逃不开一个叫“电脑城”的地方&#xff0c;那里鱼龙混杂良莠不齐&#xff0c;是令许多人记忆深刻分外难忘之处。 一、我记忆中的电脑城 想起上一次去电脑城&…

ylb-接口11实名认证

总览&#xff1a; 在web模块config包下&#xff0c;创建实名认证的一个配置类JdwxRealnameConfig&#xff1a; package com.bjpowernode.front.config;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype…

【NI USRP】 USRP 硬件资源和性能是怎么样的呢?是如何构成的呢

B系列 型号频段最大带宽通道FPGAADI 芯片B200mini70 MHZ - 6 GHZ56 MHz1X1Xilinx Spartan-6 XC6SLX150AD9364B200mini-i70 MHZ - 6 GHZ56 MHz1X1Xilinx Spartan-6 XC6SLX75AD9364B205mini-i70 MHZ - 6 GHZ56 MHz1X1Xilinx Spartan-6 XC6SLX75AD9364B20070 MHZ - 6 GHZ56 MHz1X…

AN OVERVIEW OF LANGUAGE MODELS RECENT DEVELOPMENTS AND OUTLOOK

LLM系列相关文章&#xff0c;针对《AN OVERVIEW OF LANGUAGE MODELS: RECENT DEVELOPMENTS AND OUTLOOK》的翻译。 语言模型综述&#xff1a;近年来的发展与展望 摘要1 引言2 语言模型的类型2.1 结构化LM2.2 双向LM2.3 置换LM 3 语言单元3.1 字符3.2 单词和子单词3.2.1 基于统…

Java正则表达式捕获组

捕获组是将多个字符视为一个单元的一种方法。 它们是通过将要分组的字符放在一组括号中来创建的。 例如&#xff0c;正则表达式(dog)创建包含字母d&#xff0c;o和g的单个组。 捕获组通过从左到右计算它们的左括号来编号。 在表达式((A)(B(C)))中&#xff0c;例如&#xff0c;…

Xline 源码解读(一) —— 初识 CURP 协议

01、Xline是什么 Xline 是一款开源的分布式 KV 存储引擎&#xff0c;其核心目的是实现高性能的跨数据中心强一致性&#xff0c;提供跨数据中心的meatdata 管理。那么 Xline 是怎么实现这种高性能的跨数据中心强一致性的呢&#xff1f;这篇文章就将带领大家一起来一探究竟。 02…

GAMES101 OpenCV环境安装

文章目录 Opencv 库编译Step 1.下载源码Step 2. 使用CMake编译Step3. 解决CMake 过程中的报错错误1&#xff1a; 错误的Python版本:错误1 解决办法 错误2&#xff1a;下载ippicv_2020_win_ia32_20191018_general.zip失败错误2 解决办法 错误3&#xff1a;ffmpeg相关文件下载失败…

ROS学习笔记(0):几个重要概念:节点、消息、主题、服务

1、节点&#xff08;node&#xff09; 节点是进行运算任务的进程。一个系统可以由很多节点组成&#xff0c;节点也可以称为软件模块。 ROS是以节点的形式开发的&#xff0c;节点是根据其目的&#xff0c;可以细分的可执行程序的最小单位。 主节点 由于机器人的元器件很多&…

win10查看、关闭和开启多个mysql服务

我的之前安装了2个MySQL版本&#xff0c;一个是MySQL8.0.17&#xff0c;一个是MySQL5.7.19 为什么要查看怎么关闭MySQL服务?如果是个人电脑&#xff0c;我觉得开启一个服务相当于开启一个进程&#xff0c;可能会占用部分内存。如果自己是游戏摆烂状态&#xff08;非学习状态&…

R语言forestploter包优雅的绘制孟德尔随机化研究森林图

在既往文章中&#xff0c;我们对孟德尔随机化研究做了一个简单的介绍。我们可以发现&#xff0c;使用TwoSampleMR包做出来的森林图并不是很美观。今天我们使用R语言forestploter包优雅的绘制孟德尔随机化研究森林图。 使用TwoSampleMR包做出来的森林图是这样的 而很多SCI文章…

qt和vue的交互

1、首先在vue项目中引入qwebchannel /******************************************************************************** Copyright (C) 2016 The Qt Company Ltd.** Copyright (C) 2016 Klarlvdalens Datakonsult AB, a KDAB Group company, infokdab.com, author Milian …

简易评分系统

目录 一、实验目的 二、操作环境 三、实验内容和过程 1.实验内容 2.代码 2.1 用户验证功能 2.2 菜单函数 2.3 评分功能 四、结果分析 总体的输出结果&#xff1a; 保存文件成功截图&#xff1a; 五、小结 一、实验目的 1.巩固和提高学生学过的基础理论和专业知识&am…