package com.product.print.service; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.net.URLEncodeUtil; 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; import com.product.core.exception.BaseException; import com.product.core.service.support.AbstractBaseService; import com.product.file.service.FileManagerService; import com.product.file.util.PdfConcurrenceUtil; 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.util.BaseUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.*; import java.util.stream.Collectors; /** * @ClassName PrintRealizeService * @Description 打印实现 业务层 * @Author cheng * @Date 2021/12/1 9:50 */ @Service public class PrintRealizeService extends AbstractBaseService implements IPrintRealizeService { @Autowired FileManagerService fileManagerService; /** * 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; } //获取每个字段的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); } } } /** * 获取字段对应数据字典信息 * * @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; } /** * 打印传输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); } } /** * 获取打印配置 * * @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 { // 打印模板附件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(); 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) { //转换数据为复选框 dataConvertCheckedData(dataFse); //克隆一份values Map cloneValues = new HashMap(dataFse.getValues()); //获取子表数据 Map subDataMap = dataFse.getSubData(); ConfigureBuilder config = Configure.createDefault().builder(); if (!CollectionUtil.isEmpty(subDataMap)) { for (Map.Entry entry : subDataMap.entrySet()) { cloneValues.put(entry.getKey(), entry.getValue().getData().stream().map(item -> (Map) ((Map) item.getValues())).collect(Collectors.toList())); config.bind(entry.getKey(), new DynamicTableRenderPolicy(entry.getKey())); } } 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()); } } }