xiaof 2 жил өмнө
parent
commit
99bc1aab8f
17 өөрчлөгдсөн 1383 нэмэгдсэн , 37 устгасан
  1. 4 0
      distributed-print-business/pom.xml
  2. 50 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/PdfPackageDto.java
  3. 78 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/PdfSignDto.java
  4. 24 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/BasicTemplate.java
  5. 3 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/BasicTemplateService.java
  6. 5 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/PrintCommonService.java
  7. 26 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/BasicTemplateServiceImpl.java
  8. 155 11
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintCommonServiceImpl.java
  9. 12 19
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/TaskLogicServiceImpl.java
  10. 218 6
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePdfUtil.java
  11. 462 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePrintPdfUtil.java
  12. 307 0
      distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/PdfFillUtils.java
  13. 4 1
      distributed-print-business/src/main/resources/mapper/ExamStudentMapper.xml
  14. 10 0
      distributed-print/src/main/java/com/qmth/distributed/print/api/BasicTemplateController.java
  15. 6 0
      pom.xml
  16. 2 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/contant/SystemConstant.java
  17. 17 0
      teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/ConvertUtil.java

+ 4 - 0
distributed-print-business/pom.xml

@@ -43,6 +43,10 @@
             <groupId>com.itextpdf</groupId>
             <artifactId>itextpdf</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itext-asian</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.google.zxing</groupId>
             <artifactId>core</artifactId>

+ 50 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/PdfPackageDto.java

@@ -0,0 +1,50 @@
+package com.qmth.distributed.print.business.bean.dto;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class PdfPackageDto {
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 卷袋号
+     */
+    private String packageNumber;
+
+    /**
+     * 基础板块信息
+     */
+    private List<Map<String, String>> basicPlate;
+
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getPackageNumber() {
+        return packageNumber;
+    }
+
+    public void setPackageNumber(String packageNumber) {
+        this.packageNumber = packageNumber;
+    }
+
+    public List<Map<String, String>> getBasicPlate() {
+        return basicPlate;
+    }
+
+    public void setBasicPlate(List<Map<String, String>> basicPlate) {
+        this.basicPlate = basicPlate;
+    }
+}

+ 78 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/PdfSignDto.java

@@ -0,0 +1,78 @@
+package com.qmth.distributed.print.business.bean.dto;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ */
+public class PdfSignDto {
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 卷袋号
+     */
+    private String packageNumber;
+
+    /**
+     * 基础板块信息
+     */
+    private List<Map<String, String>> basicPlate;
+
+    /**
+     * 考生表头信息
+     */
+    private Map<String, String> studentHeadPlate;
+
+    /**
+     * 考生信息
+     */
+    private List<Map<String, String>> studentPlate;
+
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getPackageNumber() {
+        return packageNumber;
+    }
+
+    public void setPackageNumber(String packageNumber) {
+        this.packageNumber = packageNumber;
+    }
+
+    public List<Map<String, String>> getBasicPlate() {
+        return basicPlate;
+    }
+
+    public void setBasicPlate(List<Map<String, String>> basicPlate) {
+        this.basicPlate = basicPlate;
+    }
+
+    public Map<String, String> getStudentHeadPlate() {
+        return studentHeadPlate;
+    }
+
+    public void setStudentHeadPlate(Map<String, String> studentHeadPlate) {
+        this.studentHeadPlate = studentHeadPlate;
+    }
+
+    public List<Map<String, String>> getStudentPlate() {
+        return studentPlate;
+    }
+
+    public void setStudentPlate(List<Map<String, String>> studentPlate) {
+        this.studentPlate = studentPlate;
+    }
+
+
+}

+ 24 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/entity/BasicTemplate.java

@@ -48,6 +48,14 @@ public class BasicTemplate extends BaseEntity implements Serializable {
      * SIGN-签到表,PACKAGE-卷袋贴,CHECK_IN-登记表
      */
     private ClassifyEnum classify;
+    /**
+     * 卷袋贴、签到表数据范围
+     */
+    private String displayRange;
+    /**
+     * 预览地址
+     */
+    private String previewPath;
     /**
      * 模板附件ID(保存到附件表ID)
      */
@@ -114,6 +122,22 @@ public class BasicTemplate extends BaseEntity implements Serializable {
         this.classify = classify;
     }
 
+    public String getDisplayRange() {
+        return displayRange;
+    }
+
+    public void setDisplayRange(String displayRange) {
+        this.displayRange = displayRange;
+    }
+
+    public String getPreviewPath() {
+        return previewPath;
+    }
+
+    public void setPreviewPath(String previewPath) {
+        this.previewPath = previewPath;
+    }
+
     public Long getAttachmentId() {
         return attachmentId;
     }

+ 3 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/BasicTemplateService.java

@@ -6,6 +6,7 @@ import com.qmth.distributed.print.business.bean.dto.TemplateDto;
 import com.qmth.distributed.print.business.bean.result.TemplatePrintInfoResult;
 import com.qmth.distributed.print.business.entity.BasicTemplate;
 
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -35,4 +36,6 @@ public interface BasicTemplateService extends IService<BasicTemplate> {
      * @return
      */
     List<TemplatePrintInfoResult> findTemplateInfoByOrgIds(List<Long> ids);
+
+    void preview(HttpServletResponse response, String data);
 }

+ 5 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/PrintCommonService.java

@@ -3,6 +3,8 @@ package com.qmth.distributed.print.business.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.itextpdf.text.DocumentException;
 import com.qmth.distributed.print.business.bean.dto.PdfDto;
+import com.qmth.distributed.print.business.bean.dto.PdfPackageDto;
+import com.qmth.distributed.print.business.bean.dto.PdfSignDto;
 import com.qmth.distributed.print.business.bean.params.ExamTaskStudentObjectParam;
 import com.qmth.distributed.print.business.bean.params.SerialNumberParams;
 import com.qmth.distributed.print.business.entity.ExamDetail;
@@ -46,6 +48,7 @@ public interface PrintCommonService {
      */
     public BasicAttachment saveAttachmentPdf(ClassifyEnum classifyEnum, ExamDetail examDetail, BasicAttachment basicAttachment, List<PdfDto> pdfList, Integer printCount, Integer sequence) throws IOException, DocumentException;
 
+    public void saveAttachmentSignPdf(PdfSignDto pdfFillDto, ExamDetail examDetail, List<PdfDto> pdfList, Integer printCount);
     /**
      * 保存html附件
      *
@@ -289,4 +292,6 @@ public interface PrintCommonService {
      * @param paperType   试卷类型
      */
     public void updateGradeBatchStatus(Long schoolId, String paperNumber, String paperType);
+
+    void saveAttachmentPackagePdf(PdfPackageDto pdfPackageDto, ExamDetail examDetail, List<PdfDto> variablePdfList, Integer printCount);
 }

+ 26 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/BasicTemplateServiceImpl.java

@@ -1,5 +1,7 @@
 package com.qmth.distributed.print.business.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -19,9 +21,12 @@ import com.qmth.distributed.print.business.mapper.BasicTemplateMapper;
 import com.qmth.distributed.print.business.service.BasicTemplateService;
 import com.qmth.distributed.print.business.service.ExamCardDetailService;
 import com.qmth.distributed.print.business.service.ExamCardService;
+import com.qmth.distributed.print.business.util.PdfFillUtils;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.BasicAttachment;
 import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.enums.ClassifyEnum;
+import com.qmth.teachcloud.common.enums.EnumResult;
 import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
 import com.qmth.teachcloud.common.service.BasicAttachmentService;
 import com.qmth.teachcloud.common.service.TeachcloudCommonService;
@@ -31,8 +36,10 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -174,4 +181,23 @@ public class BasicTemplateServiceImpl extends ServiceImpl<BasicTemplateMapper, B
     public List<TemplatePrintInfoResult> findTemplateInfoByOrgIds(List<Long> ids) {
         return basicTemplateMapper.findTemplateInfoByOrgIds(ids);
     }
+
+    @Override
+    public void preview(HttpServletResponse response, String data) {
+        JSONObject jsonObject = JSON.parseObject(data);
+        String classifyStr = jsonObject.getString("classify");
+        List<String> stringList = ClassifyEnum.listTypes().stream().map(EnumResult::getName).collect(Collectors.toList());
+        if (!stringList.contains(classifyStr)) {
+            throw ExceptionResultEnum.ERROR.exception("模板类型有误");
+        }
+        ClassifyEnum classifyEnum = ClassifyEnum.valueOf(classifyStr);
+        // 签到表
+        if (ClassifyEnum.SIGN.equals(classifyEnum)) {
+            PdfFillUtils.parseSignTempData(response, jsonObject.getString("data"), "签到表预览.pdf");
+        } else if (ClassifyEnum.PACKAGE.equals(classifyEnum)) {
+            PdfFillUtils.packageTempData(response, jsonObject.getString("data"), "卷袋贴预览.pdf");
+        } else {
+            throw ExceptionResultEnum.ERROR.exception("不支持当前模板预览");
+        }
+    }
 }

+ 155 - 11
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/PrintCommonServiceImpl.java

@@ -1,6 +1,7 @@
 package com.qmth.distributed.print.business.service.impl;
 
 import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aliyun.oss.common.utils.BinaryUtil;
@@ -13,6 +14,8 @@ import com.itextpdf.text.pdf.PdfReader;
 import com.qmth.boot.api.exception.ApiException;
 import com.qmth.boot.tools.models.ByteArray;
 import com.qmth.distributed.print.business.bean.dto.PdfDto;
+import com.qmth.distributed.print.business.bean.dto.PdfPackageDto;
+import com.qmth.distributed.print.business.bean.dto.PdfSignDto;
 import com.qmth.distributed.print.business.bean.params.ExamTaskStudentObjectParam;
 import com.qmth.distributed.print.business.bean.params.SerialNumberParams;
 import com.qmth.distributed.print.business.entity.*;
@@ -20,6 +23,7 @@ import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
 import com.qmth.distributed.print.business.enums.PrintPlanStatusEnum;
 import com.qmth.distributed.print.business.enums.StudentClazzEnum;
 import com.qmth.distributed.print.business.service.*;
+import com.qmth.distributed.print.business.util.CreatePrintPdfUtil;
 import com.qmth.distributed.print.business.util.HtmlToPdfUtil;
 import com.qmth.distributed.print.business.util.PdfUtil;
 import com.qmth.teachcloud.common.bean.dto.MqDto;
@@ -33,7 +37,6 @@ import com.qmth.teachcloud.common.mapper.BasicCourseMapper;
 import com.qmth.teachcloud.common.service.*;
 import com.qmth.teachcloud.common.util.*;
 import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -144,6 +147,9 @@ public class PrintCommonServiceImpl implements PrintCommonService {
     @Resource
     BasicClazzService basicClazzService;
 
+    @Resource
+    CreatePrintPdfUtil createPrintPdfUtil;
+
     /**
      * 保存附件
      *
@@ -273,6 +279,79 @@ public class PrintCommonServiceImpl implements PrintCommonService {
         return basicAttachment;
     }
 
+    /**
+     * 保存附件
+     *
+     * @param examDetail
+     * @param pdfList
+     * @param printCount
+     */
+    @Override
+    @Transactional
+    public void saveAttachmentSignPdf(PdfSignDto pdfFillDto, ExamDetail examDetail, List<PdfDto> pdfList, Integer printCount) {
+        try {
+            boolean oss = dictionaryConfig.sysDomain().isOss();
+            LocalDateTime nowTime = LocalDateTime.now();
+            StringJoiner pdfStringJoiner = new StringJoiner("");
+            pdfStringJoiner.add(UploadFileEnum.PDF.getTitle()).add(File.separator);
+            pdfStringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
+                    .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
+                    .add(String.format("%02d", nowTime.getDayOfMonth()));
+            pdfStringJoiner.add(File.separator).add(SystemConstant.getUuid()).add(SystemConstant.PDF_PREFIX);
+
+            String pdfDirName = pdfStringJoiner.toString();
+            String pdfDirNameStr = pdfStringJoiner.toString().replace("\\", "/");
+            String destUrl = dictionaryConfig.fssLocalPdfDomain().getConfig() + File.separator + pdfDirName;
+
+            createPrintPdfUtil.createSignPdf(null, pdfFillDto, destUrl, true);
+
+            File pdfFile = new File(destUrl);
+            if (!pdfFile.exists()) {
+                pdfFile.getParentFile().mkdirs();
+                pdfFile.createNewFile();
+            }
+            byte[] data = ByteArray.fromFile(pdfFile).value();
+            String md5 = ByteArray.md5(data).toHexString();
+            InputStream ins = new ByteArrayInputStream(data);
+            PdfDto pdfDto = PdfUtil.addPdfPage(pdfFile);
+            if (oss) {//上传至oss
+                fileStoreUtil.ossUpload(pdfDirNameStr, ins, md5, fileStoreUtil.getUploadEnumByPath(pdfDirNameStr).getFssType());
+                ins.close();
+            }
+            JSONObject attachmentPath = JSONObject.parseObject(examDetail.getAttachmentPath());
+            attachmentPath = Objects.isNull(attachmentPath) ? new JSONObject() : attachmentPath;
+            JSONArray jsonArray = (JSONArray) attachmentPath.get(SystemConstant.PATH);
+            jsonArray = Objects.isNull(jsonArray) ? new JSONArray() : jsonArray;
+            JSONObject object = new JSONObject();
+            object.put("printType", ClassifyEnum.SIGN.name());
+            object.put("pdfMd5", md5);
+            if (!oss) {
+                object.put(SystemConstant.PDF_PATH, pdfFile.getPath());
+                object.put(SystemConstant.TYPE, SystemConstant.LOCAL);
+            } else {
+                object.put(SystemConstant.PDF_PATH, pdfDirNameStr);
+                object.put(SystemConstant.TYPE, SystemConstant.OSS);
+            }
+            object.put(SystemConstant.UPLOAD_TYPE, new UploadFileEnum[]{
+                    UploadFileEnum.HTML,
+                    UploadFileEnum.PDF
+            });
+            jsonArray.add(object);
+            attachmentPath.put(SystemConstant.PATH, jsonArray);
+            examDetail.setAttachmentPath(attachmentPath.toJSONString());
+            for (int i = 0; i < printCount; i++) {
+                pdfList.add(new PdfDto(pdfFile.getPath(), PageSizeEnum.A4, pdfDto.getPageCount(), 2));
+            }
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        }
+    }
+
     /**
      * 保存html附件
      *
@@ -563,7 +642,7 @@ public class PrintCommonServiceImpl implements PrintCommonService {
                 jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
                 jsonObject.put(SystemConstant.PATH, dirName);
             } else {//上传至服务器
-                fileStoreUtil.localUpload(dirName,file.getInputStream(),md5,LocalCatalogEnum.LOCAL_FILE);
+                fileStoreUtil.localUpload(dirName, file.getInputStream(), md5, LocalCatalogEnum.LOCAL_FILE);
                 jsonObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                 jsonObject.put(SystemConstant.PATH, dirName);
             }
@@ -1115,24 +1194,24 @@ public class PrintCommonServiceImpl implements PrintCommonService {
             StudentClazzEnum studentClazzType = student.getStudentClazzType();
 
             BasicStudent basicStudent = basicStudentService.getById(studentId);
-            if (Objects.isNull(basicStudent)){
+            if (Objects.isNull(basicStudent)) {
                 throw ExceptionResultEnum.ERROR.exception("未找到基础学生信息");
             }
-            if (!Objects.equals(basicStudent.getClazzId(), basicClazzId)){
+            if (!Objects.equals(basicStudent.getClazzId(), basicClazzId)) {
                 throw ExceptionResultEnum.ERROR.exception("行政班数据不一致");
             }
             BasicClazz basicClazz = null;
-            if (SystemConstant.longNotNull(basicClazzId)){
+            if (SystemConstant.longNotNull(basicClazzId)) {
                 basicClazz = basicClazzService.getById(basicClazzId);
-                if (Objects.isNull(basicClazz)){
+                if (Objects.isNull(basicClazz)) {
                     throw ExceptionResultEnum.ERROR.exception("未找到行政班");
                 }
             }
 
             TeachClazz teachClazz = null;
-            if (SystemConstant.longNotNull(teachClazzId)){
+            if (SystemConstant.longNotNull(teachClazzId)) {
                 teachClazz = teachClazzService.getById(teachClazzId);
-                if (Objects.isNull(teachClazz)){
+                if (Objects.isNull(teachClazz)) {
                     throw ExceptionResultEnum.ERROR.exception("未找到教学班");
                 }
             }
@@ -1149,12 +1228,12 @@ public class PrintCommonServiceImpl implements PrintCommonService {
             examStudent.setExtendFields(extendFields);
             examStudent.setCreateId(sysUser.getId());
             // 行政班数据
-            if (Objects.nonNull(basicClazz)){
+            if (Objects.nonNull(basicClazz)) {
                 examStudent.setClazzId(String.valueOf(basicClazz.getId()));
                 examStudent.setClazzName(basicClazz.getClazzName());
             }
             // 教学班模式 教学班数据
-            if (Objects.nonNull(teachClazz)){
+            if (Objects.nonNull(teachClazz)) {
                 examStudent.setTeachClazzId(teachClazz.getId());
                 examStudent.setTeachClazzName(teachClazz.getTeachClazzName());
             }
@@ -1198,7 +1277,7 @@ public class PrintCommonServiceImpl implements PrintCommonService {
                 fileStoreUtil.ossUpload(dirName, inputStream, DigestUtils.md5Hex(new ByteArrayInputStream(fos.toByteArray())), UploadFileEnum.FILE.getFssType());
                 jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
             } else {
-                fileStoreUtil.copyInputStreamToFile(inputStream,new File(stringJoiner.toString()),DigestUtils.md5Hex(new ByteArrayInputStream(fos.toByteArray())),LocalCatalogEnum.LOCAL_FILE);
+                fileStoreUtil.copyInputStreamToFile(inputStream, new File(stringJoiner.toString()), DigestUtils.md5Hex(new ByteArrayInputStream(fos.toByteArray())), LocalCatalogEnum.LOCAL_FILE);
                 jsonObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
             }
             jsonObject.put(SystemConstant.PATH, dirName);
@@ -1254,4 +1333,69 @@ public class PrintCommonServiceImpl implements PrintCommonService {
             }
         }
     }
+
+    @Override
+    public void saveAttachmentPackagePdf(PdfPackageDto pdfPackageDto, ExamDetail examDetail, List<PdfDto> pdfList, Integer printCount) {
+        try {
+            boolean oss = dictionaryConfig.sysDomain().isOss();
+            LocalDateTime nowTime = LocalDateTime.now();
+            StringJoiner pdfStringJoiner = new StringJoiner("");
+            pdfStringJoiner.add(UploadFileEnum.PDF.getTitle()).add(File.separator);
+            pdfStringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
+                    .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
+                    .add(String.format("%02d", nowTime.getDayOfMonth()));
+            pdfStringJoiner.add(File.separator).add(SystemConstant.getUuid()).add(SystemConstant.PDF_PREFIX);
+
+            String pdfDirName = pdfStringJoiner.toString();
+            String pdfDirNameStr = pdfStringJoiner.toString().replace("\\", "/");
+            String destUrl = dictionaryConfig.fssLocalPdfDomain().getConfig() + File.separator + pdfDirName;
+
+            createPrintPdfUtil.createPackagePdf(null, pdfPackageDto, destUrl, true);
+
+            File pdfFile = new File(destUrl);
+            if (!pdfFile.exists()) {
+                pdfFile.getParentFile().mkdirs();
+                pdfFile.createNewFile();
+            }
+            byte[] data = ByteArray.fromFile(pdfFile).value();
+            String md5 = ByteArray.md5(data).toHexString();
+            InputStream ins = new ByteArrayInputStream(data);
+            PdfDto pdfDto = PdfUtil.addPdfPage(pdfFile);
+            if (oss) {//上传至oss
+                fileStoreUtil.ossUpload(pdfDirNameStr, ins, md5, fileStoreUtil.getUploadEnumByPath(pdfDirNameStr).getFssType());
+                ins.close();
+            }
+            JSONObject attachmentPath = JSON.parseObject(examDetail.getAttachmentPath());
+            attachmentPath = Objects.isNull(attachmentPath) ? new JSONObject() : attachmentPath;
+            JSONArray jsonArray = (JSONArray) attachmentPath.get(SystemConstant.PATH);
+            jsonArray = Objects.isNull(jsonArray) ? new JSONArray() : jsonArray;
+            JSONObject object = new JSONObject();
+            object.put("printType", ClassifyEnum.PACKAGE.name());
+            object.put("pdfMd5", md5);
+            if (!oss) {
+                object.put(SystemConstant.PDF_PATH, pdfFile.getPath());
+                object.put(SystemConstant.TYPE, SystemConstant.LOCAL);
+            } else {
+                object.put(SystemConstant.PDF_PATH, pdfDirNameStr);
+                object.put(SystemConstant.TYPE, SystemConstant.OSS);
+            }
+            object.put(SystemConstant.UPLOAD_TYPE, new UploadFileEnum[]{
+                    UploadFileEnum.HTML,
+                    UploadFileEnum.PDF
+            });
+            jsonArray.add(object);
+            attachmentPath.put(SystemConstant.PATH, jsonArray);
+            examDetail.setAttachmentPath(attachmentPath.toJSONString());
+            for (int i = 0; i < printCount; i++) {
+                pdfList.add(new PdfDto(pdfFile.getPath(), PageSizeEnum.A4, pdfDto.getPageCount(), 2));
+            }
+        } catch (Exception e) {
+            log.error(SystemConstant.LOG_ERROR, e);
+            if (e instanceof ApiException) {
+                ResultUtil.error((ApiException) e, e.getMessage());
+            } else {
+                ResultUtil.error(e.getMessage());
+            }
+        }
+    }
 }

+ 12 - 19
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/TaskLogicServiceImpl.java

@@ -22,6 +22,7 @@ import com.qmth.distributed.print.business.enums.*;
 import com.qmth.distributed.print.business.service.*;
 import com.qmth.distributed.print.business.templete.service.TaskLogicService;
 import com.qmth.distributed.print.business.util.CreatePdfUtil;
+import com.qmth.distributed.print.business.util.CreatePrintPdfUtil;
 import com.qmth.distributed.print.business.util.HtmlToPdfUtil;
 import com.qmth.teachcloud.common.annotation.ExcelDBFieldDesc;
 import com.qmth.teachcloud.common.base.BaseEntity;
@@ -118,6 +119,9 @@ public class TaskLogicServiceImpl implements TaskLogicService {
     @Resource
     CreatePdfUtil createPdfUtil;
 
+    @Resource
+    CreatePrintPdfUtil createPrintPdfUtil;
+
     @Resource
     RedisTemplate<String, Object> redisTemplate;
 
@@ -452,19 +456,15 @@ public class TaskLogicServiceImpl implements TaskLogicService {
      * @param examPrintPlan
      * @param examDetail
      * @param basicSchool
-     * @param ftlList
      * @param examDetailCourseList
      * @param list
      * @throws IOException
      * @throws DocumentException
      */
     @Transactional
-    public void createA4File(ExamPrintPlan examPrintPlan, ExamDetail examDetail, BasicSchool basicSchool, Set<File> ftlList, List<ExamDetailCourse> examDetailCourseList, List<PdfDto>... list) throws Exception {
+    public void createA4File(ExamPrintPlan examPrintPlan, ExamDetail examDetail, BasicSchool basicSchool, List<ExamDetailCourse> examDetailCourseList, List<PdfDto>... list) throws Exception {
         // 印品
-        List<Long> examDetailCourseListIds = examDetailCourseList.stream().map(BaseEntity::getId).collect(Collectors.toList());
-
         String ordinaryContent = examPrintPlan.getOrdinaryContent();
-
         if (StringUtils.isNotBlank(ordinaryContent)) {
             //获取普通印品
             JSONArray jsonArrayOrdinary = JSONArray.parseArray(ordinaryContent);
@@ -479,8 +479,8 @@ public class TaskLogicServiceImpl implements TaskLogicService {
         }
 
         String variableContent = examPrintPlan.getVariableContent();
-
         if (StringUtils.isNotBlank(variableContent)) {
+            List<Long> examDetailCourseListIds = examDetailCourseList.stream().map(BaseEntity::getId).collect(Collectors.toList());
             List<ExamStudentCourseDto> examStudentCourseDtoList = examStudentService.queryBySchoolIdAndExamDetailCourseIds(basicSchool.getId(), examDetailCourseListIds);
             int count = (int) examStudentCourseDtoList.stream().filter(s -> s.getPaperPageA3() != null && s.getPaperPageA3() > 2).count();
             boolean tag = count > 0;
@@ -490,25 +490,18 @@ public class TaskLogicServiceImpl implements TaskLogicService {
             for (int i = 0; i < jsonArrayVariable.size(); i++) {
                 JSONObject jsonObjectVariable = jsonArrayVariable.getJSONObject(i);
                 String type = (String) jsonObjectVariable.get("type");
-                if (Objects.nonNull(jsonObjectVariable.get("attachmentId")) && !Objects.equals("", jsonObjectVariable.get("attachmentId"))) {
-                    Long attachmentId = Long.parseLong((String) jsonObjectVariable.get("attachmentId"));
-                    BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
-                    ftlList.add(teachcloudCommonService.getFile(basicAttachment.getPath(), false));
+                if (Objects.nonNull(jsonObjectVariable.get("templateId")) && !Objects.equals("", jsonObjectVariable.get("templateId"))) {
+                    Long templateId = Long.parseLong((String) jsonObjectVariable.get("templateId"));
                     if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "SIGN")) {//签到表
-                        createPdfUtil.createSignBook(basicAttachment, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"), examDetailCourseList);
+                        createPdfUtil.createSignBook(templateId, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"), examDetailCourseList);
                     } else if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "PACKAGE")) {//卷袋贴
-                        createPdfUtil.createPaperPackage(tag, basicAttachment, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"), examDetailCourseList);
+                        createPdfUtil.createPaperPackage(templateId, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"), examDetailCourseList);
                     }
                 }
             }
         }
 
-        Collections.sort(list[1], new Comparator<PdfDto>() {
-            @Override
-            public int compare(PdfDto o1, PdfDto o2) {
-                return o1.getSequence() > o2.getSequence() ? 1 : -1;
-            }
-        });
+        list[1].sort((o1, o2) -> o1.getSequence() > o2.getSequence() ? 1 : -1);
     }
 
     /**
@@ -587,7 +580,7 @@ public class TaskLogicServiceImpl implements TaskLogicService {
                         paperPdfList,
                         examStudentPdfList);
 
-                createA4File(examPrintPlan, examDetail, basicSchool, ftlList, examDetailCourseList, ordinaryPdfList, variablePdfList);
+                createA4File(examPrintPlan, examDetail, basicSchool, examDetailCourseList, ordinaryPdfList, variablePdfList);
 
                 //合并A3(试卷+题卡+备用试卷+备用题卡)
 //                String dirNameA3 = createPdfUtil.mergeA3Pdf(paperPdfList, examStudentPdfList, backupPaperPdfList, backupCardPdfList);

+ 218 - 6
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePdfUtil.java

@@ -2,6 +2,7 @@ package com.qmth.distributed.print.business.util;
 
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ReflectUtil;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -11,6 +12,7 @@ import com.qmth.distributed.print.business.cache.CreatePdfCacheUtil;
 import com.qmth.distributed.print.business.entity.*;
 import com.qmth.distributed.print.business.enums.ExamDetailStatusEnum;
 import com.qmth.distributed.print.business.enums.PrintMethodEnum;
+import com.qmth.distributed.print.business.service.BasicTemplateService;
 import com.qmth.distributed.print.business.service.ExamDetailService;
 import com.qmth.distributed.print.business.service.ExamStudentService;
 import com.qmth.distributed.print.business.service.PrintCommonService;
@@ -100,6 +102,9 @@ public class CreatePdfUtil {
     @Resource
     ExamStudentService examStudentService;
 
+    @Resource
+    BasicTemplateService basicTemplateService;
+
     @Resource
     DictionaryConfig dictionaryConfig;
 
@@ -276,6 +281,82 @@ public class CreatePdfUtil {
         freemarkerUtil.createPaperPackage(htmlMap);
     }
 
+    /**
+     * 生成卷袋贴
+     *
+     * @param schoolName
+     * @param examStudentList
+     * @param variablePdfList
+     * @param printCount
+     * @param examDetailCourseList
+     * @throws IOException
+     */
+    public void createPaperPackage(Long templateId, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer printCount, List<ExamDetailCourse> examDetailCourseList) throws IOException {
+        BasicTemplate basicTemplate = basicTemplateService.getById(templateId);
+        if (Objects.isNull(basicTemplate)) {
+            throw ExceptionResultEnum.ERROR.exception("印品数据有误");
+        }
+
+        List<JSONObject> objectList = JSON.parseArray(basicTemplate.getDisplayRange(), JSONObject.class);
+
+        PdfPackageDto pdfPackageDto = new PdfPackageDto();
+        pdfPackageDto.setTitle(schoolName + "卷袋贴");
+        pdfPackageDto.setPackageNumber(examDetail.getPackageCode());
+
+        // 基础信息
+        List<Map<String, String>> basicPlate = new ArrayList<>();
+        for (JSONObject jsonObject : objectList) {
+            Map<String, String> basicMap = new HashMap<>();
+            if (jsonObject.getBoolean("enable")) {
+                String code = jsonObject.getString("code");
+                String name = jsonObject.getString("name");
+                basicMap.put("code", "courseCode");
+                basicMap.put("name", "课程代码");
+                if ("examTime".equals(code)) {
+                    String startDate = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DATE_PATTERN);
+                    String endDate = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DATE_PATTERN);
+                    String startTime = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.TIME_PATTERN);
+                    String endTime = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.TIME_PATTERN);
+                    String examTime;
+                    if (startDate.equals(endDate)) {
+                        examTime = startDate + " " + startTime + "-" + endTime;
+                    } else {
+                        examTime = startDate + " " + startTime + "-" + endDate + " " + endTime;
+                    }
+                    basicMap.put("value", examTime);
+                } else if ("courseName".equals(code)) {
+                    List<String> courseNames = examDetailCourseList.stream().map(m -> String.format("s%(s%)", m.getCourseName(), m.getCourseCode())).collect(Collectors.toList());
+                    basicMap.put("value", String.join(",", courseNames));
+                } else if ("paperNumber".equals(code)) {
+                    List<String> paperNumbers = examDetailCourseList.stream().map(ExamDetailCourse::getPaperNumber).collect(Collectors.toList());
+                    basicMap.put("value", String.join(",", paperNumbers));
+                } else if ("examPlace".equals(code)) {
+                    basicMap.put("value", examDetail.getExamPlace());
+                } else if ("examRoom".equals(code)) {
+                    basicMap.put("value", examDetail.getExamRoom());
+                } else if ("collegeName".equals(code)) {
+                    Set<String> collegeNames = examStudentList.stream().map(ExamStudent::getCollegeName).collect(Collectors.toSet());
+                    basicMap.put("value", String.join(",", collegeNames));
+                } else if ("majorName".equals(code)) {
+                    Set<String> stringSet = new HashSet<>();
+                    Set<String> clazzNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getClazzName())).map(ExamStudent::getClazzName).collect(Collectors.toSet());
+                    if (!clazzNames.isEmpty()) {
+                        stringSet.addAll(clazzNames);
+                    }
+                    Set<String> teachClazzNames = examStudentList.stream().filter(m -> StringUtils.isNotBlank(m.getTeachClazzName())).map(ExamStudent::getTeachClazzName).collect(Collectors.toSet());
+                    if (!teachClazzNames.isEmpty()) {
+                        stringSet.addAll(teachClazzNames);
+                    }
+                    basicMap.put("value", String.join(",", stringSet));
+                }
+                basicPlate.add(basicMap);
+
+            }
+        }
+        pdfPackageDto.setBasicPlate(basicPlate);
+        printCommonService.saveAttachmentPackagePdf(pdfPackageDto, examDetail, variablePdfList, printCount);
+    }
+
     /**
      * 创建签到表
      *
@@ -287,7 +368,9 @@ public class CreatePdfUtil {
      * @param printCount
      * @param examDetailCourseList
      */
-    public void createSignBook(BasicAttachment basicAttachment, String schoolName, ExamDetail examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer printCount, List<ExamDetailCourse> examDetailCourseList) throws IOException {
+    public void createSignBook(BasicAttachment basicAttachment, String schoolName, ExamDetail
+            examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer
+                                       printCount, List<ExamDetailCourse> examDetailCourseList) throws IOException {
         if (Objects.isNull(basicAttachment)) {
             throw ExceptionResultEnum.ATTACHMENT_IS_NULL.exception();
         }
@@ -467,6 +550,128 @@ public class CreatePdfUtil {
         freemarkerUtil.createSignBook(htmlMap);
     }
 
+    /**
+     * 创建签到表
+     *
+     * @param templateId
+     * @param schoolName
+     * @param examDetail
+     * @param examStudentList
+     * @param variablePdfList
+     * @param printCount
+     * @param examDetailCourseList
+     */
+    public void createSignBook(Long templateId, String schoolName, ExamDetail
+            examDetail, List<ExamStudentCourseDto> examStudentList, List<PdfDto> variablePdfList, Integer
+                                       printCount, List<ExamDetailCourse> examDetailCourseList) {
+        BasicTemplate basicTemplate = basicTemplateService.getById(templateId);
+        if (Objects.isNull(basicTemplate)) {
+            throw ExceptionResultEnum.ERROR.exception("印品数据有误");
+        }
+        PdfSignDto pdfFillDto = new PdfSignDto();
+        pdfFillDto.setTitle(schoolName + "签到表");
+        pdfFillDto.setPackageNumber(examDetail.getPackageCode());
+
+        JSONObject jsonObject = JSON.parseObject(basicTemplate.getDisplayRange());
+        List<JSONObject> objectList = JSON.parseArray(jsonObject.getString("basic"), JSONObject.class);
+
+        // 基础信息
+        List<Map<String, String>> basicPlate = new ArrayList<>();
+        for (JSONObject object : objectList) {
+            if (!object.getBoolean("enable")) {
+                continue;
+            }
+            String code = object.getString("code");
+            String name = object.getString("name");
+            if ("courseName".equals(code)) {
+                List<String> courseNames = examDetailCourseList.stream().map(m -> String.format("s%(s%)", m.getCourseName(), m.getCourseCode())).collect(Collectors.toList());
+                Map<String, String> basicMap = new HashMap<>();
+                basicMap.put("code", code);
+                basicMap.put("name", name);
+                basicMap.put("value", String.join(",", courseNames));
+                basicPlate.add(basicMap);
+            } else if ("paperNumber".equals(code)) {
+                List<String> paperNumbers = examDetailCourseList.stream().map(ExamDetailCourse::getPaperNumber).collect(Collectors.toList());
+                Map<String, String> basicMap = new HashMap<>();
+                basicMap.put("code", code);
+                basicMap.put("name", name);
+                basicMap.put("value", String.join(",", paperNumbers));
+                basicPlate.add(basicMap);
+            } else if ("examTime".equals(code)) {
+                String startDate = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.DATE_PATTERN);
+                String endDate = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.DATE_PATTERN);
+                String startTime = DateUtil.format(new Date(examDetail.getExamStartTime()), SystemConstant.TIME_PATTERN);
+                String endTime = DateUtil.format(new Date(examDetail.getExamEndTime()), SystemConstant.TIME_PATTERN);
+                String examTime;
+                if (startDate.equals(endDate)) {
+                    examTime = startDate + " " + startTime + "-" + endTime;
+                } else {
+                    examTime = startDate + " " + startTime + "-" + endDate + " " + endTime;
+                }
+                Map<String, String> basicMap = new HashMap<>();
+                basicMap.put("code", code);
+                basicMap.put("name", name);
+                basicMap.put("value", examTime);
+                basicPlate.add(basicMap);
+            } else if ("examRoom".equals(code)) {
+                Map<String, String> basicMap = new HashMap<>();
+                basicMap.put("code", code);
+                basicMap.put("name", name);
+                basicMap.put("value", examDetail.getExamRoom());
+                basicPlate.add(basicMap);
+            } else if ("examCount".equals(code)) {
+                Map<String, String> basicMap = new HashMap<>();
+                basicMap.put("code", code);
+                basicMap.put("name", name);
+                basicMap.put("value", String.valueOf(examStudentList.size()));
+                basicPlate.add(basicMap);
+            } else if ("actualExamCount".equals(code)) {
+                Map<String, String> basicMap = new HashMap<>();
+                basicMap.put("code", code);
+                basicMap.put("name", name);
+                basicMap.put("value", "");
+                basicPlate.add(basicMap);
+            }
+        }
+        pdfFillDto.setBasicPlate(basicPlate);
+
+        // 表头信息
+        List<JSONObject> tableList = JSON.parseArray(jsonObject.getString("table"), JSONObject.class);
+        Map<String, String> studentHeadPlateMap = new LinkedHashMap<>();
+        for (JSONObject object : tableList) {
+            if (object.getBoolean("enable")) {
+                studentHeadPlateMap.put(object.getString("code"), object.getString("name"));
+            }
+        }
+        studentHeadPlateMap.put("studentSign", "签名");
+        pdfFillDto.setStudentHeadPlate(studentHeadPlateMap);
+
+        // 考生信息
+        List<Map<String, String>> studentPlate = new ArrayList<>();
+        for (ExamStudentCourseDto examStudentCourseDto : examStudentList) {
+            Map<String, String> studentMap = new LinkedHashMap<>();
+            if (studentHeadPlateMap.containsKey("studentName")) {
+                studentMap.put("studentName", examStudentCourseDto.getStudentName());
+            }
+            if (studentHeadPlateMap.containsKey("studentCode")) {
+                studentMap.put("studentCode", examStudentCourseDto.getStudentCode());
+            }
+            if (studentHeadPlateMap.containsKey("className")) {
+                studentMap.put("className", StringUtils.isBlank(examStudentCourseDto.getTeachClazzName()) ? examStudentCourseDto.getClazzName() : examStudentCourseDto.getClazzName());
+            }
+            if (studentHeadPlateMap.containsKey("ticketNumber")) {
+                studentMap.put("ticketNumber", examStudentCourseDto.getTicketNumber());
+            }
+            if (studentHeadPlateMap.containsKey("studentSign")) {
+                studentMap.put("studentSign", "");
+            }
+            studentPlate.add(studentMap);
+        }
+        pdfFillDto.setStudentPlate(studentPlate);
+
+        printCommonService.saveAttachmentSignPdf(pdfFillDto, examDetail, variablePdfList, printCount);
+    }
+
     /**
      * 替换html通用模版中的条码信息
      *
@@ -552,7 +757,8 @@ public class CreatePdfUtil {
      * @param paperPdfDto  抽取的试卷文件信息
      * @param pdfList      考生试卷集合
      */
-    public PdfDto getExamStudentPaperPdf(String stuPaperType, List<PaperPdfDto> paperPdfDto, List<PdfDto> pdfList) throws IOException {
+    public PdfDto getExamStudentPaperPdf(String
+                                                 stuPaperType, List<PaperPdfDto> paperPdfDto, List<PdfDto> pdfList) throws IOException {
         Set<Integer> pagesList = new HashSet<>();
         if (!CollectionUtils.isEmpty(paperPdfDto)) {
             for (PaperPdfDto dto : paperPdfDto) {
@@ -577,7 +783,8 @@ public class CreatePdfUtil {
      * @param backupCount 备份数量
      * @param pdfList     备份试卷集合
      */
-    public PdfDto getPaperPdf(List<PaperPdfDto> paperPdfDto, Integer backupCount, List<PdfDto> pdfList) throws IOException {
+    public PdfDto getPaperPdf(List<PaperPdfDto> paperPdfDto, Integer backupCount, List<PdfDto> pdfList) throws
+            IOException {
         Set<Integer> pagesList = new HashSet<>();
         boolean tag = false;
         if (!CollectionUtils.isEmpty(paperPdfDto)) {
@@ -900,7 +1107,9 @@ public class CreatePdfUtil {
      * @param examStudentPdfList 考生题卡集合
      * @param basicCardRule      题卡规则
      */
-    public BasicAttachment examStudentHtml(String studentContent, ExamStudent examStudent, String paperType, ExamDetail examDetail, ExamDetailCourse examDetailCourse, Long userId, List<PdfDto> examStudentPdfList, BasicCardRule basicCardRule) throws IOException {
+    public BasicAttachment examStudentHtml(String studentContent, ExamStudent examStudent, String
+            paperType, ExamDetail examDetail, ExamDetailCourse examDetailCourse, Long
+                                                   userId, List<PdfDto> examStudentPdfList, BasicCardRule basicCardRule) throws IOException {
         String studentHtml = studentContent;
             /*if (Objects.nonNull(examStudent.getExtendFields())) {
                 JSONArray jsonObjectExtend = (JSONArray) JSONArray.parse(examStudent.getExtendFields());//扩展字段
@@ -955,7 +1164,8 @@ public class CreatePdfUtil {
      * @param examStudent   考生对象
      * @param basicCardRule 题卡规则对象
      */
-    private List<StudentExtendDto> createExtendObject(ExamDetail examDetail, ExamStudent examStudent, BasicCardRule basicCardRule) {
+    private List<StudentExtendDto> createExtendObject(ExamDetail examDetail, ExamStudent examStudent, BasicCardRule
+            basicCardRule) {
         ExamStudentPdfInfoDto examStudentPdfInfoDto = examStudent == null ? null : examStudentService.getByStudentId(examStudent.getId());
         if (basicCardRule == null) {
             return null;
@@ -1052,7 +1262,9 @@ public class CreatePdfUtil {
      * @param cardPdfList      备用题卡集合
      * @param basicCardRule    题卡规则对象
      */
-    public BasicAttachment cardHtml(String sequence, String cardContent, ExamDetail examDetail, ExamDetailCourse examDetailCourse, JSONArray jsonArray, Long userId, List<PdfDto> cardPdfList, BasicCardRule basicCardRule) throws IOException {
+    public BasicAttachment cardHtml(String sequence, String cardContent, ExamDetail examDetail, ExamDetailCourse
+            examDetailCourse, JSONArray jsonArray, Long userId, List<PdfDto> cardPdfList, BasicCardRule basicCardRule) throws
+            IOException {
         //通用题卡
         String cardTemp = cardContent;
         cardTemp = cardTemp.replaceAll("\\$\\{paperTypeName\\}", examDetailCourse.getPaperType());

+ 462 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/CreatePrintPdfUtil.java

@@ -0,0 +1,462 @@
+package com.qmth.distributed.print.business.util;
+
+import com.itextpdf.text.*;
+import com.itextpdf.text.pdf.*;
+import com.qmth.distributed.print.business.bean.dto.ExamStudentCourseDto;
+import com.qmth.distributed.print.business.bean.dto.PdfDto;
+import com.qmth.distributed.print.business.bean.dto.PdfPackageDto;
+import com.qmth.distributed.print.business.bean.dto.PdfSignDto;
+import com.qmth.distributed.print.business.entity.ExamDetail;
+import com.qmth.distributed.print.business.entity.ExamDetailCourse;
+import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
+import com.qmth.teachcloud.common.util.ConvertUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+import java.util.*;
+
+/**
+ * pdf模板内容填充
+ */
+@Component
+public class CreatePrintPdfUtil {
+    private static final Logger log = LoggerFactory.getLogger(CreatePrintPdfUtil.class);
+
+    /**
+     * 签到表生成
+     *
+     * @param response     response
+     * @param pdfFillDto   签到表数据
+     * @param destFileName 文件名
+     * @param saveLocal    是事保存本地文件
+     */
+    public void createSignPdf(HttpServletResponse response, PdfSignDto pdfFillDto, String destFileName, boolean saveLocal) throws Exception {
+
+        // 1:建立Document对象实例
+        Document document = new Document(PageSize.A4, 36.0F, 36.0F, 40F, 36.0F);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try {
+            // 2:建立一个PDF 写入器与document对象关联通过书写器(Writer)可以将文档写入到磁盘中
+            PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
+
+            //3、设置pdf页眉和页脚和水印
+            MyHeaderFooter headerFooter = new MyHeaderFooter();
+            pdfWriter.setPageEvent(headerFooter);
+
+            // 3:打开文档
+            document.open();
+            //生成pdf
+            this.generateSignPDF(document, pdfWriter, pdfFillDto);
+            // 5:关闭文档
+            document.close();
+        } catch (DocumentException e) {
+            e.printStackTrace();
+        }
+        if (saveLocal) {
+            PdfFillUtils.saveFile(baos, destFileName);
+        } else {
+            ConvertUtil.outputFile(response, baos, destFileName);
+        }
+    }
+
+    /**
+     * 卷袋贴生成
+     *
+     * @param response      response
+     * @param pdfPackageDto 卷袋贴参数
+     * @param destFileName  保存文件名
+     * @param saveLocal     是否保存本地
+     */
+    public void createPackagePdf(HttpServletResponse response, PdfPackageDto pdfPackageDto, String destFileName, boolean saveLocal) throws Exception {
+
+        // 1:建立Document对象实例
+        Document document = new Document(PageSize.A4, 36.0F, 36.0F, 40F, 36.0F);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try {
+            // 2:建立一个PDF 写入器与document对象关联通过书写器(Writer)可以将文档写入到磁盘中
+            PdfWriter pdfWriter = PdfWriter.getInstance(document, baos);
+            // 3:打开文档
+            document.open();
+            //生成pdf
+            this.generatePackagePDF(document, pdfWriter, pdfPackageDto);
+            // 5:关闭文档
+            document.close();
+        } catch (DocumentException e) {
+            e.printStackTrace();
+        }
+        if (saveLocal) {
+            PdfFillUtils.saveFile(baos, destFileName);
+        } else {
+            ConvertUtil.outputFile(response, baos, destFileName);
+        }
+    }
+
+    /**
+     * 生成签到表pdf文件
+     *
+     * @param document   document
+     * @param pdfWriter  pdfWriter
+     * @param pdfFillDto 签到表数据
+     */
+    private void generateSignPDF(Document document, PdfWriter pdfWriter, PdfSignDto pdfFillDto) throws DocumentException {
+        // 空格
+        Paragraph blank = new Paragraph(" ");
+        // 标题table
+        PdfPTable titleTable = PdfFillUtils.createTable(new float[]{33, 34, 33});
+        titleTable.addCell(PdfFillUtils.createCell("", null, null, 50f, Element.ALIGN_CENTER, 15, 3, 1));
+        titleTable.addCell(PdfFillUtils.createCell(pdfFillDto.getTitle(), PdfFillUtils.textFont18, null, 50f, Element.ALIGN_CENTER, 15, 3, 1));
+        // 条码
+        Image code128Image = PdfFillUtils.createBarcode(pdfWriter, pdfFillDto.getPackageNumber(), false, null, null);
+        code128Image.scalePercent(100);
+        titleTable.addCell(PdfFillUtils.createCell(code128Image, 50f, 15, 3));
+        document.add(titleTable);
+
+
+        // 基础信息表格
+        PdfPTable basicTable = PdfFillUtils.createTable(6);
+        List<Map<String, String>> basicPlate = pdfFillDto.getBasicPlate();
+        for (Map<String, String> stringMap : basicPlate) {
+            basicTable.addCell(PdfFillUtils.createCell(stringMap.get("name") + ":" + stringMap.get("value"), PdfFillUtils.textFont12, null, 16f, Element.ALIGN_LEFT, 0, 1, 3));
+        }
+        document.add(basicTable);
+
+        document.add(blank);
+
+        //表头
+        Map<String, String> studentHeadPlate = pdfFillDto.getStudentHeadPlate();
+        //计算表格宽度
+        float[] columnWidth = chooseColumnWidth(studentHeadPlate.size());
+        int columnCount = studentHeadPlate.size();
+
+        PdfPTable studentTable = PdfFillUtils.createTable(columnWidth);
+        String[] headKeys = new String[columnCount * 2];
+
+        for (int i = 0; i < 2; i++) {
+            int j = 0;
+            for (Map.Entry<String, String> entry : studentHeadPlate.entrySet()) {
+                headKeys[columnCount * i + j] = entry.getKey();
+                studentTable.addCell(PdfFillUtils.createCell(entry.getValue(), PdfFillUtils.textFont12, BaseColor.GRAY, 16f, Element.ALIGN_CENTER, 0, 1, 1));
+                j++;
+            }
+        }
+
+        //数据
+        List<Map<String, String>> studentPlate = pdfFillDto.getStudentPlate();
+        int studentPlateCount = studentPlate.size();
+        int forCount = studentPlateCount % 2 == 0 ? studentPlateCount / 2 : studentPlateCount / 2 + 1;
+
+        for (int i = 0; i < forCount; i++) {
+            Map<String, String> stringMap1 = studentPlate.get(2 * i);
+            for (int j = 0; j < stringMap1.size(); j++) {
+                String value = stringMap1.get(headKeys[j]);
+                studentTable.addCell(PdfFillUtils.createCell(value, chooseFont(value, columnWidth[j]), null, 0, Element.ALIGN_CENTER, 0, 1, 1));
+            }
+
+            if (studentPlateCount % 2 > 0 && 2 * i + 1 == studentPlate.size()) {
+                for (int i1 = 0; i1 < columnCount; i1++) {
+                    studentTable.addCell(PdfFillUtils.createCell("", PdfFillUtils.textFont12, null, 0, Element.ALIGN_CENTER, 0, 1, 1));
+                }
+                continue;
+            }
+            Map<String, String> stringMap2 = studentPlate.get(2 * i + 1);
+            for (int j = 0; j < stringMap2.size(); j++) {
+                String value = stringMap2.get(headKeys[j + columnCount]);
+                studentTable.addCell(PdfFillUtils.createCell(value, chooseFont(value, columnWidth[j + columnCount]), null, 0, Element.ALIGN_CENTER, 0, 1, 1));
+            }
+        }
+        document.add(studentTable);
+
+        document.add(blank);
+
+        Paragraph pDate = new Paragraph(" 年        月        日", PdfFillUtils.textFont12);
+        pDate.setAlignment(Element.ALIGN_RIGHT);
+        pDate.setIndentationRight(20);
+
+        PdfPTable signTable = new PdfPTable(4);
+        signTable.setWidthPercentage(100);// 表格宽度为100%
+        // 备注
+        PdfPCell cell34 = new PdfPCell();
+        cell34.setBorderWidth(0.5F);
+        cell34.setMinimumHeight(20);
+        cell34.setPhrase(new Paragraph("监考老师签名处", PdfFillUtils.textFont12));
+        cell34.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        cell34.setHorizontalAlignment(Element.ALIGN_CENTER);
+        signTable.addCell(cell34);
+        PdfPCell cell35 = new PdfPCell();
+        cell35.setBorderWidth(0.5F);
+        cell35.setColspan(3);
+        cell35.addElement(blank);
+        cell35.addElement(pDate);
+        cell35.addElement(blank);
+        signTable.addCell(cell35);
+
+        try {
+            document.add(signTable);
+        } catch (DocumentException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 卷袋贴生成方法
+     *
+     * @param document      document
+     * @param pdfWriter     pdfWriter
+     * @param pdfPackageDto 卷袋贴数据
+     */
+    private void generatePackagePDF(Document document, PdfWriter pdfWriter, PdfPackageDto pdfPackageDto) {
+        try {
+            // 空格
+            Paragraph blank = new Paragraph(" ");
+            // 标题table
+            PdfPTable titleTable = PdfFillUtils.createTable(new float[]{33, 34, 33});
+            titleTable.addCell(PdfFillUtils.createCell("", null, null, 50f, Element.ALIGN_CENTER, 15, 3, 1));
+            titleTable.addCell(PdfFillUtils.createCell(pdfPackageDto.getTitle(), PdfFillUtils.textFont28, null, 50f, Element.ALIGN_CENTER, 15, 3, 1));
+            // 条码
+            Image code128Image = PdfFillUtils.createBarcode(pdfWriter, pdfPackageDto.getPackageNumber(), false, null, null);
+            code128Image.scalePercent(100);
+            titleTable.addCell(PdfFillUtils.createCell(code128Image, 50f, 15, 3));
+            document.add(titleTable);
+
+            document.add(blank);
+
+            // 基础信息表格
+            PdfPTable basicTable = PdfFillUtils.createTable(1);
+            List<Map<String, String>> basicPlate = pdfPackageDto.getBasicPlate();
+            for (Map<String, String> stringMap : basicPlate) {
+                basicTable.addCell(PdfFillUtils.createCell(stringMap.get("name") + ":" + stringMap.get("value"), PdfFillUtils.textFont24, 50f, Element.ALIGN_LEFT, 20f));
+                document.add(blank);
+            }
+            document.add(basicTable);
+            document.add(blank);
+        } catch (DocumentException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 签到表考生签到table表头宽度选择
+     *
+     * @param size 表头字段数量
+     */
+    private float[] chooseColumnWidth(int size) {
+        float[] columnWidth;
+        if (size == 1) {
+            columnWidth = new float[]{50, 50};
+        } else if (size == 2) {
+            columnWidth = new float[]{20, 30, 20, 30};
+        } else if (size == 3) {
+            columnWidth = new float[]{10, 25, 25, 10, 25, 25};
+        } else if (size == 4) {
+            columnWidth = new float[]{6, 12, 16, 16, 6, 12, 16, 16};
+        } else if (size == 5) {
+            columnWidth = new float[]{6, 10, 11, 12, 11, 6, 10, 11, 12, 11};
+        } else if (size == 6) {
+            columnWidth = new float[]{6, 9, 9, 9, 9, 8, 6, 9, 9, 9, 9, 8};
+        } else {
+            throw ExceptionResultEnum.ERROR.exception("签到表最多只能显示6个信息");
+        }
+        return columnWidth;
+    }
+
+    /**
+     * 根据表格大小,选择字号
+     *
+     * @param value   值
+     * @param percent 宽度
+     */
+    private Font chooseFont(String value, float percent) {
+        if (value.length() < percent) {
+            return PdfFillUtils.textFont12;
+        } else if (value.length() >= percent && value.length() < 1.5 * percent) {
+            return PdfFillUtils.textFont10;
+        } else if (value.length() >= 1.5 * percent && value.length() < 2 * percent) {
+            return PdfFillUtils.textFont9;
+        }
+        return PdfFillUtils.textFont8;
+    }
+
+    /**
+     * 内部类
+     * 添加页眉、页脚
+     */
+    public static class MyHeaderFooter extends PdfPageEventHelper {
+        // 总页数
+        PdfTemplate totalPage;
+
+        // 打开文档时,创建一个总页数的模版
+        @Override
+        public void onOpenDocument(PdfWriter writer, Document document) {
+            PdfContentByte cb = writer.getDirectContent();
+            totalPage = cb.createTemplate(30, 16);
+        }
+
+        // 一页加载完成触发,写入页眉和页脚
+        @Override
+        public void onEndPage(PdfWriter writer, Document document) {
+            PdfPTable table = new PdfPTable(3);
+            try {
+                table.setTotalWidth(PageSize.A4.getWidth() - 80);
+                table.setWidths(new int[]{24, 24, 3});
+                table.setLockedWidth(true);
+                table.getDefaultCell().setFixedHeight(-10);
+                table.getDefaultCell().setBorder(Rectangle.BOTTOM);
+                table.getDefaultCell().setBorderWidth(0.5f);
+
+                table.addCell(new Paragraph("", PdfFillUtils.textFont8));// 可以直接使用addCell(str),不过不能指定字体,中文无法显示
+                table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
+                table.addCell(new Paragraph("第" + writer.getPageNumber() + "页   /", PdfFillUtils.textFont8));
+                // 总页数
+                PdfPCell cell = new PdfPCell(Image.getInstance(totalPage));
+                cell.setBorder(Rectangle.BOTTOM);
+                table.addCell(cell);
+                // 将页眉写到document中,位置可以指定,指定到下面就是页脚
+                // 页眉
+                table.writeSelectedRows(0, -1, 40, PageSize.A4.getHeight() - 20, writer.getDirectContent());
+                // 页脚
+//                table.writeSelectedRows(0, -1, 40, 40, writer.getDirectContent());
+            } catch (Exception de) {
+                throw new ExceptionConverter(de);
+            }
+        }
+
+        // 全部完成后,将总页数的pdf模版写到指定位置
+        @Override
+        public void onCloseDocument(PdfWriter writer, Document document) {
+            String text = "共" + (writer.getPageNumber()) + "页";
+            ColumnText.showTextAligned(totalPage, Element.ALIGN_LEFT, new Paragraph(text, PdfFillUtils.textFont8), 2, 6, 0);
+        }
+    }
+
+
+    /**
+     * 测试方法
+     *
+     * @param args
+     */
+    public static void main(String[] args) {
+        PdfSignDto pdfFillDto = new PdfSignDto();
+        pdfFillDto.setTitle("测试签到表");
+        pdfFillDto.setPackageNumber("200032324");
+
+        // 基础信息
+        List<Map<String, String>> basicPlate = new ArrayList<>();
+        Map<String, String> basicMap = new HashMap<>();
+        basicMap.put("code", "courseCode");
+        basicMap.put("name", "课程代码");
+        basicMap.put("value", "高等数学");
+        basicPlate.add(basicMap);
+
+        basicMap = new HashMap<>();
+        basicMap.put("code", "paperNumber");
+        basicMap.put("name", "试卷编号");
+        basicMap.put("value", "bh001");
+        basicPlate.add(basicMap);
+
+        basicMap = new HashMap<>();
+        basicMap.put("code", "examTime");
+        basicMap.put("name", "考试时间");
+        basicMap.put("value", "2022-09-10 9:00-12:00");
+        basicPlate.add(basicMap);
+
+        basicMap = new HashMap<>();
+        basicMap.put("code", "examRoom");
+        basicMap.put("name", "考试地点");
+        basicMap.put("value", "教学楼301");
+        basicPlate.add(basicMap);
+
+        basicMap = new HashMap<>();
+        basicMap.put("code", "examCount");
+        basicMap.put("name", "应考人数");
+        basicMap.put("value", "61");
+        basicPlate.add(basicMap);
+
+        basicMap = new HashMap<>();
+        basicMap.put("code", "actualExamCount");
+        basicMap.put("name", "实考人数");
+        basicMap.put("value", "");
+        basicPlate.add(basicMap);
+
+        pdfFillDto.setBasicPlate(basicPlate);
+
+        // 表头信息
+        Map<String, String> studentHeadPlateMap = new LinkedHashMap<>();
+        studentHeadPlateMap.put("seq", "序号");
+        studentHeadPlateMap.put("studentCode", "学号");
+        studentHeadPlateMap.put("studentName", "姓名");
+        studentHeadPlateMap.put("className", "班级");
+        studentHeadPlateMap.put("studentSign", "签名");
+        pdfFillDto.setStudentHeadPlate(studentHeadPlateMap);
+
+        // 考生信息
+        List<Map<String, String>> studentPlate = new ArrayList<>();
+        for (int i = 0; i < 61; i++) {
+            Map<String, String> studentMap = new HashMap<>();
+            String seq = String.valueOf(i + 1);
+            studentMap.put("seq", seq);
+            studentMap.put("studentCode", "20010" + String.format("%03d", i + 1));
+            if (i > 10 && i < 20) {
+                studentMap.put("studentName", "学生" + String.format("%06d", i + 1));
+            } else if (i > 34 && i < 50) {
+                studentMap.put("studentName", "学生" + String.format("%010d", i + 1));
+            } else {
+                studentMap.put("studentName", "学生" + seq);
+            }
+            studentMap.put("className", "班级1");
+            studentMap.put("studentSign", "");
+            studentPlate.add(studentMap);
+        }
+        pdfFillDto.setStudentPlate(studentPlate);
+
+        PdfPackageDto pdfPackageDto = new PdfPackageDto();
+        pdfPackageDto.setTitle("测试卷袋贴");
+        pdfPackageDto.setPackageNumber("20000213134");
+
+        // 基础信息
+        List<Map<String, String>> basicPlate1 = new ArrayList<>();
+        Map<String, String> basicMap1 = new HashMap<>();
+        basicMap1.put("code", "courseCode");
+        basicMap1.put("name", "课程代码");
+        basicMap1.put("value", "高等数学");
+        basicPlate1.add(basicMap1);
+
+        basicMap1 = new HashMap<>();
+        basicMap1.put("code", "paperNumber");
+        basicMap1.put("name", "试卷编号");
+        basicMap1.put("value", "bh001");
+        basicPlate1.add(basicMap1);
+
+        basicMap1 = new HashMap<>();
+        basicMap1.put("code", "examTime");
+        basicMap1.put("name", "考试时间");
+        basicMap1.put("value", "2022-09-10 9:00-12:00");
+        basicPlate1.add(basicMap1);
+
+        basicMap1 = new HashMap<>();
+        basicMap1.put("code", "examRoom");
+        basicMap1.put("name", "考试地点");
+        basicMap1.put("value", "教学楼301");
+        basicPlate1.add(basicMap1);
+
+        basicMap1 = new HashMap<>();
+        basicMap1.put("code", "examCount");
+        basicMap1.put("name", "应考人数");
+        basicMap1.put("value", "61");
+        basicPlate1.add(basicMap1);
+
+        pdfPackageDto.setBasicPlate(basicPlate1);
+
+        try {
+            CreatePrintPdfUtil createPrintPdfUtil = new CreatePrintPdfUtil();
+            createPrintPdfUtil.createSignPdf(null, pdfFillDto, "D:/sign.pdf", true);
+            createPrintPdfUtil.createPackagePdf(null, pdfPackageDto, "D:/package.pdf", true);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

+ 307 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/util/PdfFillUtils.java

@@ -0,0 +1,307 @@
+package com.qmth.distributed.print.business.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.itextpdf.awt.AsianFontMapper;
+import com.itextpdf.text.*;
+import com.itextpdf.text.pdf.*;
+import com.qmth.distributed.print.business.bean.dto.PdfPackageDto;
+import com.qmth.distributed.print.business.bean.dto.PdfSignDto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.util.List;
+import java.util.*;
+
+/**
+ * pdf模板内容填充
+ */
+public class PdfFillUtils {
+    private final static Logger log = LoggerFactory.getLogger(PdfFillUtils.class);
+
+    // 定义全局的字体静态变量
+    public static Font textFont28;
+    public static Font textFont24;
+    public static Font textFont18;
+    public static Font textFont12;
+    public static Font textFont11;
+    public static Font textFont10;
+    public static Font textFont9;
+    public static Font textFont8;
+
+    // 静态代码块
+    static {
+        try {
+            //解决中文不显示问题
+            BaseFont bfChinese = BaseFont.createFont(AsianFontMapper.ChineseSimplifiedFont, AsianFontMapper.ChineseSimplifiedEncoding_H, BaseFont.NOT_EMBEDDED);
+            textFont28 = new Font(bfChinese, 28);
+            textFont24 = new Font(bfChinese, 24);
+            textFont18 = new Font(bfChinese, 18);
+            textFont12 = new Font(bfChinese, 12);
+            textFont11 = new Font(bfChinese, 11);
+            textFont10 = new Font(bfChinese, 10);
+            textFont9 = new Font(bfChinese, 9);
+            textFont8 = new Font(bfChinese, 8);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void saveFile(ByteArrayOutputStream baos, String fileName) {
+        FileOutputStream fileOutputStream = null;
+        try {
+            fileOutputStream = new FileOutputStream(fileName);
+            fileOutputStream.write(baos.toByteArray());
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                fileOutputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 填充table
+     *
+     * @param value       cell内容
+     * @param font        字体
+     * @param cellColor   背景色
+     * @param fixedHeight 垂直对齐方式
+     */
+    public static PdfPCell createCell(String value, Font font, BaseColor cellColor, float fixedHeight, int horizontalAlignment, int disableBorderSide, int rowspan, int colspan) {
+        PdfPCell cell = new PdfPCell();
+        cell.setBorderWidth(0.1F);
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        cell.setHorizontalAlignment(horizontalAlignment);
+        cell.setUseAscender(true);
+        if (font != null) {
+            cell.setPhrase(new Phrase(value, font));
+        } else {
+            cell.setPhrase(new Phrase(value));
+        }
+        if (cellColor != null) {
+            cell.setBackgroundColor(cellColor);
+        }
+        if (fixedHeight > 0) {
+            cell.setFixedHeight(fixedHeight);
+        }
+        if (disableBorderSide > 0) {
+            cell.disableBorderSide(disableBorderSide);
+        }
+        if (rowspan > 0) {
+            cell.setRowspan(rowspan);
+        }
+        if (colspan > 0) {
+            cell.setColspan(colspan);
+        }
+        return cell;
+    }
+
+    /**
+     * 填充table
+     *
+     * @param value       cell内容
+     * @param font        字体
+     * @param fixedHeight 垂直对齐方式
+     */
+    public static PdfPCell createCell(String value, Font font, float fixedHeight, int horizontalAlignment, float paddingLeft) {
+        PdfPCell cell = new PdfPCell();
+        cell.setBorderWidth(0.1F);
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        cell.setHorizontalAlignment(horizontalAlignment);
+        cell.setUseAscender(true);
+        if (font != null) {
+            cell.setPhrase(new Phrase(value, font));
+        } else {
+            cell.setPhrase(new Phrase(value));
+        }
+        if (fixedHeight > 0) {
+            cell.setFixedHeight(fixedHeight);
+        }
+        cell.disableBorderSide(15);
+        if (paddingLeft > 0) {
+            cell.setPaddingLeft(paddingLeft);
+        }
+        return cell;
+    }
+
+    /**
+     * 填充table
+     *
+     * @param image       cell内容
+     * @param fixedHeight 垂直对齐方式
+     */
+    public static PdfPCell createCell(Image image, float fixedHeight, int disableBorderSide, int rowspan) {
+        PdfPCell cell = new PdfPCell(image);
+        cell.setBorderWidth(0.1F);
+        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
+        cell.setUseAscender(true);
+        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
+//        cell.setExtraParagraphSpace(10);
+        if (fixedHeight > 0) {
+            cell.setFixedHeight(fixedHeight);
+        }
+        if (disableBorderSide > 0) {
+            cell.disableBorderSide(disableBorderSide);
+        }
+        if (rowspan > 0) {
+            cell.setRowspan(rowspan);
+        }
+        return cell;
+    }
+
+    /**
+     * 创建指定列宽、列数的表格
+     *
+     * @param columns 单元格数量
+     */
+    public static PdfPTable createTable(int columns) {
+        PdfPTable table = new PdfPTable(columns);
+        try {
+            table.setWidthPercentage(100);// 表格宽度为100%
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return table;
+    }
+
+    /**
+     * 创建指定列宽、列数的表格
+     *
+     * @param widths 宽度
+     */
+    public static PdfPTable createTable(float[] widths) {
+        PdfPTable table = new PdfPTable(widths.length);
+        try {
+            table.setTotalWidth(widths);
+            table.setWidthPercentage(100);// 表格宽度为100%
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return table;
+    }
+
+    /**
+     * 创建条形码
+     *
+     * @param writer   writer
+     * @param barCode  条形码(数字)
+     * @param hideCode 是否隐藏条形码(数字)
+     */
+    public static Image createBarcode(PdfWriter writer, String barCode, Boolean hideCode, BaseColor barColor, BaseColor textColor) {
+        Barcode128 barcode128 = new Barcode128();
+        barcode128.setCode(barCode);//设置数字
+        barcode128.setCodeType(Barcode.CODE128);
+        //设置字体
+        if (hideCode) {
+            barcode128.setFont(null);
+        }
+        return barcode128.createImageWithBarcode(writer.getDirectContent(), barColor, textColor);
+    }
+
+
+    /**
+     * 卷袋贴临时数据
+     *
+     * @param data data
+     */
+    public static void packageTempData(HttpServletResponse response, String data, String fileName) {
+        PdfPackageDto pdfPackageDto = new PdfPackageDto();
+        pdfPackageDto.setTitle("测试卷袋贴");
+        pdfPackageDto.setPackageNumber("20000213134");
+
+        List<JSONObject> basicObjectList = JSON.parseArray(data, JSONObject.class);
+        // 基础信息
+        List<Map<String, String>> basicPlate = new ArrayList<>();
+        for (JSONObject object : basicObjectList) {
+            Map<String, String> basicMap = new HashMap<>();
+            basicMap.put("code", object.getString("code"));
+            basicMap.put("name", object.getString("name"));
+            basicMap.put("value", "XXXXXX");
+            basicPlate.add(basicMap);
+        }
+        pdfPackageDto.setBasicPlate(basicPlate);
+
+        try {
+            CreatePrintPdfUtil createPrintPdfUtil = new CreatePrintPdfUtil();
+            createPrintPdfUtil.createPackagePdf(response, pdfPackageDto, fileName, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 签到表预览数据
+     *
+     * @param response response
+     * @param data     数据内容
+     * @param fileName 文件名
+     */
+    public static void parseSignTempData(HttpServletResponse response, String data, String fileName) {
+        PdfSignDto pdfFillDto = new PdfSignDto();
+        pdfFillDto.setTitle("XXXXX签到表");
+        pdfFillDto.setPackageNumber("123456789");
+
+        JSONObject jsonObject = JSON.parseObject(data);
+        // 基础信息
+        List<Map<String, String>> basicPlate = new ArrayList<>();
+        String basicData = jsonObject.getString("basic");
+        List<JSONObject> basicObjectList = JSON.parseArray(basicData, JSONObject.class);
+        Map<String, String> basicMap;
+        for (JSONObject object : basicObjectList) {
+            basicMap = new HashMap<>();
+            basicMap.put("code", object.getString("code"));
+            basicMap.put("name", object.getString("name"));
+            basicMap.put("value", "XXXXXX");
+            basicPlate.add(basicMap);
+        }
+        basicMap = new HashMap<>();
+        basicMap.put("code", "actualExamCount");
+        basicMap.put("name", "实考人数");
+        basicMap.put("value", "");
+        basicPlate.add(basicMap);
+
+        pdfFillDto.setBasicPlate(basicPlate);
+
+        // 表头信息
+        String studentData = jsonObject.getString("table");
+        List<JSONObject> studentObjectList = JSON.parseArray(studentData, JSONObject.class);
+        Map<String, String> studentHeadPlateMap = new LinkedHashMap<>();
+        for (JSONObject object : studentObjectList) {
+            studentHeadPlateMap.put(object.getString("code"), object.getString("name"));
+            studentHeadPlateMap.put("studentCode", "学号");
+            studentHeadPlateMap.put("studentName", "姓名");
+            studentHeadPlateMap.put("className", "班级");
+        }
+        studentHeadPlateMap.put("studentSign", "签名");
+        pdfFillDto.setStudentHeadPlate(studentHeadPlateMap);
+
+
+        // 考生信息
+        List<Map<String, String>> studentPlate = new ArrayList<>();
+        for (int i = 0; i < 55; i++) {
+            Map<String, String> studentMap = new HashMap<>();
+            for (JSONObject object : studentObjectList) {
+                studentMap.put(object.getString("code"), "XXXXXX");
+            }
+            studentMap.put("studentSign", "");
+            studentPlate.add(studentMap);
+        }
+        pdfFillDto.setStudentPlate(studentPlate);
+        try {
+            CreatePrintPdfUtil createPrintPdfUtil = new CreatePrintPdfUtil();
+            createPrintPdfUtil.createSignPdf(response, pdfFillDto, fileName, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+}

+ 4 - 1
distributed-print-business/src/main/resources/mapper/ExamStudentMapper.xml

@@ -87,7 +87,10 @@
         edc.paper_pages_a3 as paperPageA3,
         edc.paper_number as paperNumber,
         es.clazz_id clazzId,
-        es.clazz_name clazzName
+        es.clazz_name clazzName,
+        es.college_name collegeName,
+        es.major_name majorName,
+        es.student_clazz_type studentClazzType
         from
         exam_student es
         left join exam_detail_course edc on

+ 10 - 0
distributed-print/src/main/java/com/qmth/distributed/print/api/BasicTemplateController.java

@@ -7,6 +7,7 @@ import com.qmth.distributed.print.business.bean.dto.TemplateDto;
 import com.qmth.distributed.print.business.entity.BasicTemplate;
 import com.qmth.distributed.print.business.service.BasicTemplateService;
 import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.enums.ClassifyEnum;
 import com.qmth.teachcloud.common.util.Result;
 import com.qmth.teachcloud.common.util.ResultUtil;
 import io.swagger.annotations.Api;
@@ -15,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 
@@ -112,5 +114,13 @@ public class BasicTemplateController {
         Object content = basicTemplateService.readContent(attachmentId);
         return ResultUtil.ok(content);
     }
+
+    @ApiOperation(value = "预览")
+    @RequestMapping(value = "/preview", method = RequestMethod.POST)
+    public void preview(HttpServletResponse response,
+                        @RequestBody String data) {
+        basicTemplateService.preview(response, data);
+    }
+
 }
 

+ 6 - 0
pom.xml

@@ -44,6 +44,7 @@
         <version-plugin.version>2.8.1</version-plugin.version>
         <netty-all.version>4.1.49.Final</netty-all.version>
         <itextpdf.version>5.5.13</itextpdf.version>
+        <itextasian.version>5.2.0</itextasian.version>
         <googleBar.version>3.4.0</googleBar.version>
         <freemarker.version>2.3.30</freemarker.version>
         <commons-text.version>1.9</commons-text.version>
@@ -278,6 +279,11 @@
                 <artifactId>itextpdf</artifactId>
                 <version>${itextpdf.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.itextpdf</groupId>
+                <artifactId>itext-asian</artifactId>
+                <version>${itextasian.version}</version>
+            </dependency>
             <dependency>
                 <groupId>com.google.zxing</groupId>
                 <artifactId>core</artifactId>

+ 2 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/contant/SystemConstant.java

@@ -90,6 +90,8 @@ public class SystemConstant {
     public static final String ZIP_PREFIX = ".zip";
     //    public static final String JPG_PREFIX = ".jpg";
     public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
+    public static final String DATE_PATTERN = "yyyy-MM-dd";
+    public static final String TIME_PATTERN = "HH:mm";
     public static final int PAGE_NUMBER = 0;
     public static final int PAGE_SIZE = 10000000;
     public static final int PAGE_SIZE_MIN = 10;

+ 17 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/util/ConvertUtil.java

@@ -19,6 +19,7 @@ import javax.imageio.ImageIO;
 import javax.servlet.http.HttpServletResponse;
 import java.awt.image.BufferedImage;
 import java.io.*;
+import java.net.URLEncoder;
 import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
@@ -361,6 +362,22 @@ public class ConvertUtil {
         }
     }
 
+    public static void outputFile(HttpServletResponse response, ByteArrayOutputStream baos, String fileName) throws Exception {
+        try {
+            String fName = URLEncoder.encode(fileName, "UTF-8");
+
+            response.reset();
+            response.setContentType("application/x-msdownload");
+            response.setHeader("Content-Disposition", "attachment; filename=" + fName);
+
+            OutputStream outStream = response.getOutputStream();
+            baos.writeTo(outStream);
+            outStream.close();
+        } catch (IOException e) {
+            throw new Exception("下载失败");
+        }
+    }
+
     public static List<File> pdfToImageFile(String sourcePath, String targetPath) throws Exception {
         PDDocument doc = null;
         ByteArrayOutputStream os = null;