springDatajpa动态sql根据时间范围将数据导出为excel并使用vue的按钮去触发

news2024/11/19 10:27:56

用到的技术点:
1.springDatajpa
2.EasyExcel
3.数据库
4.vue

前端实现:
1.创建按钮(点击此按钮弹出填写导出条件的弹出框)

 <el-button type="primary" round @click="dialogVisible = true"><svg-icon icon-class="jurassic" />&nbsp;&nbsp;导出</el-button>
 //================================
  <el-dialog
      title="导出条件"
      :visible.sync="dialogVisible"
      width="30%"
    >
      <el-form ref="exportConditionForm" :model="exportCondition" :rules="exportConditionRules" label-width="100px" class="demo-ruleForm">
        <el-form-item label="登录账号" prop="account">
          <el-input v-model="exportCondition.account" />
        </el-form-item>
        <el-form-item label="姓名" prop="name">
          <el-input v-model="exportCondition.name" />
        </el-form-item>
        <el-form-item label="登录IP地址" prop="ip">
          <el-input v-model="exportCondition.ip" />
        </el-form-item>
        <el-form-item label="登录时间" prop="time">
          <el-date-picker
            v-model="exportCondition.time"
            type="daterange"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            :default-time="['00:00:00', '23:59:59']"
          />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="exportButtonEvent">导出</el-button>
      </span>
    </el-dialog>

2.为导出按钮添加导出事件(这里是下载的关键)

 exportButtonEvent() {
      const shuju = this.exportCondition
      axios({
        method: 'post',
        //这里是我的后端接口地址改成你的,这里会涉及到跨域的
        //问题1.使用注解形式解决2.重写addCorsMappings方法3.前   
        //端处理
        //其他地方就不用改了
        url: window.wgParameter.VUE_APP_FILE_USER_API + '/loginformation/query/exportuserinfor',
        data: shuju,
        responseType: 'arraybuffer'
      }).then(res => {
        const name = res.headers['content-disposition']
        if (res.size === 0) { // 如果返回是空的
          this.$message({
            message: '报错了',
            type: 'warning'
          })
        } else { // 返回不为空
          if (!!window.ActiveXObject || 'ActiveXObject' in window) {
            window.navigator.msSaveOrOpenBlob(res, '计算结果.xlsx')
          } else {
            const url = window.URL.createObjectURL(

              new Blob([res.data], {

                type: 'application/octet-stream'
              })

            )

            const link = document.createElement('a')

            link.href = url

            link.setAttribute(

              'download', decodeURI(name.split("attachment;filename*=utf-8''")[1], 'utf-8')

            )
            link.click()
          }
        }
      }).catch(error => {
        this.$message({
          message: '报错了:' + error,
          type: 'warning'
        })
      })
    }

后端实现:
1.建表,用EasyExcel的注解(@ExcelProperty)标记表中属性(easyExcel的用法见其官网)

用来对应后台数据的实体类(在其中规定了excel的格式标题位置)

package com.zgy.handle.userService.model.loginformation;

import com.alibaba.excel.annotation.ExcelProperty;
import com.zgy.handle.userService.model.dto.BaseDTO;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Embeddable;

@Embeddable
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LogInformationDto extends BaseDTO {
    @ExcelProperty(value = "账号", index = 0)
    @ApiModelProperty("账号")
    String account;
    @ExcelProperty(value = "姓名", index = 1)
    @ApiModelProperty("姓名")
    String name;
    @ApiModelProperty("ip地址")
    @ExcelProperty(value = "ip地址", index = 2)
    String ip;
    @ApiModelProperty("登录时间/操作时间")
    @ExcelProperty(value = "登录时间/操作时间", index = 3)
    String time;
    /**
     * 类型
     * 1--登录
     * 2--操作
     */
    @ApiModelProperty("类型")
    @ExcelProperty(value = "类型", index = 4)
    Integer type;
    @ApiModelProperty("模块名")
    @ExcelProperty(value = "模块名", index = 5)
    String modulename;
}

封装前台参数的实体类

package com.zgy.handle.userService.model.loginformation;

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExportLoginformation {
    @ApiModelProperty("账号")
    String account;
    @ApiModelProperty("姓名")
    String name;
    @ApiModelProperty("ip地址")
    String ip;
    @ApiModelProperty("开始时间-结束时间")
    String[] time;
}

2.写业务处理层代码(用动态sql查数据,之后用Easyexcel将数据以excel的格式写出到response响应体中供前端下载用)

  @Override
    public void exportUserInfor(HttpServletResponse response, ExportLoginformation exportLoginformation) {
        //动态查询
        Specification<LogInformation> sf = (Specification<LogInformation>) (root, query, cb) -> {
            //用于添加所有查询条件
            List<Predicate> p = new ArrayList<>();
            if (!exportLoginformation.getIp().isBlank()) {
                Predicate p1 = cb.equal(root.get("ip").as(String.class), exportLoginformation.getIp());
                p.add(p1);
            }
            if (!exportLoginformation.getName().isBlank()) {
                Predicate p2 = cb.equal(root.get("name").as(String.class), exportLoginformation.getName());
                p.add(p2);
            }
            if (!exportLoginformation.getAccount().isBlank()) {
                Predicate p3 = cb.equal(root.get("account").as(String.class),exportLoginformation.getAccount() );
                p.add(p3);
            }
            if(exportLoginformation.getTime().length>0){
                String[] time = exportLoginformation.getTime();
                Date startDate = null;
                Date endDate = null;
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
                try {
                    if (StringUtils.isNotBlank(time[0])) {
                        startDate = dateFormat.parse(time[0]);
                    }

                    if (StringUtils.isNotBlank(time[1])) {
                        endDate = dateFormat.parse(time[1]);
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                    return null;
                }
                Predicate p4 = null;
                if (startDate != null && endDate != null) {
                    p4 = cb.between(root.get("time").as(Date.class), startDate, endDate);

                } else if (startDate != null) {
                    p4 = cb.greaterThanOrEqualTo(root.get("date").as(Date.class), startDate);

                } else {
                    p4 = cb.lessThanOrEqualTo(root.get("date").as(Date.class), endDate);
                }
                p.add(p4);
            }
            Predicate[] pre = new Predicate[p.size()];
            Predicate and = cb.and(p.toArray(pre));     //查询条件 and
            //Predicate or = cb.or(p.toArray(pre));       //查询条件 or
            query.where(and);       //添加查询条件

            //设置排序
            List<Order> orders = new ArrayList<>();
            orders.add(cb.desc(root.get("time").as(Date.class)));       //倒序
//            orders.add(cb.asc(root.get("username")));   //正序
            return query.orderBy(orders).getRestriction();
        };
        List<LogInformation> all = logInformationQueryReposition.findAll(sf);
        List<LogInformationDto> logInformationDtos = logInformationMapper.toLogInformationDtoList(all);
        String fileName =URLEncoder.encode("用户登录信息-" + System.currentTimeMillis() + ".xlsx", StandardCharsets.UTF_8).replaceAll("\\+", "%20");

        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        // 设置响应头
        response.setHeader("Access-Control-Expose-Headers", "Content-disposition");
        response.setHeader("Content-disposition","attachment;filename*=utf-8''"+fileName);
        try {
            EasyExcel.write(response.getOutputStream(), LogInformationDto.class).sheet("用户登录信息").doWrite(logInformationDtos);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

上面的业务逻辑:用户根据ip,账号,用户名,要查询的一个时间范围(开始时间,结束时间)去动态的进行数据查询,并通过数据库中的时间字段排序fileName(换成你的文件名) EasyExcel.write(response.getOutputStream(), LogInformationDto.class).sheet("用户登录信息").doWrite(logInformationDtos);其中LogInformationDto.class是你的数据封装类行用户登录信息是excel中sheet页的名字logInformationDtos你从数据库中查出的数据

后端解决跨域的问题

package com.zgy.handle.userService.confg.cros;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // `/loginformation/query/exportuserinfor`这是你的接口
        //地址没有`http://ip:端口`的部分
        registry.addMapping("/loginformation/query/exportuserinfor")
                .allowedMethods("*")
                 .allowedOrigins("*")
                .allowedHeaders("*");
    }


}

前端传来的时间格式的转换这块儿可能会报错建议使用catgpt(BIto插件)解决问题
将你的错误告诉他就好了,我的代码就是问过他后解决的错误
在这里插入图片描述
.as(类型)这个在每个属性的断言中都要加否则会报与期望的类型不匹配的错误

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

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

相关文章

Java如何实现分库分表

一、为啥要分库分表 在大型互联网系统中&#xff0c;大部分都会选择mysql作为业务数据存储。一般来说&#xff0c;mysql单表行数超过500万行或者单表容量超过2GB&#xff0c;查询效率就会随着数据量的增长而下降。这个时候&#xff0c;就需要对表进行拆分。 那么应该怎么拆分…

vite项目中处理各种静态资源的引入方式介绍

一、引用图片资源 在vite创建的vue3项目中&#xff0c;引用图片资源有以下两种方式&#xff1a; 直接在模板中使用路径引用&#xff1a;在模板中使用标签&#xff0c;通过src属性引用图片。例如&#xff1a; <template><div><img src"./assets/logo.png…

NetApp FAS 存储管理软件,海量非结构化数据存储

NetApp FAS 存储管理软件&#xff0c;海量非结构化数据存储 在 NetApp ONTAP 数据管理软件的支持下&#xff0c;帮助您构建简单、安全且值得信赖的存储基础架构。NetApp FAS 存储阵列可让客户同时兼顾性能和容量。 NetApp FAS 系统经过优化&#xff0c;易于部署和操作&#x…

记录ip段解析成ip

无脑记录者记录使用方法 1.源代码链接 https://github.com/codeexpress/cidr2ip 2.提前准备的内容 go开发语言&#xff0c;链接里面的main.go 3.使用方法 直接新增文件cidrs.txt cidrs.txt文件里面加入需要解析的ip段即可

【实战】 JWT、用户认证与异步请求(上) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(四)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求1.login2.middleware of json-server3.jira-dev-tool&#xff08;imooc-jira-tool&#xff09;安装问…

机器学习——自然语言处理(一)

1 分词 1.1 设计原则 切分粒度大&#xff1b;非字典词少、单字字典词少&#xff1b;总体次数少。 1.2 基于词典匹配的分词 1.3 基于语法和规则的分词 目前处在试验阶段 1.4 基于统计的分词 1.5 技术难点 1.5.1 歧义识别 交集型歧义&#xff1a;AB | C or A | BC 组合型…

Jmeter操作数据库运行提示“Cannot load JDBC driver class ‘com.mysql.jdbc.Driver‘”的有效解决

如图所示&#xff0c;在jmeter中运行sql时报错提示“Cannot load JDBC driver class com.mysql.jdbc.Driver” 原因分析&#xff1a;这是因为没有mysql驱动&#xff0c;需要下载对应的jar包 一、下载地址&#xff1a;MySQL :: Download Connector/J 根据需求选择下载&#xf…

数字化转型:智慧物业行业落地与应用的突围之路!

导语 | 红杉中国在《2021 年企业数字化年度指南》中指出&#xff0c;96% 的受访企业已经开展了数字化实践&#xff0c;而其中超过 6 成的受访者都表示期望在未来进一步增加数字化的投入。技术因素或将成为未来两到三年影响企业发展最为重要的外部力量。当前地产与物业行业进入不…

当前最强的免费AI画图、AI绘图工具-2

Midjourney比较贵&#xff0c;而且无法访问&#xff0c;Stable Diffusion部署起来很麻烦。网上有哪些可以直接在网页端或者下载的app可以实现AI画图的工具。我们整理了45个相关工具&#xff0c;这是系列2&#xff0c;收录到 当前最强的免费AI画图、AI绘图工具-2https://www.web…

【C++】-- 高并发内存池

高并发内存池 项目介绍池化技术内存池 定长内存池的实现整体框架threadcachethreadcache整体设计threadcache哈希桶映射对齐规则TLS无锁访问 centralcachecentralcache整体设计centralcache结构设计centralcache的实现 pagecachepagecache整体设计pagecache中获取Span 回收内存…

【C/C++练习】经典的快慢指针问题---移除元素

&#x1f4d6;题目描述 题目出处&#xff1a;移除元素 &#x1f516;示例 &#x1f4d6;题解 对于本题我将按照由易到难的顺序为大家分享三种解题思路&#xff0c;并逐一分析它们的优劣&#xff0c;以及注意事项。 &#x1f516;思路一&#xff1a;暴力求解 我想暴力求解应该…

零-云尚办公项目学习

对于云尚办公项目的学习 1、这是尚硅谷推出的新的OA项目 云尚办公系统是一套自动办公系统&#xff0c;系统主要包含&#xff1a;管理端和员工端 管理端包含:权限管理、审批管理、公众号菜单管理 员工端:采用微信公众号操作&#xff0c;包含&#xff1a;办公审批、微信授权登…

数字通信中的编码(学习笔记)

编码种类 RZ(Return Zero Code)编码 也称为归零码&#xff0c;就是在 一个周期内&#xff0c;用二进制传输数据位&#xff0c;在数据脉冲结束后&#xff0c;需要维持一段时间的低电平。 RZ编码又分为两种&#xff1a; 单极性归零码 低电平表示0&#xff0c;正电平表示1&…

【Java用法】windows10系统下修改jar中的文件并重新打包成jar文件然后运行

windows10系统下修改jar中的文件并重新打包成jar文件然后运行 一、背景描述二、操作步骤2.1 解压jar包2.2 修改配置文件2.3 重新打成jar包2.4 确认是否修改成功2.5 运行程序 一、背景描述 测试环境&#xff08;Linux&#xff09;的代码&#xff08;jar包&#xff09;拉取到本地…

AI数字人:语音驱动面部模型及超分辨率重建Wav2Lip-HD

1 Wav2Lip-HD项目介绍 数字人打造中语音驱动人脸和超分辨率重建两种必备的模型&#xff0c;它们被用于实现数字人的语音和图像方面的功能。通过Wav2Lip-HD项目可以快速使用这两种模型&#xff0c;完成高清数字人形象的打造。 项目代码地址&#xff1a;github地址 1.1…

可再生能源与能源存储技术的结合和互补

在全球对可再生能源的需求日益增长的背景下&#xff0c;如何将可再生能源与能源存储技术相结合&#xff0c;实现能源的高效利用和持续供应成为了一个重要的议题。本文将探讨可再生能源与能源存储技术的结合与互补关系&#xff0c;分析其对能源领域的影响以及未来发展的前景。 …

CSS常用样式

文章目录 字体样式文本样式颜色和背景样式对齐方式下划线、上划线、删除线设置行高 列表样式背景样式背景颜色背景图片背景重复背景大小 鼠标样式伪类样式设置透明度 字体样式 所有样式都写在<style>标签内&#xff0c;里面加选择器 <!DOCTYPE html> <html>…

别小看可拖拽式表单设计器,降本增效就靠它啦!

在经济快速发展的当下&#xff0c;办公已然进入流程化发展阶段。不少企业希望实现降本增效的办公效果&#xff0c;大家不妨可以了解下可拖拽式表单设计器。通过简单的拖拉拽就能实现应用组建&#xff0c;创建属于自己的快速开发框架平台&#xff0c;不仅省下培养专业程序人工的…

安科瑞电化学储能电能管理系统解决方案

1.概述 在我国新型电力系统中&#xff0c;新能源装机容量逐年提高&#xff0c;但是新能源比如光伏发电、风力发电是不稳定的能源&#xff0c;所以要维持电网稳定&#xff0c;促进新能源发电的消纳&#xff0c;储能将成为至关重要的一环&#xff0c;是分布式光伏、风电等新能源…

抖音本地生活团购软件开发

抖音本地生活团购软件开发需要考虑以下几个方面&#xff1a; 功能设计&#xff1a;根据本地生活团购服务特点&#xff0c;设计相应的功能模块&#xff0c;如商家入驻、商品展示、订单管理、支付等。 技术选型&#xff1a;选择适合该项目的技术和框架&#xff0c;如移动…