el-upload组件封装方案

basic-upload.vue——基本上传组件

<template><div class="basic-upload-wrap"><el-uploadref="uploadRef":file-list="fileList":accept="accept"@update:file-list="(data) => emits('update:file-list', data)":http-request="uploadFile":on-exceed="handleExceed":on-progress="handleUpdate":on-success="handleUpdate":on-remove="preDelete"v-bind="$attrs"><slot><div class="upload-btn-wrapper"><el-button class="upload-btn" type="primary"><svg-icon name="cloud-upload" />上传文件</el-button><div class="prompt" v-if="accept">只支持{{ accept }}的格式文件</div></div></slot></el-upload></div>
</template><script setup>
import api from "@/api/documentInfo";
const { uploadFiles, deleteFiles } = api;const emits = defineEmits(["update:file-list"]);
const props = defineProps({fileList: {type: Array,default: () => [],},accept: {type: String,},
});const uploadRef = ref();
const pendingDels = [];
const controllerMap = {};async function uploadFile(options) {const { file, onProgress, onSuccess, onError } = options;const formData = new FormData();formData.append("files", file);const controller = new AbortController();controllerMap[file.uid] = controller;const { code, message, data } = await uploadFiles(formData, {onUploadProgress: (event) => {handleProgress(event, onProgress);},signal: controller.signal,});if (code !== "0") {onError(message || "上传失败");}onSuccess(data);
}let timer;
function handleProgress(event, onProgress) {let complete = (event.loaded / event.total) * 100;if (complete < 90) {event.percent = complete;onProgress(event);return;}if (timer) return;timer = window.setInterval(() => {complete += (100 - complete) * 0.2;if (complete > 99 && timer) {window.clearInterval(timer);timer = null;}event.percent = complete;onProgress(event);}, 500);
}function handleExceed(files, uploadFiles) {ElMessage.warning(`最多可上传${uploadFiles.length}个附件`);
}function handleUpdate(response, uploadFile, uploadFiles) {const res = uploadFiles.map((item) => {return item.response ? item.response : item;});emits("update:file-list", res);
}const preDelete = (file) => {controllerMap[file.uid]?.abort?.();delete controllerMap[file.uid];pendingDels.push(file);const updatedFileList = props.fileList.filter((f) => f.uid !== file.uid);emits("update:file-list", updatedFileList);
};const confirmDelete = async () => {if (pendingDels.length > 0) {const ids = [...new Set(pendingDels.map((item) => item.id).filter((v) => v)),];if (!ids.length) return;await deleteFiles(ids);pendingDels.length = 0;}
};const deleteUnBind = () => {pendingDels.push(...props.fileList.filter((v) => !v.kbId));confirmDelete();
};onMounted(() => {if (uploadRef.value) {uploadRef.value.preDelete = preDelete;uploadRef.value.confirmDelete = confirmDelete;uploadRef.value.deleteUnBind = deleteUnBind;}
});
defineExpose({upload: uploadRef,
});
</script><style lang="scss" scoped>
.upload-btn-wrapper {display: flex;align-items: center;.prompt {display: inline-block;color: #88c4f9;font-size: 12px;margin-left: 8px;line-height: 1.2;}
}
</style>

list-upload.vue——文件上传列表

<template><div class="list-upload-wrap"><basic-uploadref="uploadRef":show-file-list="false":file-list="fileList"@update:file-list="(data) => emits('update:file-list', data)":accept="accept"v-bind="$attrs"></basic-upload><ul class="file-list-wrap" v-if="!!fileList.length"><li v-for="item in fileList" :key="item.id"><div class="item-content"><span class="file-name" @click="handlePreview(item)">{{ item.documentName || item.name }}</span><svg-icon name="close" class="close" @click.stop="handleDel(item)" /></div><el-progressv-if="item.percentage !== undefined && item.percentage !== 100":percentage="item.percentage":format="(percentage) => ''":text-inside="true":stroke-width="4"class="el-upload-list__item-progress"></el-progress></li></ul></div>
</template><script setup>
import { handlePreview } from "./utils.js";const emits = defineEmits(["update:file-list"]);
defineProps({fileList: {type: Array,default: () => [],},accept: {type: String,},
});const uploadRef = ref();const handleDel = (val) => {uploadRef.value.upload?.preDelete?.(val);
};const upload = computed(() => uploadRef.value?.upload);
defineExpose({upload,
});
</script><style lang="scss" scoped>
.list-upload-wrap {width: 100%;
}.file-list-wrap {$hover-color: #0093ff;list-style-type: none;padding: 0;margin-top: 16px;max-height: 30vh;overflow-y: auto;padding-right: 6px;li {margin-bottom: 20px;line-height: 1.2;&:last-child {margin-bottom: 0;}.item-content {display: flex;align-items: center;justify-content: space-between;}.file-name {font-family: "Microsoft YaHei", "Microsoft YaHei";font-weight: 400;font-size: 14px;color: #ffffff;text-align: left;font-style: normal;text-transform: none;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;cursor: pointer;&:hover {color: $hover-color;}}.close {font-size: 19px;flex: 19px 0 0;cursor: pointer;&:hover {color: $hover-color;}}.el-upload-list__item-progress {width: 100%;position: relative;top: 2px;margin-bottom: 12px;}}
}
</style>

utils.js——预览跳转

import router from "@/router";// 预览文件
export const handlePreview = (file) => {if (!file) {return;}const name = file.documentName;const url = (process.env.VUE_APP_FILE_PATH || "") + file.documentUrl;if (!name || !url || !router) return;const lowerCaseName = name.toLowerCase();const suffixName = "." + lowerCaseName.split(".").pop();// 1. 处理文本和文档类型if ([".txt", ".doc", ".docx", ".pdf"].includes(suffixName)) {let routeUrl = router.resolve({name: "office-preview",query: { url, name },});window.open(routeUrl.href, "_blank");return;}// 2. 处理图片和视频类型if ([".png", ".jpg", ".jpeg", ".bmp", ".gif", ".mp4"].includes(suffixName)) {window.open(url, "_blank");return;}// 3. 提示不支持的文件类型ElMessage({message: "暂不支持该格式文件预览",type: "warning",});
};

Use

<template><el-form-item label="应急预案:" prop="documentList"><list-upload ref="uploadRef" v-model:file-list="ruleForm.documentList":accept="'.doc, .docx, .txt, .pdf, .png, .jpg, .jpeg, .gif'" :limit="20"></list-upload></el-form-item>
</template><script setup>const uploadRef = ref();function close() {uploadRef.value.upload?.deleteUnBind();dialogVisible.value = false;}async function submit() {const formData = {id: ruleForm.value.id,documentList: ruleForm.value.documentList,};await update(formData);await uploadRef.value.upload?.confirmDelete();ElMessage.success("操作成功");}
</script>

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

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

相关文章

vue+js实现鼠标右键页面时在鼠标位置出现弹窗

首先是弹窗元素 <div class"tanchuang move-win1"id"tanchuang1"><el-button>111</el-button></div>然后在需要弹窗的地方监听点击事件&#xff0c;可以将这个方法写在页面载入事件中 // 获取弹窗元素 var tanchuang document.…

lua中判断2个表是否相等

当我们获取 table 长度的时候无论是使用 # 还是 table.getn 其都会在索引中断的地方停止计数&#xff0c;而导致无法正确取得 table 的长度&#xff0c;而且还会出现奇怪的现象。例如&#xff1a;t里面有3个元素&#xff0c;但是因为最后一个下表是5和4&#xff0c;却表现出不一…

一篇文章搞懂时间复杂度和空间复杂度

不知道小伙伴们有没有刷过力扣上的算法题&#xff0c;我在上研究生的时候&#xff0c;刷过了前40道题&#xff0c;上面的算法题&#xff0c;我觉得还挺难的&#xff0c;当你写完代码的时候&#xff0c;就可以提交自己写的代码到系统上&#xff0c;系统会给你写的代码计算时间复…

页面速度是如何影响SEO的?

搜索引擎使用复杂的算法来衡量您网站的重要方面&#xff0c;以决定是否向您发送流量。 搜索引擎使用您网站的小元素来确定您网站的质量和真实性&#xff0c;然后此操作将转化为您的网页在搜索引擎结果页面 中出现的位置。提高您在 SERP 中的排名的过程称为搜索引擎优化 (SEO)。…

【c】如何利用C语言控制可用性(用户是否可以修改值)

引入: 大家有没有想过设计一个函数控制功能的使用权限或变量修改权限? 我们首先来看代码: #include<stdio.h> bool usability==false;//初始值设为false是为了检查第一次设置有没有设置成功void setUsability(bool choice){usability=choice; } void printUsabilit…

JavaScript学习笔记(六)

37、JavaScript 错误 - Throw 和 Try to Catch try 语句使您能够测试代码块中的错误。 catch 语句允许您处理错误。 throw 语句允许您创建自定义错误。 finally 使您能够执行代码&#xff0c;在 try 和 catch 之后&#xff0c;无论结果如何。 37.1 JavaScript try 和 catc…

第57期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

Datawhale - 角色要素提取竞赛

文章目录 赛题要求一、赛事背景二、赛事任务三、评审规则1.平台说明2.数据说明3.评估指标4.评测及排行 四、作品提交要求五、 运行BaselineStep1&#xff1a;下载相关库Step2&#xff1a;配置导入Step3&#xff1a;模型测试Step4&#xff1a;数据读取Step5&#xff1a;Prompt设…

Yi-1.5 9B Chat 上线Amazon SageMaker JumpStart

你是否对简单的API调用大模型感到不满足&#xff1f;是否因为无法亲自部署属于自己的大模型而烦恼&#xff1f; 好消息来了&#xff0c;Amazon SageMaker JumpStart 初体验 CloudLab实验上线啦&#xff01; 本实验将以零一万物最新发布的中文基础模型 Yi-1.5 9B Chat 为例&am…

kettle从入门到精通 第七十四课 ETL之kettle kettle调用https接口教程,忽略SSL校验

场景&#xff1a;kettle调用https接口&#xff0c;跳过校验SSL。&#xff08;有些公司内部系统之间的https的接口是没有SSL校验这一说&#xff0c;无需使用用证书的&#xff09; 解决方案&#xff1a;自定义插件或者自定义jar包通过javascript调用https接口。 1、http post 步…

ArcGIS Pro SDK (七)编辑 9 使用草图

ArcGIS Pro SDK &#xff08;七&#xff09;编辑 9 使用草图 文章目录 ArcGIS Pro SDK &#xff08;七&#xff09;编辑 9 使用草图1 切换草图选择模式2 聆听草图修改事件3 收听草图完成前事件并修改草图4 收听草图完成事件5 触发草图事件的自定义构造工具6 自定义自定义草图工…

Pytorch添加自定义算子之(10)-mmdeploy编译流程

整体参考 一、mmcv的编译安装 见上一篇 opencv的安装 $env:OpenCV_DIR = "D:\git_clone\opencv\build" # 我这里下载解压之后的地址 $env:path = "$env:OpenCV_DIR\x64\vc15\bin;" + $env:path $env:path = "D:\git_clone\opencv\build\OpenCVConf…

后仿真中《SDF反标必懂连载篇》之 多个SDF 文件反标疑问

设计经过综合之后会生成门级网表,在门级网表里面包含了时序信息,这时的验证称之为后仿,除了验证功能是否满足,还要验证时序是否有违例的情况。 门级网表又分为,pr前和pr后,后端做完布局布线之后的,修改好timing的网表称为带时序的pr网表,pr网表进行仿真时,后端布局布…

嵌入式UI开发-lvgl+wsl2+vscode系列:8、控件(Widgets)(一)

一、前言 这里将介绍一系列控件&#xff0c;了解后就可以开始基础的开发了。 二、示例 1、Base Obj&#xff08;基础对象&#xff09; 1.1、示例1 #include "../../lv_examples.h" #if LV_BUILD_EXAMPLESvoid lv_example_obj_1(void) {lv_obj_t * obj1;obj1 lv…

Python容器 之 列表--列表的常用操作方法

1.查询相关方法&#xff1a;index()、count() &#xff08;1&#xff09;index() 说明&#xff1a; 和 字符串中的 find() 的作用是一样 列表中是没有 find() 方法的, 只有 index() 方法&#xff1b;字符串中 同时存在 find() 和 index() 方法 格式&#xff1a;列表.index(要查…

Linux时间子系统8:clock_event_device

1、前言 上一篇我们谈到了timer&#xff0c;在详细分析hrtimer的实现之前&#xff0c;我们先追根溯源来谈一下clockevent。先抛开clockevent这个概念&#xff0c;如果硬件要支持定时功能&#xff0c;那么硬件必然要能够支持产生定时时间&#xff0c;通过异步中断的方式通知CPU&…

计算机科学中的接口(Interface)介绍

计算机科学中的接口&#xff08;Interface&#xff09;介绍 计算机科学中&#xff0c;接口是一个广泛的概念&#xff0c;在不同上下文中有不同含义&#xff1a; 1.任何两电路或设备间的连接电路&#xff0c;用于连接CPU与内存、CPU与外设之间。这是一个重要的硬件层面的接口概…

你必须要知道的自闭症知识,推荐收藏

自闭症&#xff0c;一种日益受到关注的神经发育障碍&#xff0c;对于许多人来说&#xff0c;仍充满了神秘和误解。以下是 12 个你必须知道的关于自闭症的重要知识点&#xff1a; 1、自闭症并非心理问题 自闭症是一种生理上的神经发育障碍&#xff0c;不是由于孩…

Linux: security: openssh: ssh 登陆变慢又一例;strace的使用

文章目录 问题分析解决问题 今天遇到一个问题,ssh登陆服务器比平时慢了20秒。 分析 这种问题的分析,首先要靠strace,trace sshd的服务进程,看看有没有卡在某个系统调用上。 确实抓到了慢的原因;这里sshd向169.254.195.0:1812 发送了一个消息,然后接下来使用select,等…

亚马逊TM商标跟卖,同行截流采集,人工手动跟卖选品更方便!

区分TM标&#xff0c;软件自动查询&#xff0c;人工手动查询方便。 大家好&#xff0c;跟大家说下如何区分TM标。 选择相对于的站点&#xff0c;选择TM。 软件采集出来的已备案、未备案TMR标&#xff0c;现在点击TM标就会跳到美国商标局。 可以清晰的看到这个地方只有一个序…