vue3表格导入导出.xlsx

news2024/9/25 7:15:20

在这次使用时恰好整出来了,希望大家也能学习到,特此分享出来

使用前确保安装以下模块,最好全局配置element-plus

### 展示一下

###

###导出选项

###

###导入de数据

###

安装的模块

npm install js-table2excel // 安装js-table2excel
npm install xlsx // 安装xlsx
npm install dayjs // 安装dayjs
npm install axios // 安装axios
element-plus全局配置地址:快速开始 | Element Plus

依次根据官网步骤进行引入即可,不在过多介绍

接口文件配置,例如utlis/api.js
// api.js
import axios from 'axios'

const api = axios.create({
  baseURL: 'http://localhost:3000', // 后端接口地址
  timeout: 5000,
})

export default api;

vue页面的构局/前端

样式部分
<template>
    <div>
        <el-card class="box-card1">
            <div style="display: flex; align-items: center;margin: 15px;">
                <el-upload action="#" :show-file-list="false" :before-upload="importBefore" accept=".xls,.xlsx"
                    style="margin: 0 12px;display: flex;align-items: center;">
                    <el-button type="success" plain>表格导入</el-button>
                </el-upload>
                <el-button type="success" plain @click="userExport">导出表格</el-button>
            </div>

            <div style="margin-left:1.875rem; margin-top: 2.125rem;">
                <el-table :data="tableData" style="width:100%" ref="tableRef">
                    <el-table-column type="selection" width="50" align="center" />
                    <el-table-column width="100">
                        <template #default="scope">
                            <!-- {{scope.row.name}} -->
                            <template v-if="scope.row.level === '1'"><el-button type="danger" round size="small">重大
                            </el-button></template>
                            <template v-else-if="scope.row.level === '2'"><el-button type="success" round size="small">非重大
                            </el-button></template>
                        </template>
                    </el-table-column>
                    <el-table-column width="280">
                        <template #default="scope">
                            <div>
                                <h4>案件编码:{{ scope.row.anjbm }}</h4>
                            </div>
                            <div><span>案件名称:{{ scope.row.name }}</span></div>
                        </template>
                    </el-table-column>
                    <el-table-column width="280">
                        <template #default="scope">
                            <div><span>我方地位:{{ scope.row.mypos }}</span></div>
                            <div><span>提交时间:{{ dayjs(scope.row.date).format("YYYY-MM-DD hh:mm:ss") }}</span></div>
                        </template>
                    </el-table-column>
                    <el-table-column width="200">
                        <template #default="scope">
                            <div><span>案件类型:{{ scope.row.style }}</span></div>
                            <template v-if="scope.row.status === 1">
                                <div><span>案件进展:进展中</span></div>
                            </template>
                            <template v-else-if="scope.row.status === 2">
                                <div><span>案件进展:暂无进展</span></div>
                            </template>
                            <template v-else-if="scope.row.status === 3">
                                <div><span>案件进展:已审理结案</span></div>
                            </template>
                            <!-- <div><span>状态:{{ scope.row.status == 1 ? '进展中' : scope.row.status == 2 ? '暂无进展' : '已审理结案' }}</span></div> -->
                        </template>
                    </el-table-column>
                    <el-table-column width="200">
                        <template #default="scope">
                            <el-progress :percentage="scope.row.schedule" />
                        </template>
                    </el-table-column>
                    <el-table-column width="280">
                        <template #default="scope">
                            <div>
                                <template v-if="scope.row.flag === 1">
                                    <el-button size="small" link>新增执行</el-button>
                                    <el-button size="small" text>修改执行</el-button>
                                    <el-button size="small" text>执行结果</el-button>
                                </template>
                                <template v-else-if="scope.row.flag === 2">
                                    <el-button size="small" link>新增执行</el-button>
                                </template>
                                <template v-else-if="scope.row.flag === 3">
                                </template>
                            </div>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
        </el-card>
</template>
功能部分
<script setup>
import { ElMessage, ElButton, ElLoading } from 'element-plus'
import table2Excel from 'js-table2excel'
import * as XLSX from "xlsx"
import api from '../utils/api'
import dayjs from "dayjs";
import { ref, onMounted, reactive, toRefs, h } from 'vue'
import axios from 'axios'
import { ElMessageBox } from 'element-plus'
const dialogVisible = ref(false)

const state = reactive({
    tableData: [
        // {
            // level:'1',
            // anjbm:'A202311111009',
            // name:'某某酒驾撞人案件',
            // mypos:'被告',
            // date:'2023-11-19 09:42:09',
            // style:'劳动争议案件',
            // status:1
            // schedule:80
            // flag:1
        // }
    ],  //模拟请求数据
    exportConfig: [  //导出Excel表格配置
        {
            title: '案件级别',
            key: 'level',
            type: 'text'
        },
        {
            title: '案件编码',
            key: 'anjbm',
            type: 'text'
        },
        {
            title: '案件名称',
            key: 'name',
            type: 'text'
        },
        {
            title: '我方地位',
            key: 'mypos',
            type: 'text'
        },
        {
            title: '提交时间',
            key: 'date',
            type: 'text'
        },
        {
            title: '案件类型',
            key: 'style',
            type: 'text'
        },
        {
            title: '案件进展',
            key: 'status',
            type: 'text'
        },
        {
            title: '案件进度',
            key: 'schedule',
            type: 'text'
        },
        {
            title: '功能区',
            key: 'flag',
            type: 'text'
        },
        //  图片配置
        // {
        //   title: '头像',
        //   key: 'imgs',
        //   type: 'image'
        // },

    ],
    formatColumns: [ // 导出特殊字段处理
        {
            prop: 'status',
            option: {
                '1': '进展中',
                '2': '暂无进展',
                '3': '已审理结案'
            },
        },
        {
            prop: 'level',
            option: {
                '1': '重大',
                '2': '非重大',
                '3': '已结案'
            },
        },
    ]
})
const { tableData, exportConfig, formatColumns } = toRefs(state)

const tableRef = ref()

// 表格导出
const userExport = () => {
    ElMessageBox({
        title: '导出Excel表格',
        draggable: true,
        showCancelButton: true,
        showConfirmButton: false,
        message: h('div', null, [ // 这里用到了h函数
            h(ElButton, { text: true, type: 'primary', innerHTML: '导出选中数据', onClick: assignExport }),
            h(ElButton, { text: true, type: 'success', innerHTML: '导出所有数据', onClick: allExport })
        ]),
        cancelButtonText: '取消',
    }).then((res) => { }).catch((res) => { })
}

// 选中数据导出
const assignExport = () => {
    // getSelectionRows  Element Plus table表格组件方法,获取当前选中的数据
    let arr = tableRef.value.getSelectionRows()
    if (!arr.length) {
        return ElMessage({
            message: '请选择需要导出的数据',
            type: 'warning',
        })
    }
    ElMessageBox.close() // 关闭弹出框
    const loading = ElLoading.service({ // 打开遮罩层
        lock: true,
        text: '请稍等...',
        background: 'rgba(255, 255, 255, 0.5)',
    })
    let list = JSON.stringify(tableRef.value.getSelectionRows())
    list = formatExportData(JSON.parse(list))
    table2Excel(state.exportConfig, list, '案件进展批量导出')
    loading.close() // 关闭遮罩层
}

// 所有数据导出
const allExport = () => {
    ElMessageBox.close() // 关闭弹出框
    const loading = ElLoading.service({ // 打开遮罩层
        lock: true,
        text: '请稍等...',
        background: 'rgba(255, 255, 255, 0.5)',
    })
    let list = JSON.stringify(state.tableData) // 用定义的数据
    list = formatExportData(JSON.parse(list))
    table2Excel(state.exportConfig, list, '案件进展全部导出')
    loading.close() // 关闭遮罩层
}

const formatExportData = (list) => {
    // 处理特殊字段
    list.forEach((item) => {
        state.formatColumns.forEach((i) => {
            item[i.prop] = i.option[item[i.prop]]
        })
        for (let key in item) {
            if (!item[key] && item[key] == null) {
                item[key] = ""
            }
        }
    });
    return list
}

// 表格导入
const importBefore = (file) => {
    const reader = new FileReader();
    reader.onload = (e) => {
        const data = e.target.result;
        const workbook = XLSX.read(data, { type: "array" });
        const firstSheetName = workbook.SheetNames[0];
        const worksheet = workbook.Sheets[firstSheetName];
        const results = XLSX.utils.sheet_to_json(worksheet);
        importAdd(results)
    };
    reader.readAsArrayBuffer(file);
}

const importAdd = (list) => {
    // 处理上传时excel中特殊字段
    list.forEach((item) => {
        state.exportConfig.forEach((i) => {
            item[i.key] = item[i.title]
            delete item[i.title]
        })
        for (let key in item) {
            if (key == "date") {
                item[key] = ExcelDateToJSDate(item[key])
            }
        }
    })
    list = convertImportData(list)
    // 调用后台接口进行批量添加
    api.post('/l/madd', list)
        .then(response => {
            getdata()
            console.log('res', response.data);
            return response.data
        })
        .catch(error => {
            throw new Error(error)
        })
}

// 处理日期时间
const ExcelDateToJSDate = (serial) => {
    // 原始的
    // var utc_days = Math.floor(serial - 25569);
    // var utc_value = utc_days * 86400;
    // var date_info = new Date(utc_value * 1000);
    // var fractional_day = serial - Math.floor(serial) + 0.0000001;
    // var total_seconds = Math.floor(86400 * fractional_day);
    // var seconds = total_seconds % 60;
    // total_seconds -= seconds;
    // var hours = Math.floor(total_seconds / (60 * 60));
    // var minutes = Math.floor(total_seconds / 60) % 60;
    // return new Date(date_info.getFullYear(), date_info.getMonth(), date_info.getDate(), hours, minutes, seconds);

    // 更改后的,引入dayjs包后做的改进
    return dayjs(serial).format("YYYY-MM-DD hh:mm:ss")
}

// 返回上传的Excel文件
const convertImportData = (list) => {
    console.log(list);
    list.forEach((item) => {
        state.formatColumns.forEach((i) => {
            for (let key in i.option) {
                if (item[i.prop] == i.option[key]) {
                    item[i.prop] = key
                }
            }
        })
        for (let key in item) {
            if (!item[key] && item[key] == undefined) {
                item[key] = ""
            }
        }
    });
    return list
}

// 渲染数据的vue3钩子函数,并不会刷新页面
const getdata = onMounted(async () => {
    const { data } = await axios.get('/l/case/show')
    state.tableData = data.data
})
</script>

样式自己搭建即可,不再演示辣

vue后端接口的布局

之前已经讲解过数据库的搭建,mongoose搭建步骤 <-----查看创建步骤

也可根据mongoose官网:Mongoose.js中文网

以下是各接口的简单搭建

后端展示数据接口
// 数据全部展示
router.get("/case/show",async function(req,res){
  let data=await caseprogressModel.find()
  
  res.send({code:200,message:'caseshow ok',data})
})
后端批量添加接口
// 批量添加接口
router.post('/madd',async function(req, res, next) {
  const body= req.body
  console.log(body);
  const insertedData = await caseprogressModel.insertMany(body)
  res.send({code:"200",message:'madd ok',data: insertedData})
});

最终效果展示:

vue导入导出

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

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

相关文章

链表相关题目(数据结构期末复习)

题目要求 下面算法 FB1 将一个带头节点的单链表LA 分解为两个具有相同结构的单链表 LB&#xff0c;LC&#xff0c; 其中LB中节点为LA中值小于0的节点&#xff0c;而LC中节点为LA中值大于或等于0的节点。请在空白处填上合理的语句。 翻译&#xff1a;LA 初始链表&#xff1b;L…

Python图像文字识别详解,实战代码

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在现代计算机视觉和图像处理应用中&#xff0c;文字识别是一个重要的任务。本篇博客将详细介绍如何使用Python中的文字识别库&#xff0c;以及一些优秀的开源工具&#xff0c;来实现对图片中文字的准确识别。通过…

从学到考,一图带你读懂开发者技能成长秘籍

亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术&#xff0c;观点&#xff0c;和项目&#xff0c;并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏…

【Spring学习笔记】Spring 注解开发

Spring学习——注解开发 注解开发注解开发定义bean纯注解开发 Bean管理bean作用范围bean生命周期 依赖注入自动装配 第三方bean管理注解开发总结XML配置与注解配置比较 注解开发 注解开发定义bean 使用Component定义开发 Component("bookDao") public class BookD…

【Python可视化系列】一文教会你绘制美观的直方图(理论+源码)

一、引言 前面我详细介绍了如何绘制漂亮的折线图和柱状图&#xff1a; 【Python可视化系列】一文彻底教会你绘制美观的折线图&#xff08;理论源码&#xff09; 【Python可视化系列】一文教会你绘制美观的柱状图&#xff08;理论源码&#xff09; 对于一个连续性的变量&#xf…

spring三级缓存之相互依赖

spring三级缓存之相互依赖 什么是sping的互相依赖sping的三级缓存三级缓存存储了什么内容&#xff1f;三级缓存的存在是为了解决什么问题&#xff1f;三级缓存的怎样解决互相依赖的问题&#xff1f;缓存解决A和B相互依赖的过程三级缓存解决AOP并且A和B互相依赖的过程 三级缓存所…

Python 操作mysql实现事务处理

一、应用场景 Python项目对MySQL数据库进行增、删、改操作时&#xff0c;有时会出现执行sql异常的情况。在批量提交数据的时候&#xff0c;如果其中一个事务提交错误&#xff0c;往往导致预期的整个数据链不完整。 例如银行转账数据&#xff0c;用户A向用户B转账&#xff1a; …

blast安装及简单使用

一、安装blast 1.Ubuntu环境 # 下载blast wget https://ftp.ncbi.nlm.nih.gov/blast/executables/blast/2.9.0/ncbi-blast-2.9.0-x64-linux.tar.gz # 解压blast压缩包 tar -xzvf ncbi-blast-2.9.0-x64-linux.tar.gz # 测试 ./bin/blastp -h 这里就代表安装成功了&#xff0c;…

Mac电脑上设置一位数密码

1. 打开“终端”应用程序&#xff0c;你可以在 “ 应用程序 ” 文件夹中找到它。 2. 在终端窗口中&#xff0c;输入以下命令并按下回车键 pwpolicy -clearaccountpolicies 这个命令的目的是清除全局账户策略&#xff0c;允许设置较低位数的密码。 3. 输入你的开机密码并按下…

springCould-从小白开始【1】

目录 1.说明 2.父工程 3.服务端 4.消费者 5.公共模块 6.RestTemplate 1.说明❤️❤️❤️ 创建三个模块&#xff0c;服务者&#xff0c;消费者&#xff0c;公共api 注&#xff1a;spring boot和spring cloud有版本约束 2.父工程 ❤️❤️❤️ 约定版本号配置 注意&…

GSCoolink GSV1201E Type C/DP1.2转HDM1.4

DisplayPort 1.2 to HDMI 1.4 Converter with Embedded MCU 功能特征 1、GSV1201E是一款高性能、低功耗、USB Type-C Alternate Mode DisplayPort 1.2 to HDMI 1.4转换器。 2、显示接口接收器支持21.6Gbps(HBR2&#xff0c;4-lane)。 3、HDMI发射器支持9Gbps(TMDS3G3Lane)。…

OpenHarmony南向之TP触摸屏

概述 Touchscreen驱动用于驱动触摸屏使其正常工作&#xff0c;该驱动主要完成如下工作&#xff1a;对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口&#xff08;I2C或SPI&#xff09;、设定Input相关配置、下载及更新固件等操作。 Touchscreen驱…

mysql:查看线程缓存中的线程数量

使用命令show global status like Threads_cached;可以查看线程缓存中的线程数量。 例如&#xff0c;查询线程缓存中的线程数量如下&#xff1a; 然后启动应用程序&#xff0c;使用连接&#xff0c;查询如下&#xff1a; 由查询结果可以看到&#xff0c;线程缓存中的线程数量…

人工智能时代,看好硅光子!

硅光子学是一种用于制备光子集成电路&#xff08;PIC&#xff09;的技术&#xff0c;通常用于产生、检测、传输和处理光。这种方法使用半导体绝缘体上硅&#xff08;SOI&#xff09;晶片作为衬底材料&#xff0c;并采用标准的互补金属氧化物半导体&#xff08;CMOS&#xff09;…

弧形导轨的类型及应用

弧形导轨又叫圆弧形导轨&#xff0c;滚轮弧形导轨&#xff0c;是通过V型滚轮在圆弧形V型导轨面上的滚动&#xff0c;实现圆周运动&#xff1b;在工业自动化中&#xff0c;有些应用需要弧线运动&#xff0c;或者两个相交或平行的直线运动&#xff0c;这些情况需要通过弧线运动连…

netsdk1004 找不到资产文件“d:\vs-code\consoleapp1\consoleapp1\obj\project.assets.json”

今天学C#遇到一个问题记录下 创建如上所示的项目后运行出错&#xff1a; netsdk1004 找不到资产文件“d:\vs-code\consoleapp1\consoleapp1\obj\project.assets.json”。运行 nuget 包还原以生成此文件。 consoleapp1 c:\program files\dotnet\sdk\8.0.100\sdks\microsoft.net…

pyCharm 创建一个FastApi web项目,实现接口调用

FastApi和Django区别 我这边演示项目使用的fastApi作为web框架&#xff0c;当然主流一般都是使用Django做web框架&#xff0c;但是Django是一个重量级web框架他有很多组件&#xff0c;如授权&#xff0c;分流等全套web功能。我这边呢只需要有个接口可以被别人调用&#xff0c;…

脉冲水表和光电直读水表有什么区别?

脉冲水表和光电直读水表是两种常见的水表类型&#xff0c;它们在原理和功能上有着一些明显的区别。在本文中&#xff0c;我们将探讨脉冲水表和光电直读水表的区别&#xff0c;并讨论它们各自的优势和适用场景。 首先&#xff0c;我们来看看脉冲水表。脉冲水表是一种机械式水表&…

Python列表操作详解,多种方式删除首元素

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python中&#xff0c;处理列表的操作是日常开发中不可避免的任务之一。其中&#xff0c;删除列表中的元素是一个常见的需求&#xff0c;而删除第一个元素更是一个特殊的场景。本篇博客将详细介绍Python中多种方…

C++ Qt开发:TabWidget实现多窗体功能

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍TabWidget标签组件的常用方法及灵活运用。 Q…