许鹏程
2023-08-04 a26fbe729817216bcf53b13945fe6300caa89997
src/main/java/com/product/print/service/PrintRealizeService.java
@@ -1,8 +1,17 @@
package com.product.print.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.product.common.lang.StringUtils;
import com.product.core.cache.DataPoolCacheImpl;
import com.product.core.config.Global;
import com.product.core.entity.DataTableEntity;
import com.product.core.entity.FieldSetEntity;
@@ -13,16 +22,16 @@
import com.product.print.config.CmnCode;
import com.product.print.config.CmnConst;
import com.product.print.service.ide.IPrintRealizeService;
import com.product.print.util.DynamicTableRenderPolicy;
import com.product.tool.flow.service.FlowDetailService;
import com.product.util.BaseUtil;
import com.product.util.SystemParamReplace;
import com.product.util.config.SystemParamSet;
import com.product.util.SystemParamReplace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
@@ -37,236 +46,255 @@
public class PrintRealizeService extends AbstractBaseService implements IPrintRealizeService {
    @Autowired
    FileManagerService fileManagerService;
/*
    public static void main(String[] args) {
        Map<String, Object> t = new HashMap<>();
        Integer a = 1;
        t.put("test", 1);
        t.put("test2", true);
        t.put("test3", 0.11);
        Map<String, String> cc = (Map<String, String>) (Map) t;
        System.out.println(cc);
    }
*/
/*
    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new HashMap<>();
        List<Map<String, String>> subMapList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String, String> subMap = new HashMap<>();
            subMap.put("a1", "品名——" + (i + 1));
            subMap.put("a2", "单位——" + (i + 1));
            subMap.put("a3", "数量——" + (i + 1));
            subMap.put("a4", "用途——" + (i + 1));
            subMapList.add(subMap);
        }
        map.put("BGYPLYB_SUB", subMapList);
        HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();//创建一个列表的规则
        Configure config = Configure.newBuilder().customPolicy("BGYPLYB_SUB", policy).customPolicy("test_table", policy).build();
        File targetFile = new File("C:\\Users\\cheng\\Desktop\\replaceWord.docx");
        File file = new File("C:\\Users\\cheng\\Desktop\\办公用品领用表.docx");
        if (targetFile.exists()) {
            targetFile.delete();
        }
        targetFile.createNewFile();
        try (FileOutputStream is = new FileOutputStream(targetFile);
        ) {
            XWPFTemplate render = XWPFTemplate.compile(file, config).render(map);
            render.write(is);
            render.close();
        }
    }
*/
    @Override
    public void printWord(FieldSetEntity fse, HttpServletResponse response) throws BaseException {
        // 打印配置uuid
        String print_uuid = fse.getString("~" + CmnConst.PRINT_TEMP + "~");
        //查询打印配置
        FieldSetEntity fieldSetEntity = getBaseDao().getFieldSetEntity(CmnConst.TABLE_PRINT_CONFIG, print_uuid, false);
        if (fieldSetEntity == null || StringUtils.isEmpty(fieldSetEntity.getString(CmnConst.PRINT_TEMPLATE))) {
            throw new BaseException(CmnCode.PRINT_CONFIG_NOT_EXIST.getValue(), CmnCode.PRINT_CONFIG_NOT_EXIST.getText());
        }
        // 打印模板附件uuid
        String template_uuid = fieldSetEntity.getString(CmnConst.PRINT_TEMPLATE);
        // 获取打印模板
        File file = getFile(template_uuid);
        // 加载参照 打印时使用显示值 而不是实际值
        getBaseDao().loadPromptData(fse);
        // 文件名前缀部分
        Object tempKey = UUID.randomUUID();
        // 替换后的word临时路径
        String localTempPathWord = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".docx";
        File wordTemp = new File(localTempPathWord);
        try {
            new File(Global.getSystemConfig("temp.dir", "")).mkdirs();
            wordTemp.createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(CmnCode.PRINT_CONTENT_FAIL.getValue(), CmnCode.PRINT_CONTENT_FAIL.getText() + (e.getMessage() != null ? e.getMessage() : ""));
        }
        //将模和当前fse的values放入进行替换
        try (FileOutputStream is = new FileOutputStream(wordTemp);
             OutputStream out = response.getOutputStream()) {
            Map<String, DataTableEntity> subData = fse.getSubData();
   @Autowired
   FileManagerService fileManagerService;
            Configure.ConfigureBuilder configureBuilder = null;
            if (subData != null && subData.size() > 0) {
                for (Map.Entry<String, DataTableEntity> vv :
                        subData.entrySet()) {
                    getBaseDao().loadPromptData(vv.getValue());
                    if (!DataTableEntity.isEmpty(vv.getValue())) {
                        List<Map> collect = vv.getValue().getData().stream().map(item -> (Map<String, String>) ((Map) item.getValues())).collect(Collectors.toList());
                        fse.setValue(vv.getKey(), collect);
                    } else {
                        fse.setValue(vv.getKey(), new ArrayList<>());
                    }
                    if (configureBuilder == null) {
                        configureBuilder = Configure.newBuilder();
                    }
                    configureBuilder.customPolicy(vv.getKey(), new HackLoopTableRenderPolicy());
                }
            }
            XWPFTemplate render = XWPFTemplate.compile(file, configureBuilder == null ? Configure.createDefault() : configureBuilder.build()).render(fse.getValues());
            render.write(is);
            render.close();
            response.setContentType("multipart/form-data");
            response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有
            //设置响应
            response.setContentType("application/octet-stream;charset=UTF-8");
            // 将响应头中的Content-Disposition暴露出来,不然前端获取不到
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            String fileName = null;
            if(!BaseUtil.strIsNull(fieldSetEntity.getString("print_file_name"))) {
               fileName = SystemParamReplace.replaceParams(fieldSetEntity.getString("print_file_name"), fse);
            }else {
               fileName = fieldSetEntity.getString("print_name");
   /**
    * word打印复选框处理
    *
    * @param fse
    */
   public static void dataConvertCheckedData(FieldSetEntity fse) {
      TextRenderData selSymbol = new TextRenderData(CmnConst.PRINT_CHECKED_CHAR, new Style(CmnConst.PRINT_FONT, 14));
      TextRenderData unselSymbol = new TextRenderData(CmnConst.PRINT_UNCHECKED_CHAR, new Style(CmnConst.PRINT_FONT, 14));
      //获取表单字段
      Object[] fields = fse.getMeta().getFields();
      if (fields == null) {
         return;
      }
      for (int i = 0; i < fields.length; ++i) {
         //获取保存的数据值
         String dataSaveValue = fse.getString(fields[i] + CmnConst._SAVE_VALUE);
         if (BaseUtil.strIsNull(dataSaveValue)) {
            continue;
         }
            fileName+=".docx";
            // 在响应头中的Content-Disposition里设置文件名称
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            InputStream isPdf = new FileInputStream(wordTemp);
            int len;
            byte[] b = new byte[1024];
            // 输出
            while ((len = isPdf.read(b)) > 0) {
                out.write(b, 0, len);
            }
            isPdf.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(CmnCode.PRINT_CONTENT_FAIL.getValue(), CmnCode.PRINT_CONTENT_FAIL.getText() + (e.getMessage() != null ? e.getMessage() : ""));
        } finally {
           //删除word临时文件
            if (wordTemp.exists()) {
               System.out.println(wordTemp.getPath());
//                wordTemp.delete();
            }
            if (file != null) {
                file.delete();
            }
        }
         //获取每个字段的meta信息
         FieldSetEntity meta = fse.getMeta().getFieldMeta(fields[i].toString());
         if (meta == null || meta.getString(CmnConst.FIELD_REFERECE) == null || meta.getString(CmnConst.FIELD_REFERECE).indexOf("《") == -1) {
            continue;
         }
         //数据对应参照信息
         DataTableEntity dictInfos = getMetaAndCacheDictInfo(meta);
         if (BaseUtil.dataTableIsEmpty(dictInfos)) {
            continue;
         }
         for (int j = 0; j < dictInfos.getRows(); j++) {
            //获取每个参照对应值
            String dict_value = dictInfos.getFieldSetEntity(j).getString(CmnConst.DICT_VALUE);
            if (dataSaveValue.indexOf(dict_value) > -1) {
               fse.setValue(fields[i] + "_" + dict_value, selSymbol);
               continue;
            }
            fse.setValue(fields[i] + "_" + dict_value, unselSymbol);
         }
      }
   }
    }
    @Override
    public void print(FieldSetEntity fse, HttpServletResponse response) throws BaseException {
        // 打印配置uuid
        String print_uuid = fse.getString("~" + CmnConst.PRINT_TEMP + "~");
        //查询打印配置
        FieldSetEntity fieldSetEntity = getBaseDao().getFieldSetEntity(CmnConst.TABLE_PRINT_CONFIG, print_uuid, false);
        if (fieldSetEntity == null || StringUtils.isEmpty(fieldSetEntity.getString(CmnConst.PRINT_TEMPLATE))) {
            throw new BaseException(CmnCode.PRINT_CONFIG_NOT_EXIST.getValue(), CmnCode.PRINT_CONFIG_NOT_EXIST.getText());
        }
        // 打印模板附件uuid
        String template_uuid = fieldSetEntity.getString(CmnConst.PRINT_TEMPLATE);
        // 获取打印模板
        File file = getFile(template_uuid);
        // 加载参照 打印时使用显示值 而不是实际值
        getBaseDao().loadPromptData(fse);
        // 文件名前缀部分
        Object tempKey = UUID.randomUUID();
        // 替换后的word临时路径
        String localTempPathWord = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".docx";
        // 转换pdf的临时路径
        String localTempPathPdf = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".pdf";
        File wordTemp = new File(localTempPathWord);
        File pdfTemp = null;
        try {
            new File(Global.getSystemConfig("temp.dir", "")).mkdirs();
            wordTemp.createNewFile();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(CmnCode.PRINT_CONTENT_FAIL.getValue(), CmnCode.PRINT_CONTENT_FAIL.getText() + (e.getMessage() != null ? e.getMessage() : ""));
        }
        //将模和当前fse的values放入进行替换
        try (FileOutputStream is = new FileOutputStream(wordTemp);
             OutputStream out = response.getOutputStream()) {
            Map<String, DataTableEntity> subData = fse.getSubData();
   /**
    * 获取字段对应数据字典信息
    *
    * @param fieldMate
    * @return
    */
   public static DataTableEntity getMetaAndCacheDictInfo(FieldSetEntity fieldMate) {
      if (fieldMate != null && fieldMate.getString(CmnConst.FIELD_REFERECE) != null) {
         int a = fieldMate.getString(CmnConst.FIELD_REFERECE).indexOf("《");
         int b = fieldMate.getString(CmnConst.FIELD_REFERECE).indexOf("》");
         if (b > 1 && a == 0) {
            return DataPoolCacheImpl.getInstance().getCacheData("数据字典配置信息", new String[]{fieldMate.getString(CmnConst.FIELD_REFERECE).substring(a + 1, b)});
         }
      }
      return null;
   }
            Configure.ConfigureBuilder configureBuilder = null;
            if (subData != null && subData.size() > 0) {
                for (Map.Entry<String, DataTableEntity> vv :
                        subData.entrySet()) {
                    getBaseDao().loadPromptData(vv.getValue());
                    if (!DataTableEntity.isEmpty(vv.getValue())) {
                        List<Map> collect = vv.getValue().getData().stream().map(item -> (Map<String, String>) ((Map) item.getValues())).collect(Collectors.toList());
                        fse.setValue(vv.getKey(), collect);
                    } else {
                        fse.setValue(vv.getKey(), new ArrayList<>());
                    }
                    if (configureBuilder == null) {
                        configureBuilder = Configure.newBuilder();
                    }
                    configureBuilder.customPolicy(vv.getKey(), new HackLoopTableRenderPolicy());
                }
            }
            XWPFTemplate render = XWPFTemplate.compile(file, configureBuilder == null ? Configure.createDefault() : configureBuilder.build()).render(fse.getValues());
            render.write(is);
            render.close();
            response.setContentType("multipart/form-data");
            response.setHeader("Content-Disposition", "attachment;");
            // 使用openOffice 转换为pdf
            pdfTemp = PdfConcurrenceUtil.convertToPdf(wordTemp.getPath(), localTempPathPdf);
            InputStream isPdf = new FileInputStream(pdfTemp);
            int len;
            byte[] b = new byte[1024];
            // 输出
            while ((len = isPdf.read(b)) > 0) {
                out.write(b, 0, len);
            }
            isPdf.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseException(CmnCode.PRINT_CONTENT_FAIL.getValue(), CmnCode.PRINT_CONTENT_FAIL.getText() + (e.getMessage() != null ? e.getMessage() : ""));
        } finally {
            // 删除临时文件
            if (pdfTemp != null && pdfTemp.exists()) {
                pdfTemp.delete();
            }
            if (wordTemp.exists()) {
                wordTemp.delete();
            }
            if (file != null) {
                file.delete();
            }
        }
   /**
    * 打印传输pdf流到前端
    *
    * @param fse          打印数据
    * @param response     响应
    * @param isConvertPdf 是否转换为pdf
    * @throws BaseException
    */
   @Override
   public void print(FieldSetEntity fse, HttpServletResponse response, boolean isConvertPdf) throws BaseException {
      //打印配置
      FieldSetEntity printConfig = getPrintConfig(fse.getString("~" + CmnConst.PRINT_TEMP + "~"));
      //获取到替换后的文件路径 (pdf文件或者word文件)
      String tempPdfFilePath = replaceTemplateFileOut(printConfig, fse, isConvertPdf);
      //获取文件名
      String fileName = BaseUtil.ifNull(printConfig.getString(CmnConst.PRINT_FILE_NAME), printConfig.getString(CmnConst.PRINT_NAME));
      if (isConvertPdf) {
         fileName = fileName + ".pdf";
      } else {
         fileName = fileName + ".docx";
      }
      //设置响应
      response.setContentType("application/octet-stream;charset=UTF-8");
      // 将响应头中的Content-Disposition暴露出来,不然前端获取不到
      response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
      // 设置自定义头Content-Disposition
      response.setHeader("Content-Disposition", "attachment;filename=" + URLEncodeUtil.encode(fileName));
    }
      try (
            OutputStream out = response.getOutputStream();
      ) {
         FileUtil.writeToStream(new File(tempPdfFilePath), out);
      } catch (Exception e) {
         e.printStackTrace();
         throw new BaseException(CmnCode.PRINT_CONTENT_FAIL, e);
      } finally {
         //删除pdf临时文件
         FileUtil.del(tempPdfFilePath);
      }
    private File getFile(String template_uuid) throws BaseException {
        try {
            return fileManagerService.getFile(template_uuid);
        } catch (BaseException e) {
            e.printStackTrace();
            //获取打印模板错误
            throw new BaseException(CmnCode.GET_PRINT_TEMPLATE_FILE_FAIL.getValue(), CmnCode.GET_PRINT_TEMPLATE_FILE_FAIL.getText());
        }
    }
   }
   /**
    * 获取打印配置
    *
    * @param uuid 打印配置uuid
    * @return
    * @throws BaseException
    */
   public FieldSetEntity getPrintConfig(String uuid) throws BaseException {
      //查询打印配置
      FieldSetEntity fieldSetEntity = getBaseDao().getFieldSetEntity(CmnConst.TABLE_PRINT_CONFIG, uuid, false);
      if (fieldSetEntity == null || StringUtils.isEmpty(fieldSetEntity.getString(CmnConst.PRINT_TEMPLATE))) {
         throw new BaseException(CmnCode.PRINT_CONFIG_NOT_EXIST.getValue(), CmnCode.PRINT_CONFIG_NOT_EXIST.getText());
      }
      return fieldSetEntity;
   }
   /**
    * 替换模板文件并输出
    *
    * @param printConf    打印配置
    * @param fse          替换数据
    * @param isConvertPdf 是否转换为pdf
    * @return 替换后的文件路径
    * @throws BaseException 异常
    */
   private String replaceTemplateFileOut(FieldSetEntity printConf, FieldSetEntity fse, boolean isConvertPdf) throws BaseException {
      Object[] fields = fse.getFields();
      for (int i = 0; i < fields.length; i++) {
         String field = fields[i].toString();
         FieldSetEntity metaEntity = fse.getMeta().getFieldMeta(field);
         String fieldType = metaEntity.getString("field_type");
         //判断是否拥有流程标识
         if ("flowsign".equals(fieldType)) {
            if (StringUtils.equalsAny(fse.getString(field), "1", "2")) {
               //流程办理中或办结 获取流程意见
               FieldSetEntity flowTask = getBaseDao().getFieldSetByFilter("product_sys_flow_task", "table_name=? and record_uuid=?", new Object[]{fse.getTableName(), fse.getUUID()}, false);
               if (flowTask != null) {
                  String taskUuid = flowTask.getString(CmnConst.UUID);
                  //获取流程意见
                  FlowDetailService flowDetailService = SpringUtil.getBean(FlowDetailService.class);
                  JSONArray opinion = flowDetailService.getHistoryInfo(taskUuid);
                  fse.setValue("~flow_opinion~", opinion);
               }
            }
            break;
         }
      }
      // 打印模板附件uuid
      String template_uuid = printConf.getString(CmnConst.PRINT_TEMPLATE);
      // 获取打印模板
      File file = getTemplateFile(template_uuid);
      // 加载参照 打印时使用显示值 而不是实际值
      getBaseDao().loadPromptData(fse);
      // 文件名前缀部分
      Object tempKey = UUID.randomUUID();
      // 替换后的word临时路径
      String localTempPathWord = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".docx";
      replaceWord(localTempPathWord, file.getPath(), fse);
      file.delete();
      String replaceParams = SystemParamReplace.replaceParams(printConf.getString(CmnConst.PRINT_FILE_NAME), fse);
      printConf.setValue(CmnConst.PRINT_FILE_NAME, replaceParams);
      if (isConvertPdf) {
         try {
            // 替换后的pdf临时路径
            String localTempPathPdf = Global.getSystemConfig("temp.dir", "") + File.separator + "temp_print_" + tempKey + ".pdf";
            //检查文件是否存在不存则创建
            FileUtil.touch(localTempPathPdf);
            // 转换pdf
            PdfConcurrenceUtil.convertToPdf(localTempPathWord, localTempPathPdf, "docx");
            // 删除word临时文件
            File wordTemp = new File(localTempPathWord);
            if (wordTemp.exists()) {
               wordTemp.delete();
            }
            return localTempPathPdf;
         } catch (Exception e) {
            throw new BaseException(CmnCode.CONVERT_PDF_ERROR, e);
         } finally {
            FileUtil.del(localTempPathWord);
         }
      }
      return localTempPathWord;
   }
   /**
    * 替换word模板
    *
    * @param outPath      输出路径
    * @param templatePath 模板路径
    * @param dataFse      替换数据
    */
   public static void replaceWord(String outPath, String templatePath, FieldSetEntity dataFse) {
      JSONArray flowOpinion = (JSONArray) dataFse.getObject("~flow_opinion~");
      if (flowOpinion != null) {
         dataFse.remove("~flow_opinion~");
      }
      //转换数据为复选框
      dataConvertCheckedData(dataFse);
      //克隆一份values
      Map<String, Object> cloneValues = new HashMap(dataFse.getValues());
      //获取子表数据
      Map<String, DataTableEntity> subDataMap = dataFse.getSubData();
      ConfigureBuilder config = Configure.createDefault().builder();
      if (!CollectionUtil.isEmpty(subDataMap)) {
         for (Map.Entry<String, DataTableEntity> entry : subDataMap.entrySet()) {
            cloneValues.put(entry.getKey(), entry.getValue().getData().stream().map(item -> (Map<String, Object>) ((Map) item.getValues())).collect(Collectors.toList()));
            config.bind(entry.getKey(), new DynamicTableRenderPolicy(entry.getKey()));
         }
      }
      if(flowOpinion!=null && flowOpinion.size()>0){
         cloneValues.put("lx_flow_opinion", flowOpinion);
         config.bind("lx_flow_opinion", new DynamicTableRenderPolicy("lx_flow_opinion"));
      }
      try {
         //检查输出文件是否存在,不存在则创建
         FileUtil.touch(outPath);
         System.out.println(cloneValues);
         XWPFTemplate.compile(templatePath, config.build()).render(cloneValues).writeToFile(outPath);
      } catch (Exception e) {
         e.printStackTrace();
         FileUtil.del(outPath);
         throw new BaseException(CmnCode.REPLACE_TEMPLATE_CONTENT_ERROR, e);
      }
   }
   /**
    * 获取模板附件
    *
    * @param templateUid 模板附件uuid
    * @return
    * @throws BaseException
    */
   private File getTemplateFile(String templateUid) throws BaseException {
      try {
         return fileManagerService.getFile(templateUid);
      } catch (BaseException e) {
         e.printStackTrace();
         //获取打印模板错误
         throw new BaseException(CmnCode.GET_PRINT_TEMPLATE_FILE_FAIL.getValue(), CmnCode.GET_PRINT_TEMPLATE_FILE_FAIL.getText());
      }
   }
}