elementui附件上传自定义文件列表,实现传完即可预览、下载、删除,二次封装el-upload

背景

        当前 elementui 的文件上传组件在上传完文件之后只支持删除,用户希望可以看到附件信息,还可以预览自己刚刚上传但未提交的文件,还希望可以下载,因为公司的下载功能当前是通过 OnlyOffice 实现了文件格式转换,所以我们需要对 el-upload 做二次封装,从而实现这些功能。

效果

图片直接用查看器打开,文档则用OnlyOffice打开。

实现方案

1. 隐藏掉 elementui 组件自带的文件列表

博主选这个了这个方案,主要是想预防其他同事在用我的组件时因不知情而传入了file-list,更加友好高效,想怎么用都行。

::v-deep .el-upload-list{display: none;
}

或者也可以直接设置不显示文件上传列表,

'show-file-list': false,

2.写自己的文件列表和事件、样式

页面

<template>
<div class="file-upload-wrap"><!-- 上传区域 --><div class="top-upload" v-if="showEdit"><el-upload:key="fileTable.length"ref="fileUploadComponent":data="formData":action="doUpload":headers="headerFiles":multiple="multiple":before-upload="beforeUpload"v-bind="$attrs":accept="acceptType":class="{ 'file-upload-container':showType==='icons'}"v-on="$listeners"><slot name="pre-content" /><div v-if="showType === 'icons' && showUpload" class="file-upload-icons-container"><div class="el-upload__text"><span><i class="el-icon-upload" type="primary"/> </span><span v-if="$attrs.drag">将文件拖到此处,或</span><em>点击上传</em></div><div slot="tip" class="el-upload__tip">支持扩展名:{{ acceptType }}</div></div><el-button v-if="showType === 'buttons' && showUpload" :size="size" type="primary">点击上传</el-button><slot name="after-content" /></el-upload></div><!-- 文件列表 --><div><div v-for="(fileItem, fileIndex) in fileTable" :key="fileIndex" class="file-list-class"><div><img :src="getImgSrc(fileItem)" :alt="fileItem.name" class="img-class" :key="fileItem.id" />{{ fileItem.name}}</div><div class="right-buts-class"><div class="size-text">{{ fileItem.size }}</div><div><i class="el-icon-success" style="color:#22b77d;margin-right: 1px;"/>成功</div><div><el-tooltip class="item" effect="dark" content="预览" placement="top"><i class="el-icon-zoom-in icon-but-class" @click="check(fileItem)"/></el-tooltip></div><div class="convert-class"><el-tooltip class="item" effect="dark" content="下载" placement="top"><convert :scrop="{row: fileItem}" size="mini" :key="fileItem.id"><i class="el-icon-download icon-but-class2" slot="convertSlot"/></convert></el-tooltip></div><div><el-tooltip class="item" effect="dark" content="删除" placement="top"><i class="el-icon-close icon-but-class2" @click="fileRemove(fileItem)" v-if="showEdit"/></el-tooltip></div></div></div></div><!-- 图片查看 --><el-image-viewerv-if="showViewer":on-close="closeViewer":url-list="[imageUrl]"/>
</div>
</template>

方法

    getImgSrc(fileItem) {const fileTypeIcons = {'.file': 'file.png','.html': 'html.png','.psd': 'psd.png','.doc': 'doc.png','.docx': 'doc.png','.xls': 'xls.png','.xlsx': 'xls.png','.ppt': 'ppt.png','.pptx': 'ppt.png','.pdf': 'pdf.png','.jpg': 'jpg.png','.jpeg': 'jpg.png','.png': 'png.png','.gif': 'gif.png','.tiff': 'tiff.png','.txt': 'txt.png','.zip': 'zip.png','.rar': 'zip.png','.xml': 'xml.png','.cad': 'cad.png',};// 获取文件后缀名const fileName = fileItem.name || '';const lastDotIndex = fileName.lastIndexOf('.');const ext = lastDotIndex > -1 ? fileName.substring(lastDotIndex).toLowerCase() : '';const iconName = fileTypeIcons[ext] || 'unknown.png';return `@/../images/${iconName}`;},check(data) {const imgType = ['jpg', 'jpeg', 'png', 'gif', 'tiff']if (data?.url && imgType.indexOf(data?.type)>-1) {this.imageUrl = this.getImageUrl(data?.url)this.showViewer = truereturn}return opendFileByOnlyOffice(data)},fileRemove(data) {this.$refs.fileUploadComponent.handleRemove(data)},

样式

<style lang="scss" scoped>
::v-deep .el-upload-list{display: none;
}
.file-upload-container {width: 100%;display: inline-grid;text-align: center;height: 45px;::v-deep .el-upload-dragger{height: 45px;width: 100%;display: flex;justify-content: center;align-items: anchor-center;}.top-upload{width: 100%;}
}
.file-upload-wrap{width: 100%;display: flex;flex-direction: column;
}::v-deep .el-icon-upload{font-size: 14px;color: #409EFF;
}
.el-upload__tip{width: 100%;margin: 0px;
}
.el-upload__text{display: flex;flex-direction: row;justify-content: center;width: 100%;height: 15px;
}
.icon-but-class{margin-left: 10px;font-size: 14px!important;&:hover{cursor: pointer;color: #409EFF;}
}
.icon-but-class2{font-size: 14px!important;&:hover{cursor: pointer;color: #409EFF;}
}
.file-list-class{display: flex;justify-content: space-between;padding: 3px;&:hover{background-color: #f5f7fa;}
}
.size-text{margin-right: 10px;
}
.img-class{width: 16px;vertical-align: middle;margin-right: 5px;;
}
.right-buts-class{display: inline-flex;flex-direction: row;
}
.convert-class{width: 40px;::v-deep .moka-convert-selector{padding: 0px;color: #60647f;font-size: 14px!important;&:hover{color: #409EFF;}}::v-deep .el-icon--right{margin: 0px;}
}.el-icon-upload{display: inline;font-size: 14px !important;margin-right: 3px;line-height: normal !important;
}
</style>

3.用法

页面中使用

<file-upload-wrapref="attachmentFileUpload":showEdit="hasEditPermission"v-bind="filesUploadAttr":on-success="(response, file, fileList) => filesUploadSuccess(response, file, fileList)":on-remove="(file, fileList) => filesUploadRemove(file, fileList)":uploadFileList="scrop.row.attachment"
/>

相关方法

filesUploadSuccess(response, file, fileList) {if (!file.response.code === 200) return;this.messageData.attachment_id = fileList.map(upfiles => upfiles?.response?.data?.id || upfiles.id)const newData = fileList.map(upfiles => upfiles?.response?.data || upfiles)this.$set(this.messageData, 'attachment', newData);
},
filesUploadRemove(file, fileList) {this.messageData.attachment_id = fileList.map(upfiles => upfiles?.response?.data?.id || upfiles.id)const newData = fileList.map(upfiles => upfiles?.response?.data || upfiles)this.$set(this.messageData, 'attachment', newData);
},

这样就大功告成啦!

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

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

相关文章

linux的conda配置与应用阶段的简单指令备注

1.新建某虚拟环境 conda create -n 虚拟环境名 pythonPython版本号 (-y)2.退出当前虚拟环境 conda deactivate3.查看当前conda环境下所有的虚拟环境 conda info --envs4.查看conda版本和位置 conda --versionwhich conda5.激活某个conda虚拟环境 conda activate 虚拟环境名

虚拟化技术 ——KVM

一、KVM 技术简介 KVM&#xff08;Kernel-based Virtual Machine&#xff0c;基于内核的虚拟机&#xff09;是 Linux 内核原生支持的全虚拟化解决方案&#xff0c;依托 CPU 的硬件虚拟化技术&#xff08;Intel VT-x/AMD-V&#xff09;实现高效的虚拟机运行。它将 Linux 内核转…

线程间Bug检测工具Canary

Canary1.Introduction2.Approach2.1.数据依赖分析2.2.线程间依赖分析3.Bug检测4.Evaluation参考文献1.Introduction 主要做跨线程value-flow bug检查&#xff0c;下面代码中两个函数中存在指向关系&#xff1a;1. x→o1x \rightarrow o_1x→o1​, b→o2b \rightarrow o_2b→o2…

AEB 强制来临,东软睿驰Next-Cube-Lite有望成为汽车安全普惠“破局器”

AEB 强制时代正在悄然谱写“普惠安全”的行业底色。日前&#xff0c;备受关注的强制性国家标准《轻型汽车自动紧急制动系统技术要求及试验方法》&#xff08;以下简称“新国标”&#xff09;意见征求阶段已经结束。该标准将替代现行国标GB/T 39901-2021&#xff0c;计划于2028年…

css的white-space: pre

用户从别的地方复制的配置文件&#xff0c;粘贴到输入框内&#xff0c;需要保留原始格式发送给后端。核心步骤&#xff1a;### 1. 格式保持机制 - white-space: pre &#xff1a;这是最关键的CSS属性&#xff0c;确保所有空格、制表符、换行符都被保留 - wrap"off" &…

【AI解读源码系列】ant design mobile——Space间距

前言 笔者目前业务主要围绕ant design mobile组件库来交付H5前端工作。 故此出此专栏来解读每一个组件是如何实现的。 本文基于AI来解读Space组件。 文档链接&#xff1a; https://mobile.ant.design/zh/components/space 源码&#xff1a; https://github.com/ant-design/ant-…

《用餐》,午餐食堂即景小诗分享(手机/小视频/光盘/养生)

大妈食堂碎碎念&#xff0c;怪罪手机延工期。 笔记模板由python脚本于2025-08-21 19:34:46创建&#xff0c;本篇笔记适合喜欢友善生活和诗的coder翻阅。 学习的细节是欢悦的历程 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Python官…

高通平台WIFI学习-- 基于WCN6750 Tri-Band 2x2 MIMO 802.11ax的讲解

一 前言: 官方资料显示WLAN支持如下的Key features ■ Compliant with IEEE 802.11a/b/g/n/ac/ax ■ Supports 2x2 multi-user multiple-input multiple-output (MU-MIMO) ■ Up to 2.9 Gbps data rate (2x2 160 MHz) ■ Tri-band 2.4 GHz/5 GHz/6 GHz support ■ 20 MHz…

javaweb开发笔记——XML_Tomcat10_HTTP

第四章 XML_Tomcat10_HTTP 一 XML XML是EXtensible Markup Language的缩写&#xff0c;翻译过来就是可扩展标记语言。所以很明显&#xff0c;XML和HTML一样都是标记语言&#xff0c;也就是说它们的基本语法都是标签。 可扩展 三个字表面上的意思是XML允许自定义格式。但这不代…

Python从入门到自动化运维

文章目录IPO编程方式、print、input函数print() -- 输出信息到屏幕input() -- 读取用户的输入基本数据类型int、float、bool、str常用 str 操作方法格式化字符串的三种方式数据验证方法字符串拼接字符串去重数据类型转换函数容器类型列表(list)&#xff1a;可变、可重复、有序元…

【数据可视化-98】2025年上半年地方财政收入Top 20城市可视化分析:Python + Pyecharts打造炫酷暗黑主题大屏

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

【基础-单选】向服务器提交表单数据,以下哪种请求方式比较合适

向服务器提交表单数据&#xff0c;以下哪种请求方式比较合适A.RequestMethod.GET B.RequestMethod.PUT C.RequestMethod.POST D.RequestMethod.DELETE 解释如下&#xff1a; 在HarmonyOS应用开发中&#xff0c;向服务器提交表单数据&#xff0c;C. RequestMethod.POST 是比较合…

论文阅读:Code as Policies: Language Model Programs for Embodied Control

地址&#xff1a;Code as Policies: Language Model Programs for Embodied Control 摘要 针对代码补全任务训练的大型语言模型&#xff08;LLMs&#xff09;已被证实能够从文档字符串&#xff08;docstrings&#xff09;中合成简单的 Python 程序。研究发现&#xff0c;这些…

Vue 3 customRef 完全指南:自定义响应式引用的终极教程

&#x1f4d6; 概述 customRef() 是 Vue 3 中用于创建自定义响应式引用的组合式 API。它允许开发者完全控制响应式数据的读取和写入行为&#xff0c;为复杂的响应式逻辑提供了强大的灵活性。 &#x1f3af; 基本概念 什么是 customRef&#xff1f; customRef() 是一个工厂函数…

Java项目-苍穹外卖_Day1

项目来源&#xff1a; 【黑马程序员 Java项目实战《苍穹外卖》】 [https://www.bilibili.com/video/BV1TP411v7v6] ZZHow(ZZHow1024) 软件开发整体介绍 软件开发流程 需求分析&#xff1a;需求规格说明书、产品原型。设计&#xff1a;UI 设计、数据库设计、接口设计。编码…

面试可能问到的问题思考-MySQL

MySQL 1. 数据库与缓存的一致性 引入缓存&#xff0c;因为缓存只是数据库数据的副本&#xff0c;那么就可能存在副本和原数据不一致的情况 一致性 ACID里面的C&#xff0c;和CAP中的C不是一个概念&#xff0c;虽然都叫一致性。CAP中的C&#xff0c;指的是多个副本之间逻辑上…

【Java】 Spring Security 赋能 OAuth 2.0:构建安全高效的现代认证体系

还在为高昂的AI开发成本发愁?这本书教你如何在个人电脑上引爆DeepSeek的澎湃算力! 在当今数字化时代,认证与授权已成为应用系统安全的核心。OAuth 2.0 作为一种开放标准协议,广泛应用于第三方授权场景中,而 Spring Security 则提供了强大的框架支持来实现这一协议。本文深…

实际工作几月后常用相关命令笔记记录

目前&#xff0c;我这只工程师幼崽经历几个月的工作&#xff0c;不能说是收获很多&#xff0c;也算是成长经验1吧。主要工作后才知道好多东西都是自己不会的不了解的&#xff0c;但是工作需要不一定自己完全吃透&#xff0c;在合适的地方正确的使用一般情况就ok了&#xff0c;所…

突破传统文本切片的瓶颈:AntSK-FileChunk语义切片技术详解前言:为什么我们需要重新思考文本切片?

在当今大语言模型&#xff08;LLM&#xff09;应用蓬勃发展的时代&#xff0c;我们面临着一个看似简单却至关重要的问题&#xff1a;如何有效地处理长文本&#xff1f;无论是构建知识库、实现RAG&#xff08;检索增强生成&#xff09;系统&#xff0c;还是进行文档智能分析&…

LeetCode-542. 01 矩阵

1、题目描述给定一个由 0 和 1 组成的矩阵 mat &#xff0c;请输出一个大小相同的矩阵&#xff0c;其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。两个相邻元素间的距离为 1 。示例 1&#xff1a;输入&#xff1a;mat [[0,0,0],[0,1,0],[0,0,0]] 输出&#xff1a;[[…