【Vue3】CustomImport 导入文件组件

news2024/12/28 20:46:45

1. 效果图

在这里插入图片描述

2. 组件完整代码

<template>
    <div class="custom-import-warpper">
        <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px" :close-on-click-modal="false">
            <el-form label-width="140px">
                <el-form-item label="点击下载模板">
                    <el-link type="primary" :underline="false" @click="downloadTemp">下载模板</el-link>
                </el-form-item>
                <el-form-item label="选择导入模板" required style="margin-bottom: 0">
                    <el-upload style="width: 100%" :file-list="fileList" :accept="fileTypes" :auto-upload="false" :on-change="handleChange">
                        <el-button type="primary" v-out>选择文件</el-button>
                    </el-upload>
                </el-form-item>
                <el-form-item>
                    <div class="tips">
                    	<div>提示:</div>
                    	<div>&nbsp;·&nbsp;&nbsp;表格格式需要正确正确</div>
                    	<div>&nbsp;·&nbsp;&nbsp;数据不能为空,否则存在导入失败</div>
                    </div>
                </el-form-item>
                <el-form-item label="点击下载错误文件" v-if="errorUrl && fileList.length > 0">
                    <el-link type="primary" :underline="false" @click="downloadError">下载错误文件</el-link>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="onReset">取消</el-button>
                <el-button @click="onSubmit" :loading="submitLoading" type="primary" v-out>确定</el-button>
            </template>
        </el-dialog>

        <!-- 错误数据展示 -->
        <el-dialog v-model="dialogErrorVisible" :title="`${dialogTitle}失败数据`" width="800px" :close-on-click-modal="false">
            <slot :tableData="tableData"></slot>
            <template #footer>
                <el-button @click="dialogErrorVisible = false">关闭</el-button>
                <el-button @click="downloadError" type="primary" v-out>导出失败数据</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts" name="CustomImport">
import axios from 'axios'
import { ElMessage } from 'element-plus'
import type { UploadProps, UploadUserFile } from 'element-plus'
import { onMounted, ref, reactive, toRefs } from 'vue'
import { globalUrl } from '@/utils/global'
import { downloadFile } from '@/utils/tool'

const props = defineProps({
	// 允许上传文件的最大数量
    limit: {
        type: Number,
        default: null
    },
    size: {
        type: Number,
        default: null
    },
    // 弹窗标题
    title: {
        type: String,
        default: '导入文件'
    },
    // 文件类型
    fileTypes: {
        type: String,
        default: '.xls,.xlsx'
    },
    // 路径前缀
    prefix: {
        type: String,
        default: 'electronic'
    },
    // 导入文件上传路径
    actionUrl: {
        type: String,
        default: ''
    },
	// 下载模板路径
    templateUrl: {
        type: String,
        default: ''
    },
    // 下载错误明细路径
    errorUrl: {
        type: String,
        default: ''
    },
    // 下载方式
    fileDownType: {
        type: String,
        default: ''
    }
})

const token = ref<any>(localStorage.getItem('pc/token'))
const env = import.meta.env
const baseURL = ref<string>('')
const submitLoading = ref<boolean>(false)
const dialogVisible = ref<boolean>(false)
const errorUrl = ref<string>('')
const dialogTitle = ref<string>(props.title)

const dialogErrorVisible = ref<boolean>(false)

const state = reactive({
    fileList: [] as Array<UploadUserFile>,
    tableData: [] as Array<any>
})

const { fileList, tableData } = toRefs(state)

const show = () => {
    dialogVisible.value = true
    state.fileList = []
    errorUrl.value = ''
    baseURL.value = globalUrl[env.MODE] + props.prefix
}

defineExpose({ show })
// 抛出事件
const emits = defineEmits<{
    (e: 'success'): void
}>()

onMounted(() => {})

// 下载模板
const downloadTemp = () => {
    if (props.fileDownType == 'flow') {
        downTempByFlow()
    } else {
        downTempByUrl()
    }
}

// 流方式下载模板文件
const downTempByFlow = () => {
    axios({
        method: 'get',
        url: `${baseURL.value}${props.templateUrl}`,
        responseType: 'blob',
        headers: {
            Authorization: token.value,
            'content-type': 'application/x-www-form-urlencoded'
        }
    }).then(res => {
        if (!res) {
            ElMessage.error('系统错误')
        } else {
            downloadFile(res, `${dialogTitle.value}模板.xlsx`)
        }
    })
}
// 链接方式下载模板文件
const downTempByUrl = () => {
    axios
        .get(`${baseURL.value}${props.templateUrl}`, {
            headers: {
                Authorization: token.value,
                'content-type': 'application/x-www-form-urlencoded'
            }
        })
        .then(res => {
            const { code, data, message } = res.data
            if (code == '00000') {
                window.location.href = data
            } else {
                ElMessage.error(message || '系统错误')
            }
        })
        .catch(e => {})
}

// 下载错误模板
const downloadError = () => {
    if (props.fileDownType == 'flow') {
        downErroeByFlow()
    } else {
        window.location.href = errorUrl.value
    }
}

// 流方式下载错误文件
const downErroeByFlow = () => {
    axios({
        method: 'post',
        url: `${baseURL.value}${props.errorUrl}`,
        responseType: 'blob',
        data: state.tableData,
        headers: {
            Authorization: token.value
        }
    }).then(res => {
        if (!res) {
            ElMessage.error('系统错误')
        } else {
            downloadFile(res, `${dialogTitle.value}错误文件.xlsx`)
        }
    })
}
const handleChange: UploadProps['onChange'] = (uploadFile, uploadFiles) => {
    state.fileList = [{ ...uploadFile }]
    errorUrl.value = ''
}

// 取消
const onReset = () => {
    dialogVisible.value = false
    state.fileList = []
}
// 提交
const onSubmit = () => {
    if (state.fileList.length < 1) {
        ElMessage.warning('请选择导入模板')
        return
    }
    if (submitLoading.value) {
        return
    }
    submitLoading.value = true
    let formdata = new FormData()
    formdata.append('file', state.fileList[0].raw)
    axios({
        method: 'post',
        url: `${baseURL.value}${props.actionUrl}`,
        data: formdata,
        headers: {
            Authorization: token.value
        }
    })
        .then(res => {
            let { code, message, data } = res.data
            submitLoading.value = false
            if (code !== '00000') {
                ElMessage.error(message || '模板错误')
            } else {
                if (!data || (data && data.length < 1)) {
                    ElMessage.success('导入成功')
                    errorUrl.value = ''
                    onReset()
                } else {
                    if (typeof data == 'string') {
                        errorUrl.value = data
                    } else if (data && data.length > 0) {
                        state.tableData = data
                        dialogErrorVisible.value = true
                        dialogVisible.value = false
                    }
                }
                emits('success')
            }
        })
        .catch(e => {
            submitLoading.value = false
        })
}
</script>

<style lang="scss" scoped>
.tips {
	font-weight: 400;
    font-size: 12px;
    color: #86909c;
    line-height: 20px;
}
</style>

3. 组件使用示例

<!-- 批量导入 -->
<CustomImport
    ref="batchImportRef"
    fileDownType="flow"
    prefix="finance"
    title="批量导入"
    actionUrl="/api/point/uploadDetail"
    errorUrl="/api/point/exportErrors"
    templateUrl="/api/point/downloadTemplate"
    @success="searchHandle(pagination)"
></CustomImport>
const batchImportRef = ref()

// 批量导入
const handleImport = () => {
    batchImportRef.value.show()
}

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

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

相关文章

SAP从入门到放弃系列之报废率-主数据维护-Scrap

文章目录 一、前言二、场景概述&#xff1a;三、报废的类型&#xff1a;3.1、装配报废3.2、组件报废3.3、工序报废-料废3.4、工序报废-工废 四、数据维护&#xff1a;4.1、装配报废&#xff08;Assembly scrap&#xff09;4.2、组件报废(Component scrap)4.3、工序报废-料废(Op…

windows环境使用cmake配置pcl

安装环境 cmake版本&#xff1a;cmake-3.26.3-windows-x86_64 pcl版本&#xff1a;PCL 1.13.1 vs版本&#xff1a;vs2022 配置流程 cmake编译准备&#xff1a;新建两个文件夹source和cmake_bin。source用于存放.cpp文件和CMakeLists.txt 文件&#xff1b;cmake_bin存放配置生…

【NLP】理解LSTM的内在逻辑

一、说明 在学习RNN的时候,多少有些东西可以作为实例进行原理性实践;而进入LSTM时代,短小的能说明原理的案例实验并不多,相反,对此的参考文献却海啸般地到来,让人来不及消化;本文是万篇论文之一,因其叙述的独特性,被我选入介绍给大家。 二、从循环神经网络说起 人类并…

LeetCode刷题 | 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零

1049. 最后一块石头的重量 II 有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c; 且 x < y。那么粉碎的可能结…

死信是什么,如何运用RabbitMQ的死信机制?

系列文章目录 手把手教你&#xff0c;本地RabbitMQ服务搭建&#xff08;windows&#xff09; 消息队列选型——为什么选择RabbitMQ RabbitMQ 五种消息模型 RabbitMQ 能保证消息可靠性吗 推或拉&#xff1f; RabbitMQ 消费模式该如何选择 死信是什么&#xff0c;如何运用Rabbit…

使用影刀RPA合并excel数据

合并不同sheet&#xff1a; 先获取不同sheet中的表头&#xff0c;合并所有表头并去重存作列表&#xff0c;新建excel在第一行插入该表头数据,作合并数据存放使用循环方法&#xff0c;依次获取每个sheet的数据&#xff0c;用if判断表头是否在1的列表中&#xff0c;在的话则将整…

618技术揭秘:探究竞速榜页面核心前端技术 | 京东云技术团队

前言 H5页面作为移动端Web应用的重要形式之一&#xff0c;已经成为了现代Web开发的热门话题。在H5页面的开发过程中&#xff0c;前端技术的应用至关重要。本文将探究京东竞速榜H5页面的核心前端技术&#xff0c;包括动画、样式配置化、皮肤切换、海报技术、调试技巧等方面&…

easyX库图像处理相关函数

0.图像处理相关函数与类型概览 您好&#xff0c;这里是limou3434&#xff0c;本次我将给您带来的是easyX的图像处理相关接口。 如果您感兴趣也可以看看我的其他内容。 函数或数据类型描述IMAGE保存图像的对象。loadimage读取图片文件。putimage在当前绘图设备上绘制指定图像…

10--Gradle进阶 - Gradle任务的执行

10--Gradle进阶 - Gradle任务的执行 前言 在前面的篇章中&#xff0c;我们尝试执行了 gradle 的 task&#xff0c;但是不清楚有哪些语法&#xff0c;下面来介绍一下。 任务执行 任务执行语法&#xff1a;gradle [taskName...] [--option-name...]。 分类解释常见的任务&#xf…

沉浸式三维虚拟展厅交互体验科技感十足

随着科技的不断发展进步&#xff0c;展厅的表现形式也变得多样化&#xff0c;紧跟时代发展步伐&#xff0c;迭代创新。 3D虚拟展厅具有四大优势 一、降低成本&#xff0c;提高效率 3D“VR线上展厅”将艺术优势资源转到线上搭建的艺术线上展平台&#xff0c;相对传统艺术展来说有…

ModaHub魔搭社区:详解向量数据库Milvus的Mishards:集群分片中间件(二)

目录 元数据 服务发现 元数据 元数据记录了底层数据的组织结构信息。在分布式系统中&#xff0c;Milvus 写节点是元数据唯一的生产者&#xff0c;而 Mishards 节点、Milvus 写节点和读节点都是元数据的消费者。目前版本的 Milvus 只支持 MySQL 和 SQLite 作为元数据的存储后…

SpringBoot整合网易邮箱

SpringBoot整合邮箱 1&#xff0c;开启POP3/SMTP/IMAP服务 注意&#xff1a;每个邮箱的密码唯一&#xff0c;不要随意分享给他人 最后就是这个样子了 2&#xff0c;整合测试 2.1&#xff0c;pom.xml <?xml version"1.0" encoding"UTF-8"?> <…

Just KNIME it [S2C13] 机器学习的可解释性

朋友们&#xff0c;Just KNIME it 还有在跟进吗? 本季已经到 13 期啦。 本期探讨的主题是机器学习的可解释性问题&#xff0c;快随指北君一起看看吧。 挑战 挑战13&#xff1a;揭示犯罪率之迷 难度&#xff1a;中等 情境描述&#xff1a;作为一名在房地产公司任职的数据科学家…

Apikit 自学日记:发起文档测试-HTTP

HTTP 功能入口&#xff1a;API管理应用 / 选中某个项目 / API文档菜单 / 选中某一API文档 / 点击“测试”TAB API文档测试页&#xff0c;可对该API文档描述的接口进行快速测试。API文档测试页分为地址控制栏、请求控制区、返回展示区&#xff0c;以及测试辅助工具区共四个部分…

Android进阶之路 - 深入浅出字体、字体库

当时组内临时接到一个换字体库的需求&#xff0c;这个需求相对简单&#xff0c;因为手头有其他事情&#xff0c;同时之前也没换过字体库&#xff0c;就交给了同事去做了&#xff1b;现在有时间就好好充实下自己 ( 我写的也未必全对&#xff0c;如有不足可直接提出&#xff0c;相…

vue 组件基本使用方法

前言:vue 可以比较灵活的使用 html的片段&#xff0c;并将html的片段进行数据隔离&#xff0c;参数也可以互相传递&#xff0c;组件与组件之间也可以进行数据的交互 合理的使用组件可以避免重复代码或者很方便的调用第三方组件库 vue组件 简单实例组件传参实际应用父子组件交互…

右键文件夹添加指定打开的程序(如:IDEA、PyCharm等)

一.打开注册表 使用winR打开运行界面(默认为左下角)输入regedit 二.进入指定目录 1.找不到可直接复制路径: 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell 2.在当前路径shell下右键->新建->项->命名IDEA &#xff08;名字任意即可&#xff09;,修改默认…

利用影刀RPA批量导出excel中的图片并重命名

本程序要求excel中的图片应该符合以下截图中的格式&#xff1a; 图片和名称应该处于同一行&#xff0c;而且图片应该是嵌入在单元格中 程序参考&#xff1a;

linux系统Nginx服务Rewrite重写

文章目录 一、Rewrite跳转场景二、Rewrite跳转实现三、Rewrite实际场景1.Nginx跳转需求的实现方式2.rewrite放在 server{}、if{}、location{}段中3.对域名或参数字符串 四、Nginx正则表达式1.常用的正则表达式元字符2.正则表达式的优点 五、Rewrite命令1.Rewrite命令语法2.flag…

数字IC前端学习笔记:仲裁轮询(六)

相关文章 数字IC前端学习笔记&#xff1a;LSFR&#xff08;线性反馈移位寄存器&#xff09; 数字IC前端学习笔记&#xff1a;跨时钟域信号同步 数字IC前端学习笔记&#xff1a;信号同步和边沿检测 数字IC前端学习笔记&#xff1a;锁存器Latch的综合 数字IC前端学习笔记&am…