Ver Fonte

fix 统计查询导出PDF

Administrator há 1 ano atrás
pai
commit
3e2e030e0d

+ 11 - 0
ruoyi-common/pom.xml

@@ -16,6 +16,17 @@
     </description>
 
     <dependencies>
+        <!--二维码-->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.1.0</version>
+        </dependency>
 
         <!--pdf导出-->
         <dependency>

+ 7 - 0
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java

@@ -119,4 +119,11 @@ public class RuoYiConfig
     {
         return getProfile() + "/upload";
     }
+
+    /**
+     * 获取系统生成二维码保存路径
+     */
+    public static String getUploadQrPath() {
+        return getProfile() + "/qrUpload";
+    }
 }

+ 239 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java

@@ -0,0 +1,239 @@
+package com.ruoyi.common.utils;
+
+import com.google.zxing.*;
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.HybridBinarizer;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.ruoyi.common.utils.uuid.UUID;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.OutputStream;
+import java.util.Hashtable;
+
+/**
+ * @author tjf
+ * @Date: 2021/12/29/15:09
+ */
+public class QRCodeUtils {
+    private static final String CHARSET = "utf-8";
+    private static final String FORMAT_NAME = "JPG";
+    // 二维码尺寸
+    private static final int QRCODE_SIZE = 300;
+    // LOGO宽度
+    private static final int WIDTH = 60;
+    // LOGO高度
+    private static final int HEIGHT = 60;
+
+    private static BufferedImage createImage(String content, String imgPath,
+                                             boolean needCompress) throws Exception {
+        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
+        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
+        hints.put(EncodeHintType.MARGIN, 1);
+        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
+                BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
+        int width = bitMatrix.getWidth();
+        int height = bitMatrix.getHeight();
+        BufferedImage image = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
+                        : 0xFFFFFFFF);
+            }
+        }
+        if (imgPath == null || "".equals(imgPath)) {
+            return image;
+        }
+        // 插入图片
+        QRCodeUtils.insertImage(image, imgPath, needCompress);
+        return image;
+    }
+
+    /**
+     * 插入LOGO
+     *
+     * @param source       二维码图片
+     * @param imgPath      LOGO图片地址
+     * @param needCompress 是否压缩
+     * @throws Exception
+     */
+    private static void insertImage(BufferedImage source, String imgPath,
+                                    boolean needCompress) throws Exception {
+        File file = new File(imgPath);
+        if (!file.exists()) {
+            System.err.println("" + imgPath + "   该文件不存在!");
+            return;
+        }
+        Image src = ImageIO.read(new File(imgPath));
+        int width = src.getWidth(null);
+        int height = src.getHeight(null);
+        if (needCompress) { // 压缩LOGO
+            if (width > WIDTH) {
+                width = WIDTH;
+            }
+            if (height > HEIGHT) {
+                height = HEIGHT;
+            }
+            Image image = src.getScaledInstance(width, height,
+                    Image.SCALE_SMOOTH);
+            BufferedImage tag = new BufferedImage(width, height,
+                    BufferedImage.TYPE_INT_RGB);
+            Graphics g = tag.getGraphics();
+            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
+            g.dispose();
+            src = image;
+        }
+        // 插入LOGO
+        Graphics2D graph = source.createGraphics();
+        int x = (QRCODE_SIZE - width) / 2;
+        int y = (QRCODE_SIZE - height) / 2;
+        graph.drawImage(src, x, y, width, height, null);
+        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
+        graph.setStroke(new BasicStroke(3f));
+        graph.draw(shape);
+        graph.dispose();
+    }
+
+    /**
+     * 生成二维码(内嵌LOGO)
+     *
+     * @param content      内容
+     * @param imgPath      LOGO地址
+     * @param destPath     存放目录
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static String encode(String content, String imgPath, String destPath,
+                                boolean needCompress) throws Exception {
+        BufferedImage image = QRCodeUtils.createImage(content, imgPath,
+                needCompress);
+        String date = DateUtils.datePath();
+        destPath = destPath+"/" + date;
+        mkdirs(destPath);
+        String file = UUID.randomUUID() + ".jpg";
+        File fileQR = new File(destPath + "/" + file);
+        ImageIO.write(image, FORMAT_NAME, fileQR);
+        return "/profile/qrUpload/"+date+"/"+file;
+    }
+
+
+    /**
+     * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
+     *
+     * @param destPath 存放目录
+     * @date 2013-12-11 上午10:16:36
+     */
+    public static void mkdirs(String destPath) {
+        File file = new File(destPath);
+        //当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
+        if (!file.exists() && !file.isDirectory()) {
+            file.mkdirs();
+        }
+    }
+
+    /**
+     * 生成二维码(内嵌LOGO)
+     *
+     * @param content  内容
+     * @param imgPath  LOGO地址
+     * @param destPath 存储地址
+     * @throws Exception
+     */
+    public static void encode(String content, String imgPath, String destPath)
+            throws Exception {
+        QRCodeUtils.encode(content, imgPath, destPath, false);
+    }
+
+    /**
+     * 生成二维码
+     *
+     * @param content      内容
+     * @param destPath     存储地址
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static void encode(String content, String destPath,
+                              boolean needCompress) throws Exception {
+        QRCodeUtils.encode(content, null, destPath, needCompress);
+    }
+
+    /**
+     * 生成二维码
+     *
+     * @param content  内容
+     * @param destPath 存储地址
+     * @throws Exception
+     */
+    public static void encode(String content, String destPath) throws Exception {
+        QRCodeUtils.encode(content, null, destPath, false);
+    }
+
+    /**
+     * 生成二维码(内嵌LOGO)
+     *
+     * @param content      内容
+     * @param imgPath      LOGO地址
+     * @param output       输出流
+     * @param needCompress 是否压缩LOGO
+     * @throws Exception
+     */
+    public static void encode(String content, String imgPath,
+                              OutputStream output, boolean needCompress) throws Exception {
+        BufferedImage image = QRCodeUtils.createImage(content, imgPath,
+                needCompress);
+        ImageIO.write(image, FORMAT_NAME, output);
+    }
+
+    /**
+     * 生成二维码
+     *
+     * @param content 内容
+     * @param output  输出流
+     * @throws Exception
+     */
+    public static void encode(String content, OutputStream output)
+            throws Exception {
+        QRCodeUtils.encode(content, null, output, false);
+    }
+
+    /**
+     * 解析二维码
+     *
+     * @param file 二维码图片
+     * @return
+     * @throws Exception
+     */
+    public static String decode(File file) throws Exception {
+        BufferedImage image;
+        image = ImageIO.read(file);
+        if (image == null) {
+            return null;
+        }
+        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
+                image);
+        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+        Result result;
+        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
+        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
+        result = new MultiFormatReader().decode(bitmap, hints);
+        String resultStr = result.getText();
+        return resultStr;
+    }
+
+    /**
+     * 解析二维码
+     *
+     * @param path 二维码图片地址
+     * @return
+     * @throws Exception
+     */
+    public static String decode(String path) throws Exception {
+        return QRCodeUtils.decode(new File(path));
+    }
+}

+ 12 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/conference/ZxConference.java

@@ -57,6 +57,18 @@ public class ZxConference extends BaseEntity
 
     /** 政协会议活动-用户关联信息 */
     private List<ZxConferenceUser> zxConferenceUserList;
+    /**
+     * 会议二维码
+     */
+    private String conferenceQr;
+
+    public String getConferenceQr() {
+        return conferenceQr;
+    }
+
+    public void setConferenceQr(String conferenceQr) {
+        this.conferenceQr = conferenceQr;
+    }
 
     public Long getUserId() {
         return userId;

+ 35 - 15
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/StatisticsServiceImpl.java

@@ -17,10 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -102,22 +99,45 @@ public class StatisticsServiceImpl implements IStatisticsService {
         // 2.解析前台传来的echart图,生成pdf段落元素
         Paragraph pictureEle = PDFUtil.createImageFromEncodeBase64(memberInfo.getEle(), "柱状统计图", Float.parseFloat("34"),
                 Float.parseFloat("50"), true);
-        Paragraph pictureElePie = PDFUtil.createImageFromEncodeBase64(memberInfo.getPie(), "柱状统计图", Float.parseFloat("34"),
+        Paragraph picturePie = PDFUtil.createImageFromEncodeBase64(memberInfo.getPie(), "柱状统计图", Float.parseFloat("34"),
                 Float.parseFloat("100"), true);
-
-        // 生成table表格段落(略去此处)
-        // Paragraph table1 = PDFUtil.createTable(xx略, "2、段落名称2", new String[]
-        //{ "数据a1", "数据a2", "数据a3" }, xx略);
-        // Paragraph table2 = PDFUtil.createTable(xx略, "3、段落名称3", xx略, xx略);
-        // Paragraph table3  = PDFUtil.createTable(xx略,"4、段落名称4", xx略, xx略);
+        //查询界别字典值
+        List<SysDictData> dictDataList = dictDataMapper.selectDictDataByType("circles");
+        List<MemberInfoVoTwo> memberInfoVoTwoList = new ArrayList<>();
+        if (dictDataList != null && dictDataList.size() > 0) {
+            //根据委员界别分类统计
+            List<MemberInfo> memberInfoList = memberInfoMapper.selectMemberInfoList(new MemberInfo());
+            if (memberInfoList != null && memberInfoList.size() > 0) {
+                Map<String, List<MemberInfo>> memberInfoCollect = memberInfoList.stream().collect(Collectors.groupingBy(MemberInfo::getBoundary));
+                for (SysDictData sysDictData : dictDataList) {
+                    MemberInfoVoTwo memberInfoVoTwo = new MemberInfoVoTwo();
+                    memberInfoVoTwo.setSort(sysDictData.getDictSort());
+                    String dictLabel = sysDictData.getDictLabel();
+                    String dictValue = sysDictData.getDictValue();
+                    memberInfoVoTwo.setBoundary(dictLabel);
+                    List<MemberInfo> memberInfoListV = memberInfoCollect.get(dictValue);
+                    //如果没这个界别就输入0
+                    if (memberInfoListV != null && memberInfoListV.size() > 0){
+                        memberInfoVoTwo.setNum(memberInfoListV.size());
+                    }else {
+                        memberInfoVoTwo.setNum(0);
+                    }
+                    memberInfoVoTwoList.add(memberInfoVoTwo);
+                }
+            }
+        }
+        List<String> methodNames = new ArrayList<>();
+        methodNames.add("getSort");
+        methodNames.add("getBoundary");
+        methodNames.add("getNum");
+        // 生成table表格段落
+        Paragraph table = PDFUtil.createTable(memberInfoVoTwoList, "界别统计表", new String[]{"序号","界别","人数"},methodNames );
 
         // 将所有需要放到文档里的元素,汇总
         List<Paragraph> paragraphs = new ArrayList<Paragraph>();
         paragraphs.add(pictureEle);
-        //paragraphs.add(table1);
-        //paragraphs.add(table2);
-        //paragraphs.add(table3);
-
+        paragraphs.add(table);
+        paragraphs.add(picturePie);
         // 导出pdf文档:将paragraphs塞到document中,并下载document
         PDFUtil.exportDocument(document, null, paragraphs, response, "报表");
     }

+ 9 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/ZxConferenceServiceImpl.java

@@ -1,7 +1,9 @@
 package com.ruoyi.system.service.impl;
 
 
+import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.QRCodeUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.system.domain.conference.ZxConference;
 import com.ruoyi.system.domain.conference.ZxConferenceUser;
@@ -97,6 +99,13 @@ public class ZxConferenceServiceImpl implements IZxConferenceService {
         zxConference.setCreateTime(DateUtils.getNowDate());
         int rows = zxConferenceMapper.insertZxConference(zxConference);
         insertZxConferenceUser(zxConference);
+        try {
+            String imagePath= QRCodeUtils.encode(zxConference.getConferenceId().toString(), null, RuoYiConfig.getUploadQrPath(), true);
+            zxConference.setConferenceQr(imagePath);
+            zxConferenceMapper.updateZxConference(zxConference);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
         return rows;
     }
 

+ 7 - 3
ruoyi-system/src/main/resources/mapper/system/ZxConferenceMapper.xml

@@ -12,6 +12,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="conferenceTime"    column="conference_time"    />
         <result property="conferenceAddress"    column="conference_address"    />
         <result property="publishTime"    column="publish_time"    />
+        <result property="conferenceQr"    column="conference_qr"    />
         <result property="createBy"    column="create_by"    />
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
@@ -42,11 +43,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectZxConferenceVo">
-        select conference_id, conference_title, conference_date, conference_time, conference_address, publish_time, create_by, create_time, update_by, update_time, remark from zx_conference
+        select conference_id, conference_title, conference_date, conference_time, conference_address, publish_time,conference_qr, create_by, create_time, update_by, update_time, remark from zx_conference
     </sql>
 
     <select id="selectZxConferenceList" parameterType="ZxConference" resultMap="ZxConferenceResult">
-        select a.conference_id, a.conference_title, a.conference_date, a.conference_time, a.conference_address, a.publish_time, a.create_by, a.create_time, a.update_by, a.update_time, a.remark,
+        select a.conference_id, a.conference_title, a.conference_date, a.conference_time, a.conference_address, a.publish_time,a.conference_qr, a.create_by, a.create_time, a.update_by, a.update_time, a.remark,
         b.conference_id as sub_conference_id, b.user_id as sub_user_id, b.user_name as sub_user_name, b.post_name as sub_post_name, b.user_level as sub_user_level, b.reply_time as sub_reply_time, b.is_join as sub_is_join, b.leave_type as sub_leave_type, b.leave_reason as sub_leave_reason,b.sign_in as sub_sign_in, b.create_by as sub_create_by, b.create_time as sub_create_time, b.update_by as sub_update_by, b.update_time as sub_update_time, b.remark as sub_remark
         from zx_conference a
         left join zx_conference_user b on b.conference_id = a.conference_id
@@ -62,7 +63,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
     
     <select id="selectZxConferenceByConferenceId" parameterType="Long" resultMap="ZxConferenceZxConferenceUserResult">
-        select a.conference_id, a.conference_title, a.conference_date, a.conference_time, a.conference_address, a.publish_time, a.create_by, a.create_time, a.update_by, a.update_time, a.remark,
+        select a.conference_id, a.conference_title,a.conference_qr, a.conference_date, a.conference_time, a.conference_address, a.publish_time, a.create_by, a.create_time, a.update_by, a.update_time, a.remark,
  b.conference_id as sub_conference_id, b.user_id as sub_user_id, b.user_name as sub_user_name, b.post_name as sub_post_name, b.user_level as sub_user_level, b.reply_time as sub_reply_time, b.is_join as sub_is_join, b.leave_type as sub_leave_type, b.leave_reason as sub_leave_reason,b.sign_in as sub_sign_in, b.create_by as sub_create_by, b.create_time as sub_create_time, b.update_by as sub_update_by, b.update_time as sub_update_time, b.remark as sub_remark
         from zx_conference a
         left join zx_conference_user b on b.conference_id = a.conference_id
@@ -90,6 +91,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="conferenceTime != null">conference_time,</if>
             <if test="conferenceAddress != null and conferenceAddress != ''">conference_address,</if>
             <if test="publishTime != null">publish_time,</if>
+            <if test="conferenceQr != null">conference_qr,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
@@ -102,6 +104,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="conferenceTime != null">#{conferenceTime},</if>
             <if test="conferenceAddress != null and conferenceAddress != ''">#{conferenceAddress},</if>
             <if test="publishTime != null">#{publishTime},</if>
+            <if test="conferenceQr != null">#{conferenceQr},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
@@ -118,6 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="conferenceTime != null">conference_time = #{conferenceTime},</if>
             <if test="conferenceAddress != null and conferenceAddress != ''">conference_address = #{conferenceAddress},</if>
             <if test="publishTime != null">publish_time = #{publishTime},</if>
+            <if test="conferenceQr != null">conference_qr = #{conferenceQr},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>