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

用到的技术点:
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(类型)这个在每个属性的断言中都要加否则会报与期望的类型不匹配的错误

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值