用户档案PDF报表

news2024/11/26 9:49:12

用户档案PDF报表

理解数据填充的两种方式熟练构造分组报表

熟练构造Chart图形报表实现个人档案的PDF输出

数据填充

我们介绍了如何使用JasperReport来生成简单的文本报表,正式企业开发中动态数据展示也是报表中最重要的一 环,接下来我们共同研究的就是填充动态数据到PDF报表中。

/**
* 填充数据构造JasperPrint
* is: 文件输入流
* parameters:参数
* dataSource:数据源
*/
public static JasperPrint fillReport(InputStream is, Map<String, Object> parameters, 
JRDataSource dataSource) throws JRException {

通过这段填充数据的源代码得知,JasperReport对报表模板中的数据填充有很多中方式,最典型的有以下两种:

  • Parameters(参数)填充
  • DataSource(数据源)填充

参数Map填充数据

Parameters通常是用来在打印的时候从程序里传值到报表里。也就是说parameters通常的是起参数传递的作用。 他们可以被用在一些特定的场合(比如应用中SQL 查询的条件),如report中任何一个需要从外部传入的变量等(如一个Image对象所包括的char或报表title的字符串)。parameters也需要在创建的时候定义它的数据类型。parameters 的数据类型是标准的java的Object。

模板制作

创建新模板,删除不需要的Band

创建Parameter

在outline面板中找到Parameters,右键 -> Create Parameter,新建一个Parameter(生成一个Paramerter1)

选中新建的参数Paramete1,可以看到右侧的Properties栏,这里可以设置参数的信息,设置Name为title、Class为java.lang.String.这里要注意名字要认真取,不能重复,因为传入的参数的key就是这个参数名,以此来进行一一对应

模板参数设置

将设置好的参数直接拖入表格中对应的位置,并设置好大小与对齐方式。

PDF输出

package cn.itcast.controller;

import net.sf.jasperreports.engine.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
public class JasperController02 {

    /**
     *  基于parameters以Map的形式填充数据
     */
    @GetMapping("/testJasper2")
    public void createPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1.引入jasper文件
        Resource resource = new ClassPathResource("templates/testParam.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());


        //2.创建JasperPrint,向jasper文件中填充数据
        ServletOutputStream os = response.getOutputStream();
        try {
            Map parameters = new HashMap<>();
            //设置参数 参数的key = 模板中使用的parameters参数的name
            parameters.put("username","张三");
            parameters.put("phone","120");
            parameters.put("department","讲师");
            parameters.put("company","字节跳动");

            JasperPrint print = JasperFillManager.fillReport(fis,parameters,new JREmptyDataSource());
            JasperExportManager.exportReportToPdfStream(print,os);
        } catch (JRException e) {
            e.printStackTrace();
        }finally {
            os.flush();
        }
    }
}

骚戴理解:这个是通过hashMap来填充参数的,这里写的都是静态的数据,唯一要注意的就是这个hashMap里的key要和Parameters里面的属性名保持一致!使用HashMap填充适用于一对一的数据,就是标题下面只有一行数据的情况,如果是想一对多,也就是数据列表的形式,跟数据库表格数据一样的话就要用JDBC或者JavaBean的填充方式!

数据源填充数据

JDBC数据源

配置数据连接

选择Data Adapters右键选择Create Data Adapter

使用JDBC数据源填充数据:使用Jaspersoft Studio 先要配置一个数据库连接填写数据源的类型,选择“Database JDBC Connection”

配置数据库信息

这一步,需要:

(1)给创建的这个数据连接起个名字;

(2)根据数据库选择驱动类型; Jaspersoft Studio 已经内置了很多常用数据库的驱动,使用的时候直接选就可以了。当然,如果这还满足不了你的话,你还可以添加你指定的 JDBC 驱动 jar 包。

骚戴理解:这个Mysql驱动其实就是jdbc的驱动包,如下所示!

模板制作

制作空白模板

创建空白模板,并将不需要的Band删除

将数据库用户字段配置到模块中

为了方便的进行模板制作,可以将需要数据库表中的字段添加到Studio中。在outline中右键模板,选择dataset and query

用户可以在 SQL 查询语句输入窗口中,输入需要查询数据的查询语句,点击右上角的“Read Fields”按钮,界面下方的字段列表中,就会显示此查询语句中所涵盖的所有字段的列表。在后面的报表设计中,我们就可以直接使用这些字段了。

在“Fields”列表中,只保留报表中使用的字段,其他用不到的字段最好用“Delete”删掉,防止由于数据表变化,导致报表模板中的字段设置与数据表对应不上,导致报表报错。输入完毕后,点击“OK”按钮,系统即会把查询语句保存在报表模板中。

填充Filed

将id,mobile,username等拖入到 Detail Band中设计模板如下:

骚戴理解:在把Fields里面列名拽到控制台可能会出现下面这样的情况

可以看到多了一些东西,也就是我红色画出的部分,这些其实就是描述,可以不用,所以删掉即可

在预览的时候出现这样的情况,这是样式问题,选中Detail1可以看到它的高度是286px

在选中列框可以看到高度是30px

只需要把detail1的高度改成列框的高度即可

其实也可以直接拖拽detail1的框和列框的高度保持一致即可

调整后

动态传入参数来筛选数据

创建动态参数cid

这里修改sql语句加一个查询条件,使用Jasper的语法$P{}传参数

然后报错测试即可!

PDF输出

package cn.itcast.controller;

import net.sf.jasperreports.engine.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.Map;

@RestController
public class JasperController03 {

    /**
     *  基于JDBC数据源的形式填充数据
     */
    @GetMapping("/testJasper3")
    public void createPdf(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.引入jasper文件
        Resource resource = new ClassPathResource("templates/testConn.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());

        //2.创建JasperPrint,向jasper文件中填充数据
        ServletOutputStream os = response.getOutputStream();
        try {
            Map parameters = new HashMap<>();
            //查询企业id为1的所有用户
            parameters.put("cid","1");

            //获取数据库连接
            Connection conn= getConnection();
            JasperPrint print = JasperFillManager.fillReport(fis,parameters,conn);
            JasperExportManager.exportReportToPdfStream(print,os);
        } catch (JRException e) {
            e.printStackTrace();
        }finally {
            os.flush();
        }
    }

    public Connection getConnection() throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/ihrm","root","111111");
        return conn;
    }
}

骚戴理解:这里只需要修改JasperPrint print = JasperFillManager.fillReport(fis,parameters,conn);即可,传入一个Connection对象替换原来的new JREmptyDataSource()

JavaBean数据源

创建Filed

创建Filed

骚戴理解:JavaBean的方式就只能手动一个个的去创建Fields,然后拖拽到控制台进行设计,不像JDBC一样可以自己生成!

构造模板

PDF输出

配置实体类

package cn.itcast.domain;

public class User {

    private String id;
    private String username;
    private String company;
    private String dept;
    private String mobile;

    public User(String id, String username, String company, String dept, String mobile) {
        this.id = id;
        this.username = username;
        this.company = company;
        this.dept = dept;
        this.mobile = mobile;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public String getDept() {
        return dept;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
}

使用javaBean数据源

package cn.itcast.controller;

import cn.itcast.domain.User;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class JasperController04 {

    /**
     *  基于javaBean数据源的形式填充数据
     */
    @GetMapping("/testJasper4")
    public void createPdf(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.引入jasper文件
        Resource resource = new ClassPathResource("templates/testBean.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());

        //2.创建JasperPrint,向jasper文件中填充数据
        ServletOutputStream os = response.getOutputStream();
        try {
            Map parameters = new HashMap<>();
            //构建javaBean的数据源
            //1.获取到对象的list集合
            List<User> userList = getUserList();
            //2.通过list集合创建javaBean的数据源对象
            JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(userList);
            JasperPrint print = JasperFillManager.fillReport(fis,parameters,ds);
            JasperExportManager.exportReportToPdfStream(print,os);
        } catch (JRException e) {
            e.printStackTrace();
        }finally {
            os.flush();
        }
    }

    public List<User> getUserList() {
        List<User> list = new ArrayList<>();
        for(int i=0;i<10;i++) {
            User user = new User(i+"", "用户"+i, "字节跳动","讲师", "1380000000"+i);
            list.add(user);
        }
        return list;
    }


}

骚戴理解:JavaBean实现的核心代码如下所示

JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(userList);

通过传入集合来构造一个JRBeanCollectionDataSource对象,这是JavaBean的数据源

分组报表

概述

有两种情况会使用分组报表: 美观和好看的显示。

当数据分为两层表时,经常需要批量打印子表的数据。打印时,常常需要按照父表的外键或关联值进行自动分组,即每一条父表记录所属的子表记录打印到一组报表中,每组报表都单独计数及计算页数。

在应用中,可以通过选择需要打印的父表记录,将父表记录的 ID 传入,由报表自动进行分组。

设置分组属性

新建模板

使用用户列表模板完成分组案例

新建报表群组

选中报表名称点击右键,选择菜单中的“Create Group”。

需要设置分组的名称、分组字段。也可以设置按照指定的函数、方法处理后进行分组

按照字段“companyName”进行分组。设置完毕,点击“Next”。系统显示细节设置界面。此处可以设置是否加入“group header”和“group footer”区。建议保持默认选中,加入这两个区域,这样可以控制在每组报表的结尾, 打印相应的信息,例如统计信息等。

放置报表数据

将Fields里的companyName拖入 Group Header中 ,会跳出 TextField Wizard框,选中

No Calculation Function

双击 $F{companyName} 会弹出Expression editor框

骚戴理解:这里注意写法和Java的写法差不多,有点类似字符串拼接

"以企业进行分组:企业名称" + $F{companyName)

添加分组Band

将需要作为表头打印的内容拖入 CompanyGroup Header1 栏,将字段拖入 detail 栏,将每个分组结尾需要打印的内容放入 Companygroup footer 栏,将页脚需要打印的内容放入 Page Footer栏,如下图。

统计每组记录数

首先创建fx的Variables变量

设置这个Variables变量的属性,只需要设置下面右边画出来的属性即可

其中Expression表示分组依据,这里是一个表达式$F{companyName},表示分组是按照companyName企业名称进行分组的!Calculation表示计算方式,这里用的是Count,因为是需要统计每个组的记录数,就是有多少条数据,Calculation还有其他的选项,这里列出来便于了解!

最后的Reset type其实是设置根据什么情况下来重置统计数,这里选择是按分组进行统计重置,也就是统计完一个组后就会把重置count=0,然后统计下一个分组,这些设计好后ctrl+s保存即可拖拽这个变量到控制台进行设计,这是自定义变量,Jaspersoft Studio自带一些Variables是可以直接用的,例如这里就用到了PAGE_NUMBER

Jaspersoft Studio自带的Variables都是什么意思?

  • REPORT_COUNT:当前报表中已经处理的记录数。
  • PAGE_NUMBER:当前页的页码。
  • COLUMN_NUMBER:在详细段中,指明正在处理的列的编号。在组报表中,它是当前分组的列数。
  • PAGE_COUNT:报表的总页数。
  • COLUMN_COUNT:在详细段中,它指出正在处理的列的总数。在组报表中,它是总列数。
  • REPORT_MAX_COUNT:报表中待处理的最大记录数。如果未指定,则无穷大。

PDF输出

package cn.itcast.controller;

import cn.itcast.domain.User;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class JasperController05 {

    /**
     *  分组报表
     */
    @GetMapping("/testJasper5")
    public void createPdf(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.引入jasper文件
        Resource resource = new ClassPathResource("templates/testGroup.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());

        //2.创建JasperPrint,向jasper文件中填充数据
        ServletOutputStream os = response.getOutputStream();
        try {
            Map parameters = new HashMap<>();
            //构建javaBean的数据源
            //1.获取到对象的list集合
            List<User> userList = getUserList();
            //2.通过list集合创建javaBean的数据源对象
            JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(userList);
            JasperPrint print = JasperFillManager.fillReport(fis,parameters,ds);
            JasperExportManager.exportReportToPdfStream(print,os);
        } catch (JRException e) {
            e.printStackTrace();
        }finally {
            os.flush();
        }
    }

    public List<User> getUserList() {
        List<User> list = new ArrayList<>();
        for(int i=0;i<10;i++) {
            User user = new User(i+"", "itcast"+i, "传智播客","讲师", "1380000000"+i);
            list.add(user);
        }
        for(int i=0;i<5;i++) {
            User user = new User(i+"", "itheima"+i, "黑马程序员","讲师", "1380000000"+i);
            list.add(user);
        }

        return list;
    }


}

效果如下:

Chart图表

创建模板

  • 创建模板,删除不需要的band,保留title和summary。

  • 创建fifileds

  • 创建chart图标

第一步:palette面板找到chart图表,拖拽到Summary中

第二步:选择需要的图表类型

第三步:设置图表参数

Key: 圆饼图的内容是什么,也就是下面的 First,Second…的内容

Value:这个圆饼图的比例依据,根据 Value 属性来显示每个 Key 占的比例

Label:显示标签

骚戴理解:可以通过下面的图来更好的理解

PDF输出

实体类

package cn.itcast.domain;

public class UserCount {
    private String company;
    private Long count;

    public UserCount(String company, Long count) {
        this.company = company;
        this.count = count;
    }

    public String getCompany() {
        return company;
    }

    public void setCompany(String company) {
        this.company = company;
    }

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }
}

骚戴理解:上面的这个对象的属性名要和Jaspersoft Studio的Fields里面的保持一致!

PDF输出

package cn.itcast.controller;

import cn.itcast.domain.User;
import cn.itcast.domain.UserCount;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class JasperController06 {

    /**
     *  charts图形报表
     */
    @GetMapping("/testJasper6")
    public void createPdf(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.引入jasper文件
        Resource resource = new ClassPathResource("templates/testCharts.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());

        //2.创建JasperPrint,向jasper文件中填充数据
        ServletOutputStream os = response.getOutputStream();
        try {
            Map parameters = new HashMap<>();
            //构建javaBean的数据源
            //1.获取到对象的list集合
            List<UserCount> userList = getUserCountList();
            //2.通过list集合创建javaBean的数据源对象
            JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(userList);
            JasperPrint print = JasperFillManager.fillReport(fis,parameters,ds);
            JasperExportManager.exportReportToPdfStream(print,os);
        } catch (JRException e) {
            e.printStackTrace();
        }finally {
            os.flush();
        }
    }

    public List<UserCount> getUserCountList() {
        List<UserCount> list = new ArrayList<>();

        UserCount uc1 = new UserCount("传智播客",1000l);
        UserCount uc2 = new UserCount("黑马程序员",1000l);
        UserCount uc3 = new UserCount("baidu",1000l);
        list.add(uc1);
        list.add(uc2);
        list.add(uc3);
        return list;
    }


}

父子报表

概述

复杂报表或数据内容较多的时候,可以使用子报表解决。

制作父报表

首先制作父报表,就是调用子报表的一个基础报表。主报表的作用有如下两种: 父报表中需要显示数据,使用子报表弥补studio设计的不足,父报表不需要显示任何数据,只是作为子报表的载体。适用于复杂报表的设计

制作子报表

点击组件面板上的“Subreport”按钮,拖动到报表工作区上。

系统会自动弹出子报表选择窗口。可以选择创建一个新报表,还是使用一个已有的报表作为子报表。

选择“Create a new report”,可以立即制作新的子报表;

如果选择“Just create the subreport element”,系统会生成一个子报表区,可以在之后挂接需要的子报表。

如果选择“Select an existing report”,则可以调用已经有的报表作为子报表;然后选择“Select a report file...”,选择第一个从控制台资源里获取子报表

选择需要导入的子报表,例如我这里选择mysql这个子报表

生成的效果就是下面这样的!

参数传递

PDF输出

package cn.itcast.controller;

import cn.itcast.domain.UserCount;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class JasperController07 {

    /**
     *  父子报表
     */
    @GetMapping("/testJasper7")
    public void createPdf(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //1.引入jasper文件
        Resource resource = new ClassPathResource("templates/main01.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());

        //2.创建JasperPrint,向jasper文件中填充数据
        ServletOutputStream os = response.getOutputStream();
        try {
            Map parameters = new HashMap<>();
            //参数  子报表的路径   子报表需要的数据
            Resource subResout = new ClassPathResource("templates/testCharts.jasper");
            parameters.put("sublist",getUserCountList());//子报表需要的数据
            parameters.put("subpath",subResout.getFile().getPath());// 子报表的路径

            JasperPrint print = JasperFillManager.fillReport(fis,parameters,new JREmptyDataSource());
            JasperExportManager.exportReportToPdfStream(print,os);
        } catch (JRException e) {
            e.printStackTrace();
        }finally {
            os.flush();
        }
    }

    public List<UserCount> getUserCountList() {
        List<UserCount> list = new ArrayList<>();

        UserCount uc1 = new UserCount("传智播客",1000l);
        UserCount uc2 = new UserCount("黑马程序员",1000l);
        UserCount uc3 = new UserCount("baidu",1000l);
        list.add(uc1);
        list.add(uc2);
        list.add(uc3);
        return list;
    }


}

用户档案下载

搭建环境

配置坐标

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.5.0</version>
</dependency>
<dependency>
    <groupId>org.olap4j</groupId>
    <artifactId>olap4j</artifactId>
    <version>1.2.0</version>
</dependency>
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.7</version>
</dependency>

解决乱码问题

jasperreports_extension.properties

net.sf.jasperreports.extension.registry.factory.simple.font.families=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.lobstertwo=stsong/fonts.xml

骚戴理解:通过在导出pdf报表时候会出现中文乱码的问题,只需要把上面标出来的部分导入到项目里即可,然后在设计模板的时候中文都用华文宋体!

实现用户档案下载

    /**
     * 打印员工pdf报表
     */
    @RequestMapping(value = "/{id}/pdf" , method = RequestMethod.GET)
    public void pdf(@PathVariable String id) throws IOException {
        //1.引入jasper文件
        org.springframework.core.io.Resource resource = new ClassPathResource("templates/profile.jasper");
        FileInputStream fis = new FileInputStream(resource.getFile());

        //2.构造数据
        //用户详情数据
        UserCompanyPersonal personal = userCompanyPersonalService.findById(id);
        //用户岗位信息数据
        UserCompanyJobs jobs = userCompanyJobsService.findById(id);

        //用户头像http://ruya1a2n3.hd-bkt.clouddn.com/1659438854295257088?t=1684575706082
        String staffPhoto = "http://ruya1a2n3.hd-bkt.clouddn.com/" + id + "?t=100";

        //3.填充pdf模版数据,并输出pdf
        Map params = new HashMap();


        Map<String, Object> personalMap = BeanMapUtils.beanToMap(personal);
        Map<String, Object> jobsMap = BeanMapUtils.beanToMap(jobs);

        params.putAll(personalMap);
        params.putAll(jobsMap);
        params.put("staffPhoto" , staffPhoto);

        ServletOutputStream sos = response.getOutputStream();
        try{
            JasperPrint print = JasperFillManager.fillReport(fis , params , new JREmptyDataSource());
            JasperExportManager.exportReportToPdfStream(print , sos);
        }catch (JRException e){
            e.printStackTrace();
        }finally {
            sos.flush();
        }

    }

骚戴理解:注意上面的 staffPhoto图片路径要写自己的七牛云域名!!!然后要用要把数据库里bs_user表里的staff_photo都改成七牛云的url路径(因为只有有的是data url的路径),不然通过Postman测试会下面的报错

BeanMapUtils

package com.ihrm.common.utils;

import org.springframework.cglib.beans.BeanMap;

import java.util.HashMap;
import java.util.Map;

public class BeanMapUtils {

    /**
     * 将对象属性转化为map结合
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key+"", beanMap.get(key));
            }
        }
        return map;
    }

    /**
     * 将map集合中的数据转化为指定对象的同名属性中
     */
    public static <T> T mapToBean(Map<String, Object> map,Class<T> clazz) throws Exception {
        T bean = clazz.newInstance();
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }
}

导入替换src\module-employees\pages\details.vue前端代码

<template>
  <div class="dashboard-container">
    <div class="app-container">
      <el-card>

          <el-tabs v-model="activeName" class="infoPosin">
            <el-tab-pane name="first" class="rInfo">
             
            <div class="fr">
              <a  class="fa fa-print" aria-hidden="true"  title="打印" @click='handleExport()'></a>
              <el-tooltip class="item" effect="dark" content="点击打印按钮->右击打印预览界面->点击'打印'" placement="top-end">
                  <i class="fa fa-question-circle-o" aria-hidden="true"></i>
              </el-tooltip>
            </div>
            

              <span slot="label">登录账户设置</span>
              <component v-bind:is="accountInfo" :objId='objId' ref="user"></component>
            </el-tab-pane>
            <el-tab-pane name="two" class="rInfo">
                <span slot="label">个人详情</span>
                <component v-bind:is="userInfo" :objId='objId' ref="user"></component>
            </el-tab-pane>
            <el-tab-pane name="third" class="rInfo">
                <span slot="label">岗位信息</span>
                <component v-bind:is="postInfo" :objId='objId'></component>
            </el-tab-pane>
        </el-tabs>
      </el-card>
    </div>
  </div>
</template>

<script>
import accountInfo from './../components/details-account-info'
import userInfo from './../components/details-user-info'
import postInfo from './../components/details-post-info'
export default {
  name: 'employeesDetails',
  components: { accountInfo, userInfo, postInfo},
  data() {
    return {
      accountInfo:'accountInfo',
      userInfo: 'userInfo',
      postInfo: 'postInfo',  
      activeName: 'first',
      objId: this.$route.params.id,
      dataList: []
    }
  },
  methods: {
        // 下载文件
    handleExport() {
      let id = this.$route.params.id;
      location.href="http://localhost:9003/employees/"+id+"/pdf"
    },
  }
}
</script>

<style rel="stylesheet/scss" lang="scss">
.el-tabs__content {
  overflow: initial;
}
.logInfo {
  width: 250px;
  float: right;

  h2 {
    margin: 0 0 0 20px;
    padding: 0 0 0 20px;
    height: 40px;
    line-height: 40px;
    border-bottom: 2px solid #e4e7ed;
    font-size: 14px;
    font-weight: normal;
  }
}
.logList {
  li {
    list-style: none;
    padding-left: 80px;
    .logRinfo {
      position: relative;
      padding: 25px 0 0;
      margin-left: 15px;
      .time {
        position: absolute;
        left: -100px;
        top: 25px;
      }
      .logContent {
        position: relative;
      }
      .logContent:before {
        content: '';
        width: 14px;
        height: 14px;
        display: block;
        border-radius: 50px;
        position: absolute;
        left: -24px;
        top: 0;
        z-index: 20;
        border: 1px solid #26a69a;
        background: #fff;
      }
    }
    .logRinfo:before {
      content: '';
      position: absolute;
      left: -18px;
      top: -15px;
      width: 2px;
      height: 40px;
      background-color: #e0e0e0;
    }
  }
}
</style>

<style rel="stylesheet/scss" lang="scss" scoped>
</style>

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

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

相关文章

FastCorrect:语音识别快速纠错模型丨RTC Dev Meetup

前言 「语音处理」是实时互动领域中非常重要的一个场景&#xff0c;在声网发起的「RTC Dev Meetup丨语音处理在实时互动领域的技术实践和应用」活动中&#xff0c;来自百度、寰宇科技和依图的技术专家&#xff0c;围绕该话题进行了相关分享。 本文基于微软亚洲研究院主管研究…

chatgpt赋能python:Python应用图标的SEO优化策略

Python应用图标的SEO优化策略 作为一门跨平台解释型编程语言&#xff0c;Python已经成为越来越多企业和开发者的首选语言之一。在Python应用的推广过程中&#xff0c;图标的设计和SEO优化也变得越来越重要。在本文中&#xff0c;我们将探讨Python应用图标的SEO优化策略&#x…

CCE集群切换OBS共享存储方案

目录 一、背景 二、创建PVC 三、同步nfs数据到OBS 四、变更无状态负载数据储存为OBS 五、卸载弹性文件服务SFS&#xff08;nfs&#xff09; 一、背景 生产环境CEE集群&#xff0c;每个K8s节点挂载同一个华为云弹性文件服务SFS(可以简单的理解为nfs)。无状态应用通过hostPath…

chatgpt赋能python:Python就业岗位:行业热门,前景广阔

Python 就业岗位&#xff1a;行业热门&#xff0c;前景广阔 作为其中一门最受欢迎的编程语言&#xff0c;Python 经常出现在各个行业的招聘需求中。无论是大企业、初创公司&#xff0c;还是政府机构和非营利组织&#xff0c;都需要 Python 专业人士来应对日益增长的数据和技术…

chatgpt赋能python:Python库使用指南

Python库使用指南 Python是一种高级编程语言&#xff0c;拥有丰富而强大的标准库和第三方库。在本文中&#xff0c;将介绍一些主要Python库的使用方法以及如何通过使用它们来提高SEO。 Requests库 Requests是一个流行的第三方库&#xff0c;用于HTTP请求和响应。可以使用它来…

【内网安全-隧道搭建】内网穿透_Spp上线(全双工通信)

目录 Spp&#xff08;特殊协议上线&#xff09; 1、简述&#xff1a; 2、用法&#xff1a; 1、准备 2、服务器 3、客户机 4、cs、msf Spp&#xff08;特殊协议上线&#xff09; 1、简述&#xff1a; 1&#xff09;支持的协议&#xff1a;tcp、udp、rudp&#xff08;可靠…

基于动力学模型的无人驾驶车辆MPC轨迹跟踪算法及carsim+matlab联合仿真学习笔记

目录 1 模型推导及算法分析 1.1 模型推导 1.1.1 车辆动力学模型 1.1.2 线性时变预测模型推导 1.2 模型预测控制器设计 1.2.1 目标函数设计 1.2.2 约束设计 2 代码解析 2.1 模板框架 2.1.1 S-Function 2.1.2 mdlInitializeSizes函数 2.1.3 mdlUpdates()函数 2.1.4 …

机器学习中的数学原理——分类的正则化

通过这篇博客&#xff0c;你将清晰的明白什么是分类的正则化。这个专栏名为白话机器学习中数学学习笔记&#xff0c;主要是用来分享一下我在 机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01…

Go异步任务解决方案 Asynq

今天为大家介绍一个Go处理异步任务的解决方案&#xff1a;Asynq&#xff0c;是一个 Go 库&#xff0c;用于排队任务并与 worker 异步处理它们。它由Redis提供支持&#xff0c;旨在实现可扩展且易于上手。 一、概述 Asynq 是一个 Go 库&#xff0c;用于对任务进行排队并与工作人…

Python爬虫学习-简单爬取网页数据

疫情宅家无事&#xff0c;就随便写一些随笔吧QwQ… 这是一篇介绍如何用Python实现简单爬取网页数据并导入MySQL中的数据库的文章。主要用到BeautifulSoup requests 和 pymysql。 以网页https://jbk.39.net/mxyy/jbzs/为例&#xff0c;假设我们要爬取的部分数据如下图所示&#…

【板栗糖GIS】——如何下载哔哩哔哩的视频CC字幕为不带时间节点的纯文字

【板栗糖GIS】——如何下载哔哩哔哩的视频CC字幕为不带时间节点的纯文字 目录 1. 打开edge浏览器或谷歌浏览器 2. 安装油猴插件 3. 安装字幕插件 4. 打开哔哩哔哩视频播放页面&#xff0c;点击字幕 首先在想要下载之前需要先判定视频是否有云字幕&#xff0c;如果有才可以…

xxl-job详解

什么是xxl-job&#xff1f; ​ xxl-job是一个分布式的任务调度平台&#xff0c;其核心设计目标是&#xff1a;学习简单、开发迅速、轻量级、易扩展&#xff0c;现在已经开放源代码并接入多家公司的线上产品线&#xff0c;开箱即用。xxl是xxl-job的开发者大众点评的许雪里名称的…

SpringBoot+vue 实现监控视频rtsp播放(java+Nginx+ffmpeg+flv.js)

其实原理就是: 将监控通过FFMPEG,推送给Nginx,前端通过Nginx地址拉取视频&#xff0c;就可以播放了。 1:安装FFMPEG. 2:下载并且配置nginx. 3:使用java代码实现调用cmd或者linux窗口,并且运行操作FFMPEG的命令&#xff0c;进行监控视频rtsp格式的推送&#xff0c;推送给nginx. …

模板方法设计模式的学习和使用

1、模板方法设计模式的学习 当涉及到一系列具有相似行为的算法或操作时,模板方法设计模式是一种有效的设计模式。它允许你定义一个算法的骨架,同时将某些步骤的实现细节交给子类来实现。   模板方法模式基于以下两个核心原则&#xff1a; 抽象类定义模板方法骨架&#xff1a…

chatgpt赋能python:Python将一张图片分割成多张:从理论到实践

Python将一张图片分割成多张&#xff1a;从理论到实践 简介 随着Internet的爆炸式增长&#xff0c;图片已经成为了我们生活中不可或缺的一部分。具有高质量、高清晰度的图片可以提升网站的美观程度&#xff0c;帮助网站吸引更多的用户。但是&#xff0c;有时候大型的图片并不…

chatgpt赋能python:Python并不是一门简单的编程语言

Python 并不是一门简单的编程语言 Python 是一门直观且易学的编程语言&#xff0c;这一点没有错&#xff0c;但是要说它是简单的&#xff0c;那其实是不准确的。Python 有着广泛的应用领域&#xff0c;包括人工智能、大数据分析、Web开发、自动化测试等。尽管初学者可以迅速上…

MySQL中BETWEEN AND(范围查询)

0 写在前面 MySQL 提供了 BETWEEN AND 关键字&#xff0c;用来判断字段的数值是否在指定范围内。 BETWEEN AND 需要两个参数&#xff0c;即范围的起始值和终止值。如果字段值在指定的范围内&#xff0c;则这些记录被返回。如果不在指定范围内&#xff0c;则不会被返回。 最近…

JS 装饰器

JS 装饰器 JavaScript 装饰器是一种以 符号开头的特殊语法&#xff0c;放在目标代码的前面用于包装或扩展代码功能。JavaScript 的装饰器语法目前仍处于提案阶段&#xff0c;现阶段使用的话需要通过 bable 等方式进行编译之后&#xff0c;才能在浏览器正常运行。装饰器分为两…

chatgpt赋能python:Python将空值替换成0

Python 将空值替换成 0 在数据分析和处理过程中&#xff0c;清洗数据往往是非常重要的一个环节。而在清洗数据过程中&#xff0c;经常会遇到空值&#xff08;Missing Values&#xff09;的问题。空值是指在数据集中出现的缺失值&#xff0c;它可能是由于数据输入错误、数据采集…

chatgpt赋能python:Python定义数据框:介绍和基础操作

Python定义数据框&#xff1a;介绍和基础操作 数据框是一种非常方便的数据结构&#xff0c;用于在Python中存储和处理表格数据。数据框可以看作是围绕Series对象构建的2D数据结构&#xff0c;Series是一种存储单个列的一维标记数组。在本文中&#xff0c;我们将介绍如何使用Py…