diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java index 319a11a..535145d 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java @@ -2,7 +2,6 @@ import com.casic.missiles.dto.certificate.CropPicture; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -14,18 +13,17 @@ public class ImageTool { - public static List crosswiseCutting(CropPicture cropPicture) throws IOException { + public static List doCrosswiseCutting(CropPicture cropPicture) throws IOException { // 读入大图 File file = new File(cropPicture.getTargetImgUrl()); FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); +// System.out.println(file.exists()); BufferedImage image = ImageIO.read(fis); int chunks = cropPicture.getCutRows() * cropPicture.getCutCols(); - ImageReader imageReader=ImageIO.getImageReadersBySuffix(cropPicture.getTargetImgUrl()).next(); // 计算每个小图的宽度和高度 int chunkWidth = image.getWidth() / cropPicture.getCutCols(); int chunkHeight = image.getHeight() / cropPicture.getCutRows(); - System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 +// System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 BufferedImage imgs[] = new BufferedImage[chunks]; for (int x = 0,count = 0; x < cropPicture.getCutRows(); x++) { for (int y = 0; y < cropPicture.getCutCols(); y++) { @@ -34,14 +32,14 @@ //写入图像内容 Graphics2D gr = imgs[count++].createGraphics(); gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); - System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); +// System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); gr.dispose(); } } List subfileUrls = new ArrayList<>(); // 输出小图 for (int i = 0; i < imgs.length; i++) { - subfileUrls.add(cropPicture.getSubfileUrl() + i + cropPicture.getSubfileType()); + subfileUrls.add(cropPicture.getSubfileUrl() + i +"."+cropPicture.getSubfileType()); ImageIO.write(imgs[i], cropPicture.getSubfileType(), new File(subfileUrls.get(subfileUrls.size() - 1))); System.out.println(i); } @@ -49,29 +47,5 @@ return subfileUrls; } - public static void main(String[] agrs) throws IOException { - String originalImg = "D:\\casic\\tmp\\1645701777117741057\\ceshi.jpg"; - // 读入大图 - File file = new File(originalImg); - FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); - BufferedImage image = ImageIO.read(fis); - /* - * 假设我需要切割的四点坐标为a(20,30)b(200,40)c(30,200)d(200,210) - * 起始坐标为(最小的x,最小的y) - * 此时的实际切割坐标应为由a为起始坐标,width为(x坐标最大的点的x - a的x坐标),height为(y坐标最大的点的y - a的y坐标) - * 此时的width为180,height为180 - */ - //切割图片 - BufferedImage bf = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); - Graphics2D graphics2D = bf.createGraphics(); - graphics2D.drawImage(image, 20, 30, 180, 180, 0, 0, 180, 180, null); - graphics2D.dispose(); - //输出图片 - Random random = new Random(); - int j = random.nextInt(1000); - ImageIO.write(bf, "jpg", new File("D:\\casic\\tmp\\1645701777117741057" + j + ".jpg")); - System.out.println("完成切割"); - } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java index 319a11a..535145d 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java @@ -2,7 +2,6 @@ import com.casic.missiles.dto.certificate.CropPicture; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -14,18 +13,17 @@ public class ImageTool { - public static List crosswiseCutting(CropPicture cropPicture) throws IOException { + public static List doCrosswiseCutting(CropPicture cropPicture) throws IOException { // 读入大图 File file = new File(cropPicture.getTargetImgUrl()); FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); +// System.out.println(file.exists()); BufferedImage image = ImageIO.read(fis); int chunks = cropPicture.getCutRows() * cropPicture.getCutCols(); - ImageReader imageReader=ImageIO.getImageReadersBySuffix(cropPicture.getTargetImgUrl()).next(); // 计算每个小图的宽度和高度 int chunkWidth = image.getWidth() / cropPicture.getCutCols(); int chunkHeight = image.getHeight() / cropPicture.getCutRows(); - System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 +// System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 BufferedImage imgs[] = new BufferedImage[chunks]; for (int x = 0,count = 0; x < cropPicture.getCutRows(); x++) { for (int y = 0; y < cropPicture.getCutCols(); y++) { @@ -34,14 +32,14 @@ //写入图像内容 Graphics2D gr = imgs[count++].createGraphics(); gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); - System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); +// System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); gr.dispose(); } } List subfileUrls = new ArrayList<>(); // 输出小图 for (int i = 0; i < imgs.length; i++) { - subfileUrls.add(cropPicture.getSubfileUrl() + i + cropPicture.getSubfileType()); + subfileUrls.add(cropPicture.getSubfileUrl() + i +"."+cropPicture.getSubfileType()); ImageIO.write(imgs[i], cropPicture.getSubfileType(), new File(subfileUrls.get(subfileUrls.size() - 1))); System.out.println(i); } @@ -49,29 +47,5 @@ return subfileUrls; } - public static void main(String[] agrs) throws IOException { - String originalImg = "D:\\casic\\tmp\\1645701777117741057\\ceshi.jpg"; - // 读入大图 - File file = new File(originalImg); - FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); - BufferedImage image = ImageIO.read(fis); - /* - * 假设我需要切割的四点坐标为a(20,30)b(200,40)c(30,200)d(200,210) - * 起始坐标为(最小的x,最小的y) - * 此时的实际切割坐标应为由a为起始坐标,width为(x坐标最大的点的x - a的x坐标),height为(y坐标最大的点的y - a的y坐标) - * 此时的width为180,height为180 - */ - //切割图片 - BufferedImage bf = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); - Graphics2D graphics2D = bf.createGraphics(); - graphics2D.drawImage(image, 20, 30, 180, 180, 0, 0, 180, 180, null); - graphics2D.dispose(); - //输出图片 - Random random = new Random(); - int j = random.nextInt(1000); - ImageIO.write(bf, "jpg", new File("D:\\casic\\tmp\\1645701777117741057" + j + ".jpg")); - System.out.println("完成切割"); - } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java index d63c5ae..04c3b87 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java @@ -1,21 +1,16 @@ package com.casic.missiles.service.listeners.register.data; -import cn.hutool.core.lang.Assert; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.dto.certificate.ElectronicImage; import com.casic.missiles.dto.certificate.FilePrintRegister; import com.casic.missiles.dto.flowable.ApprovalLogResponse; -import com.casic.missiles.enums.BusinessExceptionEnum; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.enums.system.FilePrintEnum; -import com.casic.missiles.exception.BusinessException; import com.casic.missiles.mapper.file.PrintFileRegisterMapper; -import com.casic.missiles.service.IBaseApprovalService; import com.casic.missiles.utils.SpringContextUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @@ -28,17 +23,19 @@ /** * 有关键字的非工作流人员章 * - * @param extendImageMapList + * @param extendImageList * @return */ - private static List electronicKeySignSeals(List extendImageMapList, Map metaDataMap, FilePrintRegister filePrintRegister) { + private static List electronicKeySignSeals(List extendImageList, Map metaDataMap, FilePrintRegister filePrintRegister) { List electronicImageSeals = new ArrayList<>(); - for (Map extendImageMap : extendImageMapList) { - ElectronicImage electronicImage = defaultElectronicImage((String) extendImageMap.get(DOC_NAME)); - if (metaDataMap.containsKey((String) extendImageMap.get(FILED_NAME)) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageMap.get(FILED_NAME)))) { - electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + for (ImageConfig extendImageConfig : extendImageList) { + ElectronicImage electronicImage = defaultElectronicImage(extendImageConfig.getDocName()); + if (metaDataMap.containsKey(extendImageConfig.getFiledName()) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageConfig.getFiledName()))) { + electronicImage.setImageConfig(extendImageConfig); + electronicImage.setIsSealImage(true); + electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageConfig.getFiledName())); //放入待下载的文件集合 - filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageConfig.getFiledName())); electronicImageSeals.add(electronicImage); } } @@ -80,50 +77,6 @@ return electronicImage; } - public static void approvalImage(Map metaDataMap, JSONObject imageMap, List imageMapList, FilePrintRegister filePrintRegister) { - - if (StringUtils.isNotEmpty(imageMap.get(APPROVAL_FIELD).toString())) { - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString()), - () -> { - throw new BusinessException(BusinessExceptionEnum.APPROVAL_FIELD_ERROR); - }); - IBaseApprovalService approvalOperateService = SpringContextUtil.getBean(IBaseApprovalService.class); - - if (!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString())) { - Iterator> it = metaDataMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue() instanceof List) { - List innerMetaDataList = (List) entry.getValue(); - if (ObjectUtils.isNotEmpty(innerMetaDataList)) { - for (Object innerMetaDataObject : innerMetaDataList) { - List> approvalLogList = null; - Field[] fields = innerMetaDataObject.getClass().getDeclaredFields(); - for (Field field : fields) { - if (!field.isAccessible()) { - field.setAccessible(true); - } - try { - if (imageMap.get(APPROVAL_FIELD).equals(field.getName()) && field.get(innerMetaDataObject) != null) { - approvalLogList = approvalOperateService.approvalLog(field.get(innerMetaDataObject).toString()); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } catch (Exception ie) { - throw new BusinessException(500, "字段映射异常"); - } - } - } - } - } - } - } else { - //获取 - List> approvalLogList = approvalOperateService.approvalLog((String) metaDataMap.get(imageMap.get(APPROVAL_FIELD).toString())); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } - } /** * 构建带有关键字的工作流签名图片方法 @@ -148,15 +101,14 @@ /** * 构建带有关键字的图片方法 */ - public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageMapList, Map metaDataMap) { + public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageConfigList, Map metaDataMap) { //处理文中的章 - List extendImageMapList = imageMapList.stream() - .filter(imageMap -> "0".equals(imageMap.get(APPROVAL_FLAG))) + List extendImageList = imageConfigList.stream() + .filter(imageMap -> StringUtils.isEmpty(imageMap.getApprovalFlag()) || "0".equals(imageMap.getApprovalFlag())) .collect(Collectors.toList()); - filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageMapList, metaDataMap, filePrintRegister)); + filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageList, metaDataMap, filePrintRegister)); } - /** * 电子签名创建器 */ diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java index 319a11a..535145d 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java @@ -2,7 +2,6 @@ import com.casic.missiles.dto.certificate.CropPicture; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -14,18 +13,17 @@ public class ImageTool { - public static List crosswiseCutting(CropPicture cropPicture) throws IOException { + public static List doCrosswiseCutting(CropPicture cropPicture) throws IOException { // 读入大图 File file = new File(cropPicture.getTargetImgUrl()); FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); +// System.out.println(file.exists()); BufferedImage image = ImageIO.read(fis); int chunks = cropPicture.getCutRows() * cropPicture.getCutCols(); - ImageReader imageReader=ImageIO.getImageReadersBySuffix(cropPicture.getTargetImgUrl()).next(); // 计算每个小图的宽度和高度 int chunkWidth = image.getWidth() / cropPicture.getCutCols(); int chunkHeight = image.getHeight() / cropPicture.getCutRows(); - System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 +// System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 BufferedImage imgs[] = new BufferedImage[chunks]; for (int x = 0,count = 0; x < cropPicture.getCutRows(); x++) { for (int y = 0; y < cropPicture.getCutCols(); y++) { @@ -34,14 +32,14 @@ //写入图像内容 Graphics2D gr = imgs[count++].createGraphics(); gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); - System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); +// System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); gr.dispose(); } } List subfileUrls = new ArrayList<>(); // 输出小图 for (int i = 0; i < imgs.length; i++) { - subfileUrls.add(cropPicture.getSubfileUrl() + i + cropPicture.getSubfileType()); + subfileUrls.add(cropPicture.getSubfileUrl() + i +"."+cropPicture.getSubfileType()); ImageIO.write(imgs[i], cropPicture.getSubfileType(), new File(subfileUrls.get(subfileUrls.size() - 1))); System.out.println(i); } @@ -49,29 +47,5 @@ return subfileUrls; } - public static void main(String[] agrs) throws IOException { - String originalImg = "D:\\casic\\tmp\\1645701777117741057\\ceshi.jpg"; - // 读入大图 - File file = new File(originalImg); - FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); - BufferedImage image = ImageIO.read(fis); - /* - * 假设我需要切割的四点坐标为a(20,30)b(200,40)c(30,200)d(200,210) - * 起始坐标为(最小的x,最小的y) - * 此时的实际切割坐标应为由a为起始坐标,width为(x坐标最大的点的x - a的x坐标),height为(y坐标最大的点的y - a的y坐标) - * 此时的width为180,height为180 - */ - //切割图片 - BufferedImage bf = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); - Graphics2D graphics2D = bf.createGraphics(); - graphics2D.drawImage(image, 20, 30, 180, 180, 0, 0, 180, 180, null); - graphics2D.dispose(); - //输出图片 - Random random = new Random(); - int j = random.nextInt(1000); - ImageIO.write(bf, "jpg", new File("D:\\casic\\tmp\\1645701777117741057" + j + ".jpg")); - System.out.println("完成切割"); - } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java index d63c5ae..04c3b87 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java @@ -1,21 +1,16 @@ package com.casic.missiles.service.listeners.register.data; -import cn.hutool.core.lang.Assert; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.dto.certificate.ElectronicImage; import com.casic.missiles.dto.certificate.FilePrintRegister; import com.casic.missiles.dto.flowable.ApprovalLogResponse; -import com.casic.missiles.enums.BusinessExceptionEnum; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.enums.system.FilePrintEnum; -import com.casic.missiles.exception.BusinessException; import com.casic.missiles.mapper.file.PrintFileRegisterMapper; -import com.casic.missiles.service.IBaseApprovalService; import com.casic.missiles.utils.SpringContextUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @@ -28,17 +23,19 @@ /** * 有关键字的非工作流人员章 * - * @param extendImageMapList + * @param extendImageList * @return */ - private static List electronicKeySignSeals(List extendImageMapList, Map metaDataMap, FilePrintRegister filePrintRegister) { + private static List electronicKeySignSeals(List extendImageList, Map metaDataMap, FilePrintRegister filePrintRegister) { List electronicImageSeals = new ArrayList<>(); - for (Map extendImageMap : extendImageMapList) { - ElectronicImage electronicImage = defaultElectronicImage((String) extendImageMap.get(DOC_NAME)); - if (metaDataMap.containsKey((String) extendImageMap.get(FILED_NAME)) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageMap.get(FILED_NAME)))) { - electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + for (ImageConfig extendImageConfig : extendImageList) { + ElectronicImage electronicImage = defaultElectronicImage(extendImageConfig.getDocName()); + if (metaDataMap.containsKey(extendImageConfig.getFiledName()) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageConfig.getFiledName()))) { + electronicImage.setImageConfig(extendImageConfig); + electronicImage.setIsSealImage(true); + electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageConfig.getFiledName())); //放入待下载的文件集合 - filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageConfig.getFiledName())); electronicImageSeals.add(electronicImage); } } @@ -80,50 +77,6 @@ return electronicImage; } - public static void approvalImage(Map metaDataMap, JSONObject imageMap, List imageMapList, FilePrintRegister filePrintRegister) { - - if (StringUtils.isNotEmpty(imageMap.get(APPROVAL_FIELD).toString())) { - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString()), - () -> { - throw new BusinessException(BusinessExceptionEnum.APPROVAL_FIELD_ERROR); - }); - IBaseApprovalService approvalOperateService = SpringContextUtil.getBean(IBaseApprovalService.class); - - if (!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString())) { - Iterator> it = metaDataMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue() instanceof List) { - List innerMetaDataList = (List) entry.getValue(); - if (ObjectUtils.isNotEmpty(innerMetaDataList)) { - for (Object innerMetaDataObject : innerMetaDataList) { - List> approvalLogList = null; - Field[] fields = innerMetaDataObject.getClass().getDeclaredFields(); - for (Field field : fields) { - if (!field.isAccessible()) { - field.setAccessible(true); - } - try { - if (imageMap.get(APPROVAL_FIELD).equals(field.getName()) && field.get(innerMetaDataObject) != null) { - approvalLogList = approvalOperateService.approvalLog(field.get(innerMetaDataObject).toString()); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } catch (Exception ie) { - throw new BusinessException(500, "字段映射异常"); - } - } - } - } - } - } - } else { - //获取 - List> approvalLogList = approvalOperateService.approvalLog((String) metaDataMap.get(imageMap.get(APPROVAL_FIELD).toString())); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } - } /** * 构建带有关键字的工作流签名图片方法 @@ -148,15 +101,14 @@ /** * 构建带有关键字的图片方法 */ - public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageMapList, Map metaDataMap) { + public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageConfigList, Map metaDataMap) { //处理文中的章 - List extendImageMapList = imageMapList.stream() - .filter(imageMap -> "0".equals(imageMap.get(APPROVAL_FLAG))) + List extendImageList = imageConfigList.stream() + .filter(imageMap -> StringUtils.isEmpty(imageMap.getApprovalFlag()) || "0".equals(imageMap.getApprovalFlag())) .collect(Collectors.toList()); - filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageMapList, metaDataMap, filePrintRegister)); + filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageList, metaDataMap, filePrintRegister)); } - /** * 电子签名创建器 */ diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java index fbbca76..dc4a642 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java @@ -1,13 +1,14 @@ package com.casic.missiles.service.listeners.register.data; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.dto.certificate.FilePrintRegister; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.dto.system.FieldTableDTO; import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.system.FilePrintEnum; @@ -45,21 +46,13 @@ * 3、设置文件id,作为操作空间文件名称,防止对其他同时处理的证书形成影响 */ protected final FilePrintRegister initialization(String templateFileDir, - Long id, ModuleTemplatePrintConfig moduleTemplatePrintConfig) { + Long id, + ModuleTemplatePrintConfig moduleTemplatePrintConfig) { FilePrintRegister filePrintRegister = new FilePrintRegister(); templateFileDir = templateFileDir + id + File.separator; - - PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); - //查询模板id,获取模板的minFileName - String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); - filePrintRegister.setFileName(templateName); - filePrintRegister.setTemDir(templateFileDir); - filePrintRegister.setTemplatePath(templateFileDir + templateName); + //处理待填充模板 + templateFile(moduleTemplatePrintConfig, templateFileDir, filePrintRegister); filePrintRegister.setFileNameId(id); - //添加模板到待下载列表 - List fileNames = new ArrayList<>(); - fileNames.add(templateName); - filePrintRegister.setBeDownloadedFileNames(fileNames); //这里需要添加电子签章 ElectronicSignSeal.electronicNoKeySignSeals(moduleTemplatePrintConfig.getSigns(), filePrintRegister); //添加默认的参数 @@ -68,6 +61,27 @@ } /** + * 处理模板文件 + * + * @param moduleTemplatePrintConfig + * @param templateFileDir + * @param filePrintRegister + */ + private void templateFile(ModuleTemplatePrintConfig moduleTemplatePrintConfig, String templateFileDir, FilePrintRegister filePrintRegister) { + PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); + //设置目录、路径 + filePrintRegister.setTemDir(templateFileDir); + //查询模板id,获取模板的minFileName + if (ObjectUtils.isNotEmpty(moduleTemplatePrintConfig.getTemplateFileId())) { + String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); + //添加到文件目录 + filePrintRegister.setFileNames(templateName); + //添加模板到待下载列表 + filePrintRegister.setBeDownloadedFileNames(templateName); + } + } + + /** * 新增填充默认参数 */ private Map populateDefaultParam() { @@ -160,8 +174,11 @@ if (ObjectUtils.isNotEmpty(moduleFieldId)) { //获取当前模块配置 ModuleFieldConfig moduleFieldConfig = moduleFieldMapper.selectById(moduleFieldId); - //构建图片元素 - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + if (ObjectUtils.isNotEmpty(moduleFieldConfig)) { + //构建图片元素 + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); + } } //通过模块ids集合,进行关联模块参数的获取 String relateModuleIds = moduleTemplatePrintConfig.getRelateModuleFieldIds(); @@ -169,7 +186,8 @@ List moduleFieldConfigs = getRelateModuleFieldConfig(relateModuleIds); //构建图片元素 for (ModuleFieldConfig moduleFieldConfig : moduleFieldConfigs) { - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); } } //处理map中的自带的图片参数 @@ -178,9 +196,21 @@ } else { filePrintRegister.setParams(customParam); } - } + + protected void populateMergeColNames(ModuleFieldConfig moduleFieldConfig, FilePrintRegister filePrintRegister) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getMergeColNames())) { + if (CollectionUtil.isNotEmpty(filePrintRegister.getMergeColNames())) { + filePrintRegister.getMergeColNames().addAll(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } else { + filePrintRegister.setMergeColNames(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } + } + } + + + /** * 相当于消费存在一定的顺序 * @@ -382,32 +412,24 @@ /** * 构建图片json元素 */ - buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig.getImageJson()); + buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig); } + /** * 构建文件图片元素 * * @param metaDataMap * @param filePrintRegister - * @param imageJson */ - private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, String imageJson) { - if (StringUtils.isNotEmpty(imageJson)) { - //获取审批流程的bean - JSONObject imageMap = JSON.parseObject(imageJson); - //处理图片信息 - List imageMapList = (List) imageMap.get(BIND_KEY_LIST); - //判断是否有工作流字段(approvalField,工作流map取出 - ElectronicSignSeal.approvalImage(metaDataMap,imageMap,imageMapList,filePrintRegister); - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(ObjectUtils.isEmpty(imageMap.get(BIND_KEY_LIST)), - () -> { - throw new BusinessException(BusinessExceptionEnum.BIND_KEY_LIST_NULL); - }); + private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, ModuleFieldConfig moduleFieldConfig) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getImageJson())) { + //转换图片实体配置 + List imageConfig = JSON.parseArray(moduleFieldConfig.getImageJson(), ImageConfig.class); + //遍历判断是否有工作流字段(approvalField),工作流map取出 //执行构建关键字图片集合,默认为不会在列表中构建图片 - ElectronicSignSeal.bindPictureKey(filePrintRegister, imageMapList, metaDataMap); + ElectronicSignSeal.bindPictureKey(filePrintRegister, imageConfig, metaDataMap); } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java index 319a11a..535145d 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java @@ -2,7 +2,6 @@ import com.casic.missiles.dto.certificate.CropPicture; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -14,18 +13,17 @@ public class ImageTool { - public static List crosswiseCutting(CropPicture cropPicture) throws IOException { + public static List doCrosswiseCutting(CropPicture cropPicture) throws IOException { // 读入大图 File file = new File(cropPicture.getTargetImgUrl()); FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); +// System.out.println(file.exists()); BufferedImage image = ImageIO.read(fis); int chunks = cropPicture.getCutRows() * cropPicture.getCutCols(); - ImageReader imageReader=ImageIO.getImageReadersBySuffix(cropPicture.getTargetImgUrl()).next(); // 计算每个小图的宽度和高度 int chunkWidth = image.getWidth() / cropPicture.getCutCols(); int chunkHeight = image.getHeight() / cropPicture.getCutRows(); - System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 +// System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 BufferedImage imgs[] = new BufferedImage[chunks]; for (int x = 0,count = 0; x < cropPicture.getCutRows(); x++) { for (int y = 0; y < cropPicture.getCutCols(); y++) { @@ -34,14 +32,14 @@ //写入图像内容 Graphics2D gr = imgs[count++].createGraphics(); gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); - System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); +// System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); gr.dispose(); } } List subfileUrls = new ArrayList<>(); // 输出小图 for (int i = 0; i < imgs.length; i++) { - subfileUrls.add(cropPicture.getSubfileUrl() + i + cropPicture.getSubfileType()); + subfileUrls.add(cropPicture.getSubfileUrl() + i +"."+cropPicture.getSubfileType()); ImageIO.write(imgs[i], cropPicture.getSubfileType(), new File(subfileUrls.get(subfileUrls.size() - 1))); System.out.println(i); } @@ -49,29 +47,5 @@ return subfileUrls; } - public static void main(String[] agrs) throws IOException { - String originalImg = "D:\\casic\\tmp\\1645701777117741057\\ceshi.jpg"; - // 读入大图 - File file = new File(originalImg); - FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); - BufferedImage image = ImageIO.read(fis); - /* - * 假设我需要切割的四点坐标为a(20,30)b(200,40)c(30,200)d(200,210) - * 起始坐标为(最小的x,最小的y) - * 此时的实际切割坐标应为由a为起始坐标,width为(x坐标最大的点的x - a的x坐标),height为(y坐标最大的点的y - a的y坐标) - * 此时的width为180,height为180 - */ - //切割图片 - BufferedImage bf = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); - Graphics2D graphics2D = bf.createGraphics(); - graphics2D.drawImage(image, 20, 30, 180, 180, 0, 0, 180, 180, null); - graphics2D.dispose(); - //输出图片 - Random random = new Random(); - int j = random.nextInt(1000); - ImageIO.write(bf, "jpg", new File("D:\\casic\\tmp\\1645701777117741057" + j + ".jpg")); - System.out.println("完成切割"); - } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java index d63c5ae..04c3b87 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java @@ -1,21 +1,16 @@ package com.casic.missiles.service.listeners.register.data; -import cn.hutool.core.lang.Assert; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.dto.certificate.ElectronicImage; import com.casic.missiles.dto.certificate.FilePrintRegister; import com.casic.missiles.dto.flowable.ApprovalLogResponse; -import com.casic.missiles.enums.BusinessExceptionEnum; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.enums.system.FilePrintEnum; -import com.casic.missiles.exception.BusinessException; import com.casic.missiles.mapper.file.PrintFileRegisterMapper; -import com.casic.missiles.service.IBaseApprovalService; import com.casic.missiles.utils.SpringContextUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @@ -28,17 +23,19 @@ /** * 有关键字的非工作流人员章 * - * @param extendImageMapList + * @param extendImageList * @return */ - private static List electronicKeySignSeals(List extendImageMapList, Map metaDataMap, FilePrintRegister filePrintRegister) { + private static List electronicKeySignSeals(List extendImageList, Map metaDataMap, FilePrintRegister filePrintRegister) { List electronicImageSeals = new ArrayList<>(); - for (Map extendImageMap : extendImageMapList) { - ElectronicImage electronicImage = defaultElectronicImage((String) extendImageMap.get(DOC_NAME)); - if (metaDataMap.containsKey((String) extendImageMap.get(FILED_NAME)) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageMap.get(FILED_NAME)))) { - electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + for (ImageConfig extendImageConfig : extendImageList) { + ElectronicImage electronicImage = defaultElectronicImage(extendImageConfig.getDocName()); + if (metaDataMap.containsKey(extendImageConfig.getFiledName()) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageConfig.getFiledName()))) { + electronicImage.setImageConfig(extendImageConfig); + electronicImage.setIsSealImage(true); + electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageConfig.getFiledName())); //放入待下载的文件集合 - filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageConfig.getFiledName())); electronicImageSeals.add(electronicImage); } } @@ -80,50 +77,6 @@ return electronicImage; } - public static void approvalImage(Map metaDataMap, JSONObject imageMap, List imageMapList, FilePrintRegister filePrintRegister) { - - if (StringUtils.isNotEmpty(imageMap.get(APPROVAL_FIELD).toString())) { - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString()), - () -> { - throw new BusinessException(BusinessExceptionEnum.APPROVAL_FIELD_ERROR); - }); - IBaseApprovalService approvalOperateService = SpringContextUtil.getBean(IBaseApprovalService.class); - - if (!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString())) { - Iterator> it = metaDataMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue() instanceof List) { - List innerMetaDataList = (List) entry.getValue(); - if (ObjectUtils.isNotEmpty(innerMetaDataList)) { - for (Object innerMetaDataObject : innerMetaDataList) { - List> approvalLogList = null; - Field[] fields = innerMetaDataObject.getClass().getDeclaredFields(); - for (Field field : fields) { - if (!field.isAccessible()) { - field.setAccessible(true); - } - try { - if (imageMap.get(APPROVAL_FIELD).equals(field.getName()) && field.get(innerMetaDataObject) != null) { - approvalLogList = approvalOperateService.approvalLog(field.get(innerMetaDataObject).toString()); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } catch (Exception ie) { - throw new BusinessException(500, "字段映射异常"); - } - } - } - } - } - } - } else { - //获取 - List> approvalLogList = approvalOperateService.approvalLog((String) metaDataMap.get(imageMap.get(APPROVAL_FIELD).toString())); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } - } /** * 构建带有关键字的工作流签名图片方法 @@ -148,15 +101,14 @@ /** * 构建带有关键字的图片方法 */ - public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageMapList, Map metaDataMap) { + public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageConfigList, Map metaDataMap) { //处理文中的章 - List extendImageMapList = imageMapList.stream() - .filter(imageMap -> "0".equals(imageMap.get(APPROVAL_FLAG))) + List extendImageList = imageConfigList.stream() + .filter(imageMap -> StringUtils.isEmpty(imageMap.getApprovalFlag()) || "0".equals(imageMap.getApprovalFlag())) .collect(Collectors.toList()); - filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageMapList, metaDataMap, filePrintRegister)); + filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageList, metaDataMap, filePrintRegister)); } - /** * 电子签名创建器 */ diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java index fbbca76..dc4a642 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java @@ -1,13 +1,14 @@ package com.casic.missiles.service.listeners.register.data; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.dto.certificate.FilePrintRegister; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.dto.system.FieldTableDTO; import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.system.FilePrintEnum; @@ -45,21 +46,13 @@ * 3、设置文件id,作为操作空间文件名称,防止对其他同时处理的证书形成影响 */ protected final FilePrintRegister initialization(String templateFileDir, - Long id, ModuleTemplatePrintConfig moduleTemplatePrintConfig) { + Long id, + ModuleTemplatePrintConfig moduleTemplatePrintConfig) { FilePrintRegister filePrintRegister = new FilePrintRegister(); templateFileDir = templateFileDir + id + File.separator; - - PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); - //查询模板id,获取模板的minFileName - String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); - filePrintRegister.setFileName(templateName); - filePrintRegister.setTemDir(templateFileDir); - filePrintRegister.setTemplatePath(templateFileDir + templateName); + //处理待填充模板 + templateFile(moduleTemplatePrintConfig, templateFileDir, filePrintRegister); filePrintRegister.setFileNameId(id); - //添加模板到待下载列表 - List fileNames = new ArrayList<>(); - fileNames.add(templateName); - filePrintRegister.setBeDownloadedFileNames(fileNames); //这里需要添加电子签章 ElectronicSignSeal.electronicNoKeySignSeals(moduleTemplatePrintConfig.getSigns(), filePrintRegister); //添加默认的参数 @@ -68,6 +61,27 @@ } /** + * 处理模板文件 + * + * @param moduleTemplatePrintConfig + * @param templateFileDir + * @param filePrintRegister + */ + private void templateFile(ModuleTemplatePrintConfig moduleTemplatePrintConfig, String templateFileDir, FilePrintRegister filePrintRegister) { + PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); + //设置目录、路径 + filePrintRegister.setTemDir(templateFileDir); + //查询模板id,获取模板的minFileName + if (ObjectUtils.isNotEmpty(moduleTemplatePrintConfig.getTemplateFileId())) { + String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); + //添加到文件目录 + filePrintRegister.setFileNames(templateName); + //添加模板到待下载列表 + filePrintRegister.setBeDownloadedFileNames(templateName); + } + } + + /** * 新增填充默认参数 */ private Map populateDefaultParam() { @@ -160,8 +174,11 @@ if (ObjectUtils.isNotEmpty(moduleFieldId)) { //获取当前模块配置 ModuleFieldConfig moduleFieldConfig = moduleFieldMapper.selectById(moduleFieldId); - //构建图片元素 - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + if (ObjectUtils.isNotEmpty(moduleFieldConfig)) { + //构建图片元素 + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); + } } //通过模块ids集合,进行关联模块参数的获取 String relateModuleIds = moduleTemplatePrintConfig.getRelateModuleFieldIds(); @@ -169,7 +186,8 @@ List moduleFieldConfigs = getRelateModuleFieldConfig(relateModuleIds); //构建图片元素 for (ModuleFieldConfig moduleFieldConfig : moduleFieldConfigs) { - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); } } //处理map中的自带的图片参数 @@ -178,9 +196,21 @@ } else { filePrintRegister.setParams(customParam); } - } + + protected void populateMergeColNames(ModuleFieldConfig moduleFieldConfig, FilePrintRegister filePrintRegister) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getMergeColNames())) { + if (CollectionUtil.isNotEmpty(filePrintRegister.getMergeColNames())) { + filePrintRegister.getMergeColNames().addAll(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } else { + filePrintRegister.setMergeColNames(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } + } + } + + + /** * 相当于消费存在一定的顺序 * @@ -382,32 +412,24 @@ /** * 构建图片json元素 */ - buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig.getImageJson()); + buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig); } + /** * 构建文件图片元素 * * @param metaDataMap * @param filePrintRegister - * @param imageJson */ - private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, String imageJson) { - if (StringUtils.isNotEmpty(imageJson)) { - //获取审批流程的bean - JSONObject imageMap = JSON.parseObject(imageJson); - //处理图片信息 - List imageMapList = (List) imageMap.get(BIND_KEY_LIST); - //判断是否有工作流字段(approvalField,工作流map取出 - ElectronicSignSeal.approvalImage(metaDataMap,imageMap,imageMapList,filePrintRegister); - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(ObjectUtils.isEmpty(imageMap.get(BIND_KEY_LIST)), - () -> { - throw new BusinessException(BusinessExceptionEnum.BIND_KEY_LIST_NULL); - }); + private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, ModuleFieldConfig moduleFieldConfig) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getImageJson())) { + //转换图片实体配置 + List imageConfig = JSON.parseArray(moduleFieldConfig.getImageJson(), ImageConfig.class); + //遍历判断是否有工作流字段(approvalField),工作流map取出 //执行构建关键字图片集合,默认为不会在列表中构建图片 - ElectronicSignSeal.bindPictureKey(filePrintRegister, imageMapList, metaDataMap); + ElectronicSignSeal.bindPictureKey(filePrintRegister, imageConfig, metaDataMap); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java index 9b01b5c..1ebba81 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java @@ -7,24 +7,27 @@ import cn.afterturn.easypoi.word.entity.params.ExcelListEntity; import cn.afterturn.easypoi.word.parse.excel.ExcelEntityParse; import cn.afterturn.easypoi.word.parse.excel.ExcelMapParse; +import cn.hutool.core.collection.CollectionUtil; +import liquibase.pro.packaged.A; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.xwpf.usermodel.*; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; import java.math.BigInteger; import java.util.*; +import java.util.stream.Collector; import java.util.stream.Collectors; /** * poi 类不满足列循环格式插入,修改源码后满足 */ public class ParseWord07 { - private static final Logger LOGGER = LoggerFactory.getLogger(cn.afterturn.easypoi.word.parse.ParseWord07.class); + + private static final Logger LOGGER = LoggerFactory.getLogger(ParseWord07.class); public ParseWord07() { } @@ -37,9 +40,9 @@ * @return * @throws Exception */ - public XWPFDocument parseWord(String url, Map map) throws Exception { + public XWPFDocument parseWord(String url, Map map, List mergeColNames) throws Exception { MyXWPFDocument doc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(doc, map); + this.parseWordSetValue(doc, map, mergeColNames); return doc; } @@ -51,7 +54,7 @@ * @param map * @throws Exception */ - private void parseWordSetValue(MyXWPFDocument doc, Map map) throws Exception { + private void parseWordSetValue(MyXWPFDocument doc, Map map, List mergeColNames) throws Exception { this.parseAllParagraph(doc.getParagraphs(), map); this.parseHeaderAndFoot(doc, map); Iterator itTable = doc.getTablesIterator(); @@ -59,7 +62,7 @@ while (itTable.hasNext()) { XWPFTable table = (XWPFTable) itTable.next(); if (table.getText().indexOf("{{") != -1) { - this.parseThisTable(table, map); + this.parseThisTable(table, map, mergeColNames); } } } @@ -122,35 +125,6 @@ } //先执行预匹配,获取最大的长度,在进行之下的扩容 - private Integer checkTableMaxColLength(List cells, Map map, Integer maxExpansionLength) throws Exception { - int cellIndex = 0; - while (cellIndex < cells.size()) { - String text = cells.get(cellIndex).getText().trim(); - if (text != null && text.contains("#fe:") && text.startsWith("{{")) { - break; - } - cellIndex++; - } - //匹配失败 - if (cellIndex >= cells.size()) { - return maxExpansionLength; - } - String text = cells.get(cellIndex).getText().trim(); - if (text != null && text.contains("fe:") && text.startsWith("{{")) { - text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); - String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); - String[] paramKeys = keys[0].split("\\."); - Object result = PoiPublicUtil.getParamsValue(keys[0], map); - if (result instanceof List) { - List> resultMap = (List>) result; - List resultList = resultMap.stream().map(m -> m.get(paramKeys[paramKeys.length - 1])).collect(Collectors.toList()); - return maxExpansionLength > resultList.size() ? maxExpansionLength : cellIndex + 1 + resultList.size(); - } - } - return maxExpansionLength; - } - - //先执行预匹配,获取最大的长度,在进行之下的扩容 private Boolean checkThisTableCellIterator(List cells, XWPFTable table, Map map, int row, Integer maxExpansionLength, Integer differExpansionLength) throws Exception { int cellIndex = 0; @@ -175,6 +149,14 @@ return false; } String text = cells.get(cellIndex).getText().trim(); + return parseNextColAndAddCol(cells, text, cellIndex, map, table); + } + + + /** + * 解析列,并自动增加列 + */ + private Boolean parseNextColAndAddCol(List cells, String text, int cellIndex, Map map, XWPFTable table) throws Exception { if (text != null && text.contains("fe:") && text.startsWith("{{")) { text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); @@ -209,6 +191,130 @@ return false; } + /** + * 合并行的算法 + */ + private void mergeCell(XWPFTable table, List mergeColNames) { + //表头检测 + if (CollectionUtil.isNotEmpty(mergeColNames)) { + //遍寻列,同时增加下标超值判断 + int positionIndex = tryGetInitialMergeRow(table); + //查询合并索引的列 + List mergeIndexList = checkThisTableCellMergeIndex(positionIndex, table, mergeColNames); + + Map mergeIndexMap = mergeIndexList.stream().collect(Collectors.toMap(e -> e, e -> e)); + //直到查询的上下列不一样的时候,停止遍历列的循环,停止遍历 + while (positionIndex < table.getNumberOfRows()) { + XWPFTableRow row = table.getRow(positionIndex); + if (row == null) { + return; + } + int startIndex = positionIndex, maxEndIndex = positionIndex; + for (int i = 0; i < row.getTableCells().size(); i++) { + if (!mergeIndexMap.containsKey(i)) { + continue; + } + int endIndex = positionIndex; + int rowIndex = positionIndex + 1; + while ((maxEndIndex > positionIndex && rowIndex <= maxEndIndex) || + (maxEndIndex == positionIndex && rowIndex < table.getNumberOfRows())) { + if (table.getRow(rowIndex).getTableCells().get(i).getText().equals(row.getCell(i).getText())) { + endIndex = rowIndex; + rowIndex++; + } else { + break; + } + } + maxEndIndex = i == 0 ? endIndex : maxEndIndex; + if (endIndex > startIndex) { + doMergeCell(table, startIndex, endIndex, i); + } + } + positionIndex = maxEndIndex + 1; + } + } + } + + private Integer tryGetInitialMergeRow(XWPFTable table) { + int positionIndex = 1, initialMergeRow = 0; + while (positionIndex < table.getNumberOfRows()) { + if (StringUtils.isEmpty(table.getRow(positionIndex).getTableCells().get(0).getText())) { + initialMergeRow = ++positionIndex; + } else { + return initialMergeRow; + } + } + return initialMergeRow; + } + + private List checkThisTableCellMergeIndex(int positionIndex, XWPFTable table, List mergeColNames) { + Map mergeColNameMap = mergeColNames.stream().collect( + Collectors.toMap(e -> e, e -> e) + ); + int colIndex = 0; + List mergeIndexList = new ArrayList<>(); + for (int i = 0; i <= positionIndex; i++) { + XWPFTableRow row = table.getRow(i); + if (ObjectUtils.isEmpty(row)) { + continue; + } + //标题合并行 + while (colIndex < row.getTableCells().size()) { + String titleText = row.getTableCells().get(colIndex).getText(); + if (StringUtils.isNotEmpty(titleText)) { + if (mergeColNameMap.containsKey(titleText)) { + //合并两行的存在 + if (i < positionIndex) { + Integer mergerIndex = 0; + List cells = table.getRow(positionIndex).getTableCells(); + for (int j = 0; j < cells.size(); ) { + //获取当前所在行为空, + if (StringUtils.isNotEmpty(cells.get(j).getText())) { + if (++mergerIndex > colIndex) { + mergeIndexList.add(j - 1); + break; + } + while (StringUtils.isNotEmpty(cells.get(++j).getText())) { + } + } else { + j++; + if (++mergerIndex > colIndex) { + mergeIndexList.add(j - 1); + break; + } + } + } + } else { + mergeIndexList.add(colIndex); + } + } + } + colIndex++; + } + } + return mergeIndexList; + } + + /** + * 执行合并行列算法的核心方法 + */ + private static void doMergeCell(XWPFTable table, int beginRowIndex, int endRowIndex, int colIndex) { + if (beginRowIndex == endRowIndex || beginRowIndex > endRowIndex) { + return; + } + //合并行单元格的第一个单元格 + CTVMerge startMerge = CTVMerge.Factory.newInstance(); + startMerge.setVal(STMerge.RESTART); + //合并行单元格的第一个单元格之后的单元格 + CTVMerge endMerge = CTVMerge.Factory.newInstance(); + endMerge.setVal(STMerge.CONTINUE); + table.getRow(beginRowIndex).getCell(colIndex).getCTTc().getTcPr().setVMerge(startMerge); + for (int i = beginRowIndex + 1; i <= endRowIndex; i++) { + table.getRow(i).getCell(colIndex).getCTTc().getTcPr().setVMerge(endMerge); + } + } + + public void mergeCellsHorizontal(List cells, int fromCell, int toCell) { for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) { XWPFTableCell cell = cells.get(cellIndex); @@ -232,13 +338,24 @@ }); } - private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map map) throws Exception { + /** + * 行循环检测 + */ + private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map map, List mergeColNames) throws + Exception { + //增加嵌套表格的填充数据 + List tableNestList = cell.getTables(); + for (XWPFTable nestTable : tableNestList) { + if (nestTable.getText().indexOf("{{") != -1) { + this.parseThisTable(nestTable, map, mergeColNames); + } + } String text = cell.getText().trim(); - if (text != null && text.contains("fe:") && text.startsWith("{{")) { + if (StringUtils.isNotEmpty(text) && text.contains("fe:") && text.startsWith("{{")) { text = text.replace("!fe:", "").replace("$fe:", "").replace("fe:", "").replace("{{", ""); String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); Object result = PoiPublicUtil.getParamsValue(keys[0], map); - return Objects.nonNull(result) ? result : new ArrayList(0); + return Objects.isNull(result) ? null : result instanceof String ? null : result; } else { return null; } @@ -286,58 +403,62 @@ } private void parseThisRow(List cells, Map map) throws Exception { - Iterator var3 = cells.iterator(); - while (var3.hasNext()) { - XWPFTableCell cell = (XWPFTableCell) var3.next(); + int cellIndex = 0; + if (cells != null && cells.get(0).getText().contains("{{") && !cells.get(0).getText().contains("}}")) { + for (; cellIndex < cells.size(); cellIndex++) { + if (cells.get(cellIndex).getText().contains("}}")) { + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + break; + } + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + } + } + //去除{{,继续执行此行的处理 + for (; cellIndex < cells.size(); cellIndex++) { + XWPFTableCell cell = cells.get(cellIndex); this.parseAllParagraph(cell.getParagraphs(), map); } - } - private void parseThisTable(XWPFTable table, Map map) throws Exception { + private void parseThisTable(XWPFTable table, Map map, List mergeColNames) throws Exception { //默认为当前单元格的长度 - Integer maxExpansionLength = table.getRow(0).getTableCells().size(); -// //预匹配,获取扩展的最大长度 - for (int i = 0; i < table.getNumberOfRows(); ++i) { - XWPFTableRow row = table.getRow(i); - List cells = row.getTableCells(); - maxExpansionLength = checkTableMaxColLength(cells, map, maxExpansionLength); - } + Integer maxExpansionLength = tryMatchMaxLength(table, map); Integer differExpansionLength = maxExpansionLength - table.getRow(0).getTableCells().size(); //执行匹配,进行行列扩展 for (int i = 0; i < table.getNumberOfRows(); ++i) { XWPFTableRow row = table.getRow(i); List cells = row.getTableCells(); - //增加对该行列的检测 + //增加对该行列循环填充参数的添加 checkThisTableCellIterator(cells, table, map, i, maxExpansionLength, differExpansionLength); //检测该行的首个字母是否是 - Object listobj = this.checkThisTableIsNeedIterator((XWPFTableCell) cells.get(0), map); - if (listobj == null) { + Object listObj = this.checkThisTableIsNeedIterator(cells.get(0), map, mergeColNames); + if (listObj == null) { this.parseThisRow(cells, map); - } else if (listobj instanceof ExcelListEntity) { - (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj); - i = i + ((ExcelListEntity) listobj).getList().size() - 1; + } else if (listObj instanceof ExcelListEntity) { + (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listObj); + i = i + ((ExcelListEntity) listObj).getList().size() - 1; } else { - ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj); - i = i + ((List) listobj).size() - 1; + ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listObj); + i = i + ((List) listObj).size() - 1; } } - + //单个元合并 + mergeCell(table, mergeColNames); } - public XWPFDocument parseWord(String url, List> list) throws Exception { + public XWPFDocument parseWord(String url, List> list, List mergeColNames) throws Exception { if (list != null && list.size() != 0) { if (list.size() == 1) { - return this.parseWord(url, (Map) list.get(0)); + return this.parseWord(url, (Map) list.get(0), mergeColNames); } else { MyXWPFDocument doc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(doc, (Map) list.get(0)); + this.parseWordSetValue(doc, (Map) list.get(0), mergeColNames); doc.createParagraph().setPageBreak(true); for (int i = 1; i < list.size(); ++i) { MyXWPFDocument tempDoc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(tempDoc, (Map) list.get(i)); + this.parseWordSetValue(tempDoc, (Map) list.get(i), mergeColNames); tempDoc.createParagraph().setPageBreak(true); doc.getDocument().addNewBody().set(tempDoc.getDocument().getBody()); } @@ -349,8 +470,8 @@ } } - public void parseWord(XWPFDocument document, Map map) throws Exception { - this.parseWordSetValue((MyXWPFDocument) document, map); + public void parseWord(XWPFDocument document, Map map, List mergeColNames) throws Exception { + this.parseWordSetValue((MyXWPFDocument) document, map, mergeColNames); } /** @@ -371,17 +492,61 @@ this.parseThisParagraph((XWPFParagraph) xwpfHeader.getListParagraph().get(i), map); } } - List footerList = doc.getFooterList(); Iterator var9 = footerList.iterator(); while (var9.hasNext()) { XWPFFooter xwpfFooter = (XWPFFooter) var9.next(); - for (int i = 0; i < xwpfFooter.getListParagraph().size(); ++i) { this.parseThisParagraph((XWPFParagraph) xwpfFooter.getListParagraph().get(i), map); } } - } + + private Integer tryMatchMaxLength(XWPFTable table, Map map) throws Exception { + Integer maxExpansionLength = -1; + table.getRow(0).getTableCells().size(); + //预匹配,获取扩展的最大长度、 + for (int i = 0; i < table.getNumberOfRows(); ++i) { + XWPFTableRow row = table.getRow(i); + List cells = row.getTableCells(); + maxExpansionLength = doGetTableMaxColLength(cells, map, maxExpansionLength); + } + return maxExpansionLength; + } + + //先执行预匹配,获取最大的长度,在进行之下的扩容 + private Integer doGetTableMaxColLength(List cells, Map map, Integer maxExpansionLength) throws Exception { + int cellIndex = 0; + while (cellIndex < cells.size()) { + String text = cells.get(cellIndex).getText().trim(); + if (text != null && text.contains("#fe:") && text.startsWith("{{")) { + break; + } + cellIndex++; + } + //匹配失败 + if (cellIndex >= cells.size()) { + return maxExpansionLength; + } + String text = cells.get(cellIndex).getText().trim(); + if (text != null && text.contains("fe:") && text.startsWith("{{")) { + text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); + String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); + String[] paramKeys = keys[0].split("\\."); + Object result = PoiPublicUtil.getParamsValue(keys[0], map); + if (result instanceof List) { + List> resultMap = (List>) result; + List resultList = resultMap.stream().map(m -> m.get(paramKeys[paramKeys.length - 1])).collect(Collectors.toList()); + return maxExpansionLength > resultList.size() ? maxExpansionLength : cellIndex + 1 + resultList.size(); + } else if (result instanceof String) { + if (StringUtils.isEmpty((String) result)) { + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + } + } + } + return maxExpansionLength; + } + + } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java index 319a11a..535145d 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java @@ -2,7 +2,6 @@ import com.casic.missiles.dto.certificate.CropPicture; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -14,18 +13,17 @@ public class ImageTool { - public static List crosswiseCutting(CropPicture cropPicture) throws IOException { + public static List doCrosswiseCutting(CropPicture cropPicture) throws IOException { // 读入大图 File file = new File(cropPicture.getTargetImgUrl()); FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); +// System.out.println(file.exists()); BufferedImage image = ImageIO.read(fis); int chunks = cropPicture.getCutRows() * cropPicture.getCutCols(); - ImageReader imageReader=ImageIO.getImageReadersBySuffix(cropPicture.getTargetImgUrl()).next(); // 计算每个小图的宽度和高度 int chunkWidth = image.getWidth() / cropPicture.getCutCols(); int chunkHeight = image.getHeight() / cropPicture.getCutRows(); - System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 +// System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 BufferedImage imgs[] = new BufferedImage[chunks]; for (int x = 0,count = 0; x < cropPicture.getCutRows(); x++) { for (int y = 0; y < cropPicture.getCutCols(); y++) { @@ -34,14 +32,14 @@ //写入图像内容 Graphics2D gr = imgs[count++].createGraphics(); gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); - System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); +// System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); gr.dispose(); } } List subfileUrls = new ArrayList<>(); // 输出小图 for (int i = 0; i < imgs.length; i++) { - subfileUrls.add(cropPicture.getSubfileUrl() + i + cropPicture.getSubfileType()); + subfileUrls.add(cropPicture.getSubfileUrl() + i +"."+cropPicture.getSubfileType()); ImageIO.write(imgs[i], cropPicture.getSubfileType(), new File(subfileUrls.get(subfileUrls.size() - 1))); System.out.println(i); } @@ -49,29 +47,5 @@ return subfileUrls; } - public static void main(String[] agrs) throws IOException { - String originalImg = "D:\\casic\\tmp\\1645701777117741057\\ceshi.jpg"; - // 读入大图 - File file = new File(originalImg); - FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); - BufferedImage image = ImageIO.read(fis); - /* - * 假设我需要切割的四点坐标为a(20,30)b(200,40)c(30,200)d(200,210) - * 起始坐标为(最小的x,最小的y) - * 此时的实际切割坐标应为由a为起始坐标,width为(x坐标最大的点的x - a的x坐标),height为(y坐标最大的点的y - a的y坐标) - * 此时的width为180,height为180 - */ - //切割图片 - BufferedImage bf = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); - Graphics2D graphics2D = bf.createGraphics(); - graphics2D.drawImage(image, 20, 30, 180, 180, 0, 0, 180, 180, null); - graphics2D.dispose(); - //输出图片 - Random random = new Random(); - int j = random.nextInt(1000); - ImageIO.write(bf, "jpg", new File("D:\\casic\\tmp\\1645701777117741057" + j + ".jpg")); - System.out.println("完成切割"); - } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java index d63c5ae..04c3b87 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java @@ -1,21 +1,16 @@ package com.casic.missiles.service.listeners.register.data; -import cn.hutool.core.lang.Assert; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.dto.certificate.ElectronicImage; import com.casic.missiles.dto.certificate.FilePrintRegister; import com.casic.missiles.dto.flowable.ApprovalLogResponse; -import com.casic.missiles.enums.BusinessExceptionEnum; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.enums.system.FilePrintEnum; -import com.casic.missiles.exception.BusinessException; import com.casic.missiles.mapper.file.PrintFileRegisterMapper; -import com.casic.missiles.service.IBaseApprovalService; import com.casic.missiles.utils.SpringContextUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @@ -28,17 +23,19 @@ /** * 有关键字的非工作流人员章 * - * @param extendImageMapList + * @param extendImageList * @return */ - private static List electronicKeySignSeals(List extendImageMapList, Map metaDataMap, FilePrintRegister filePrintRegister) { + private static List electronicKeySignSeals(List extendImageList, Map metaDataMap, FilePrintRegister filePrintRegister) { List electronicImageSeals = new ArrayList<>(); - for (Map extendImageMap : extendImageMapList) { - ElectronicImage electronicImage = defaultElectronicImage((String) extendImageMap.get(DOC_NAME)); - if (metaDataMap.containsKey((String) extendImageMap.get(FILED_NAME)) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageMap.get(FILED_NAME)))) { - electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + for (ImageConfig extendImageConfig : extendImageList) { + ElectronicImage electronicImage = defaultElectronicImage(extendImageConfig.getDocName()); + if (metaDataMap.containsKey(extendImageConfig.getFiledName()) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageConfig.getFiledName()))) { + electronicImage.setImageConfig(extendImageConfig); + electronicImage.setIsSealImage(true); + electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageConfig.getFiledName())); //放入待下载的文件集合 - filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageConfig.getFiledName())); electronicImageSeals.add(electronicImage); } } @@ -80,50 +77,6 @@ return electronicImage; } - public static void approvalImage(Map metaDataMap, JSONObject imageMap, List imageMapList, FilePrintRegister filePrintRegister) { - - if (StringUtils.isNotEmpty(imageMap.get(APPROVAL_FIELD).toString())) { - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString()), - () -> { - throw new BusinessException(BusinessExceptionEnum.APPROVAL_FIELD_ERROR); - }); - IBaseApprovalService approvalOperateService = SpringContextUtil.getBean(IBaseApprovalService.class); - - if (!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString())) { - Iterator> it = metaDataMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue() instanceof List) { - List innerMetaDataList = (List) entry.getValue(); - if (ObjectUtils.isNotEmpty(innerMetaDataList)) { - for (Object innerMetaDataObject : innerMetaDataList) { - List> approvalLogList = null; - Field[] fields = innerMetaDataObject.getClass().getDeclaredFields(); - for (Field field : fields) { - if (!field.isAccessible()) { - field.setAccessible(true); - } - try { - if (imageMap.get(APPROVAL_FIELD).equals(field.getName()) && field.get(innerMetaDataObject) != null) { - approvalLogList = approvalOperateService.approvalLog(field.get(innerMetaDataObject).toString()); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } catch (Exception ie) { - throw new BusinessException(500, "字段映射异常"); - } - } - } - } - } - } - } else { - //获取 - List> approvalLogList = approvalOperateService.approvalLog((String) metaDataMap.get(imageMap.get(APPROVAL_FIELD).toString())); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } - } /** * 构建带有关键字的工作流签名图片方法 @@ -148,15 +101,14 @@ /** * 构建带有关键字的图片方法 */ - public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageMapList, Map metaDataMap) { + public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageConfigList, Map metaDataMap) { //处理文中的章 - List extendImageMapList = imageMapList.stream() - .filter(imageMap -> "0".equals(imageMap.get(APPROVAL_FLAG))) + List extendImageList = imageConfigList.stream() + .filter(imageMap -> StringUtils.isEmpty(imageMap.getApprovalFlag()) || "0".equals(imageMap.getApprovalFlag())) .collect(Collectors.toList()); - filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageMapList, metaDataMap, filePrintRegister)); + filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageList, metaDataMap, filePrintRegister)); } - /** * 电子签名创建器 */ diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java index fbbca76..dc4a642 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java @@ -1,13 +1,14 @@ package com.casic.missiles.service.listeners.register.data; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.dto.certificate.FilePrintRegister; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.dto.system.FieldTableDTO; import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.system.FilePrintEnum; @@ -45,21 +46,13 @@ * 3、设置文件id,作为操作空间文件名称,防止对其他同时处理的证书形成影响 */ protected final FilePrintRegister initialization(String templateFileDir, - Long id, ModuleTemplatePrintConfig moduleTemplatePrintConfig) { + Long id, + ModuleTemplatePrintConfig moduleTemplatePrintConfig) { FilePrintRegister filePrintRegister = new FilePrintRegister(); templateFileDir = templateFileDir + id + File.separator; - - PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); - //查询模板id,获取模板的minFileName - String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); - filePrintRegister.setFileName(templateName); - filePrintRegister.setTemDir(templateFileDir); - filePrintRegister.setTemplatePath(templateFileDir + templateName); + //处理待填充模板 + templateFile(moduleTemplatePrintConfig, templateFileDir, filePrintRegister); filePrintRegister.setFileNameId(id); - //添加模板到待下载列表 - List fileNames = new ArrayList<>(); - fileNames.add(templateName); - filePrintRegister.setBeDownloadedFileNames(fileNames); //这里需要添加电子签章 ElectronicSignSeal.electronicNoKeySignSeals(moduleTemplatePrintConfig.getSigns(), filePrintRegister); //添加默认的参数 @@ -68,6 +61,27 @@ } /** + * 处理模板文件 + * + * @param moduleTemplatePrintConfig + * @param templateFileDir + * @param filePrintRegister + */ + private void templateFile(ModuleTemplatePrintConfig moduleTemplatePrintConfig, String templateFileDir, FilePrintRegister filePrintRegister) { + PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); + //设置目录、路径 + filePrintRegister.setTemDir(templateFileDir); + //查询模板id,获取模板的minFileName + if (ObjectUtils.isNotEmpty(moduleTemplatePrintConfig.getTemplateFileId())) { + String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); + //添加到文件目录 + filePrintRegister.setFileNames(templateName); + //添加模板到待下载列表 + filePrintRegister.setBeDownloadedFileNames(templateName); + } + } + + /** * 新增填充默认参数 */ private Map populateDefaultParam() { @@ -160,8 +174,11 @@ if (ObjectUtils.isNotEmpty(moduleFieldId)) { //获取当前模块配置 ModuleFieldConfig moduleFieldConfig = moduleFieldMapper.selectById(moduleFieldId); - //构建图片元素 - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + if (ObjectUtils.isNotEmpty(moduleFieldConfig)) { + //构建图片元素 + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); + } } //通过模块ids集合,进行关联模块参数的获取 String relateModuleIds = moduleTemplatePrintConfig.getRelateModuleFieldIds(); @@ -169,7 +186,8 @@ List moduleFieldConfigs = getRelateModuleFieldConfig(relateModuleIds); //构建图片元素 for (ModuleFieldConfig moduleFieldConfig : moduleFieldConfigs) { - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); } } //处理map中的自带的图片参数 @@ -178,9 +196,21 @@ } else { filePrintRegister.setParams(customParam); } - } + + protected void populateMergeColNames(ModuleFieldConfig moduleFieldConfig, FilePrintRegister filePrintRegister) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getMergeColNames())) { + if (CollectionUtil.isNotEmpty(filePrintRegister.getMergeColNames())) { + filePrintRegister.getMergeColNames().addAll(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } else { + filePrintRegister.setMergeColNames(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } + } + } + + + /** * 相当于消费存在一定的顺序 * @@ -382,32 +412,24 @@ /** * 构建图片json元素 */ - buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig.getImageJson()); + buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig); } + /** * 构建文件图片元素 * * @param metaDataMap * @param filePrintRegister - * @param imageJson */ - private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, String imageJson) { - if (StringUtils.isNotEmpty(imageJson)) { - //获取审批流程的bean - JSONObject imageMap = JSON.parseObject(imageJson); - //处理图片信息 - List imageMapList = (List) imageMap.get(BIND_KEY_LIST); - //判断是否有工作流字段(approvalField,工作流map取出 - ElectronicSignSeal.approvalImage(metaDataMap,imageMap,imageMapList,filePrintRegister); - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(ObjectUtils.isEmpty(imageMap.get(BIND_KEY_LIST)), - () -> { - throw new BusinessException(BusinessExceptionEnum.BIND_KEY_LIST_NULL); - }); + private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, ModuleFieldConfig moduleFieldConfig) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getImageJson())) { + //转换图片实体配置 + List imageConfig = JSON.parseArray(moduleFieldConfig.getImageJson(), ImageConfig.class); + //遍历判断是否有工作流字段(approvalField),工作流map取出 //执行构建关键字图片集合,默认为不会在列表中构建图片 - ElectronicSignSeal.bindPictureKey(filePrintRegister, imageMapList, metaDataMap); + ElectronicSignSeal.bindPictureKey(filePrintRegister, imageConfig, metaDataMap); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java index 9b01b5c..1ebba81 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java @@ -7,24 +7,27 @@ import cn.afterturn.easypoi.word.entity.params.ExcelListEntity; import cn.afterturn.easypoi.word.parse.excel.ExcelEntityParse; import cn.afterturn.easypoi.word.parse.excel.ExcelMapParse; +import cn.hutool.core.collection.CollectionUtil; +import liquibase.pro.packaged.A; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.xwpf.usermodel.*; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; import java.math.BigInteger; import java.util.*; +import java.util.stream.Collector; import java.util.stream.Collectors; /** * poi 类不满足列循环格式插入,修改源码后满足 */ public class ParseWord07 { - private static final Logger LOGGER = LoggerFactory.getLogger(cn.afterturn.easypoi.word.parse.ParseWord07.class); + + private static final Logger LOGGER = LoggerFactory.getLogger(ParseWord07.class); public ParseWord07() { } @@ -37,9 +40,9 @@ * @return * @throws Exception */ - public XWPFDocument parseWord(String url, Map map) throws Exception { + public XWPFDocument parseWord(String url, Map map, List mergeColNames) throws Exception { MyXWPFDocument doc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(doc, map); + this.parseWordSetValue(doc, map, mergeColNames); return doc; } @@ -51,7 +54,7 @@ * @param map * @throws Exception */ - private void parseWordSetValue(MyXWPFDocument doc, Map map) throws Exception { + private void parseWordSetValue(MyXWPFDocument doc, Map map, List mergeColNames) throws Exception { this.parseAllParagraph(doc.getParagraphs(), map); this.parseHeaderAndFoot(doc, map); Iterator itTable = doc.getTablesIterator(); @@ -59,7 +62,7 @@ while (itTable.hasNext()) { XWPFTable table = (XWPFTable) itTable.next(); if (table.getText().indexOf("{{") != -1) { - this.parseThisTable(table, map); + this.parseThisTable(table, map, mergeColNames); } } } @@ -122,35 +125,6 @@ } //先执行预匹配,获取最大的长度,在进行之下的扩容 - private Integer checkTableMaxColLength(List cells, Map map, Integer maxExpansionLength) throws Exception { - int cellIndex = 0; - while (cellIndex < cells.size()) { - String text = cells.get(cellIndex).getText().trim(); - if (text != null && text.contains("#fe:") && text.startsWith("{{")) { - break; - } - cellIndex++; - } - //匹配失败 - if (cellIndex >= cells.size()) { - return maxExpansionLength; - } - String text = cells.get(cellIndex).getText().trim(); - if (text != null && text.contains("fe:") && text.startsWith("{{")) { - text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); - String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); - String[] paramKeys = keys[0].split("\\."); - Object result = PoiPublicUtil.getParamsValue(keys[0], map); - if (result instanceof List) { - List> resultMap = (List>) result; - List resultList = resultMap.stream().map(m -> m.get(paramKeys[paramKeys.length - 1])).collect(Collectors.toList()); - return maxExpansionLength > resultList.size() ? maxExpansionLength : cellIndex + 1 + resultList.size(); - } - } - return maxExpansionLength; - } - - //先执行预匹配,获取最大的长度,在进行之下的扩容 private Boolean checkThisTableCellIterator(List cells, XWPFTable table, Map map, int row, Integer maxExpansionLength, Integer differExpansionLength) throws Exception { int cellIndex = 0; @@ -175,6 +149,14 @@ return false; } String text = cells.get(cellIndex).getText().trim(); + return parseNextColAndAddCol(cells, text, cellIndex, map, table); + } + + + /** + * 解析列,并自动增加列 + */ + private Boolean parseNextColAndAddCol(List cells, String text, int cellIndex, Map map, XWPFTable table) throws Exception { if (text != null && text.contains("fe:") && text.startsWith("{{")) { text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); @@ -209,6 +191,130 @@ return false; } + /** + * 合并行的算法 + */ + private void mergeCell(XWPFTable table, List mergeColNames) { + //表头检测 + if (CollectionUtil.isNotEmpty(mergeColNames)) { + //遍寻列,同时增加下标超值判断 + int positionIndex = tryGetInitialMergeRow(table); + //查询合并索引的列 + List mergeIndexList = checkThisTableCellMergeIndex(positionIndex, table, mergeColNames); + + Map mergeIndexMap = mergeIndexList.stream().collect(Collectors.toMap(e -> e, e -> e)); + //直到查询的上下列不一样的时候,停止遍历列的循环,停止遍历 + while (positionIndex < table.getNumberOfRows()) { + XWPFTableRow row = table.getRow(positionIndex); + if (row == null) { + return; + } + int startIndex = positionIndex, maxEndIndex = positionIndex; + for (int i = 0; i < row.getTableCells().size(); i++) { + if (!mergeIndexMap.containsKey(i)) { + continue; + } + int endIndex = positionIndex; + int rowIndex = positionIndex + 1; + while ((maxEndIndex > positionIndex && rowIndex <= maxEndIndex) || + (maxEndIndex == positionIndex && rowIndex < table.getNumberOfRows())) { + if (table.getRow(rowIndex).getTableCells().get(i).getText().equals(row.getCell(i).getText())) { + endIndex = rowIndex; + rowIndex++; + } else { + break; + } + } + maxEndIndex = i == 0 ? endIndex : maxEndIndex; + if (endIndex > startIndex) { + doMergeCell(table, startIndex, endIndex, i); + } + } + positionIndex = maxEndIndex + 1; + } + } + } + + private Integer tryGetInitialMergeRow(XWPFTable table) { + int positionIndex = 1, initialMergeRow = 0; + while (positionIndex < table.getNumberOfRows()) { + if (StringUtils.isEmpty(table.getRow(positionIndex).getTableCells().get(0).getText())) { + initialMergeRow = ++positionIndex; + } else { + return initialMergeRow; + } + } + return initialMergeRow; + } + + private List checkThisTableCellMergeIndex(int positionIndex, XWPFTable table, List mergeColNames) { + Map mergeColNameMap = mergeColNames.stream().collect( + Collectors.toMap(e -> e, e -> e) + ); + int colIndex = 0; + List mergeIndexList = new ArrayList<>(); + for (int i = 0; i <= positionIndex; i++) { + XWPFTableRow row = table.getRow(i); + if (ObjectUtils.isEmpty(row)) { + continue; + } + //标题合并行 + while (colIndex < row.getTableCells().size()) { + String titleText = row.getTableCells().get(colIndex).getText(); + if (StringUtils.isNotEmpty(titleText)) { + if (mergeColNameMap.containsKey(titleText)) { + //合并两行的存在 + if (i < positionIndex) { + Integer mergerIndex = 0; + List cells = table.getRow(positionIndex).getTableCells(); + for (int j = 0; j < cells.size(); ) { + //获取当前所在行为空, + if (StringUtils.isNotEmpty(cells.get(j).getText())) { + if (++mergerIndex > colIndex) { + mergeIndexList.add(j - 1); + break; + } + while (StringUtils.isNotEmpty(cells.get(++j).getText())) { + } + } else { + j++; + if (++mergerIndex > colIndex) { + mergeIndexList.add(j - 1); + break; + } + } + } + } else { + mergeIndexList.add(colIndex); + } + } + } + colIndex++; + } + } + return mergeIndexList; + } + + /** + * 执行合并行列算法的核心方法 + */ + private static void doMergeCell(XWPFTable table, int beginRowIndex, int endRowIndex, int colIndex) { + if (beginRowIndex == endRowIndex || beginRowIndex > endRowIndex) { + return; + } + //合并行单元格的第一个单元格 + CTVMerge startMerge = CTVMerge.Factory.newInstance(); + startMerge.setVal(STMerge.RESTART); + //合并行单元格的第一个单元格之后的单元格 + CTVMerge endMerge = CTVMerge.Factory.newInstance(); + endMerge.setVal(STMerge.CONTINUE); + table.getRow(beginRowIndex).getCell(colIndex).getCTTc().getTcPr().setVMerge(startMerge); + for (int i = beginRowIndex + 1; i <= endRowIndex; i++) { + table.getRow(i).getCell(colIndex).getCTTc().getTcPr().setVMerge(endMerge); + } + } + + public void mergeCellsHorizontal(List cells, int fromCell, int toCell) { for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) { XWPFTableCell cell = cells.get(cellIndex); @@ -232,13 +338,24 @@ }); } - private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map map) throws Exception { + /** + * 行循环检测 + */ + private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map map, List mergeColNames) throws + Exception { + //增加嵌套表格的填充数据 + List tableNestList = cell.getTables(); + for (XWPFTable nestTable : tableNestList) { + if (nestTable.getText().indexOf("{{") != -1) { + this.parseThisTable(nestTable, map, mergeColNames); + } + } String text = cell.getText().trim(); - if (text != null && text.contains("fe:") && text.startsWith("{{")) { + if (StringUtils.isNotEmpty(text) && text.contains("fe:") && text.startsWith("{{")) { text = text.replace("!fe:", "").replace("$fe:", "").replace("fe:", "").replace("{{", ""); String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); Object result = PoiPublicUtil.getParamsValue(keys[0], map); - return Objects.nonNull(result) ? result : new ArrayList(0); + return Objects.isNull(result) ? null : result instanceof String ? null : result; } else { return null; } @@ -286,58 +403,62 @@ } private void parseThisRow(List cells, Map map) throws Exception { - Iterator var3 = cells.iterator(); - while (var3.hasNext()) { - XWPFTableCell cell = (XWPFTableCell) var3.next(); + int cellIndex = 0; + if (cells != null && cells.get(0).getText().contains("{{") && !cells.get(0).getText().contains("}}")) { + for (; cellIndex < cells.size(); cellIndex++) { + if (cells.get(cellIndex).getText().contains("}}")) { + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + break; + } + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + } + } + //去除{{,继续执行此行的处理 + for (; cellIndex < cells.size(); cellIndex++) { + XWPFTableCell cell = cells.get(cellIndex); this.parseAllParagraph(cell.getParagraphs(), map); } - } - private void parseThisTable(XWPFTable table, Map map) throws Exception { + private void parseThisTable(XWPFTable table, Map map, List mergeColNames) throws Exception { //默认为当前单元格的长度 - Integer maxExpansionLength = table.getRow(0).getTableCells().size(); -// //预匹配,获取扩展的最大长度 - for (int i = 0; i < table.getNumberOfRows(); ++i) { - XWPFTableRow row = table.getRow(i); - List cells = row.getTableCells(); - maxExpansionLength = checkTableMaxColLength(cells, map, maxExpansionLength); - } + Integer maxExpansionLength = tryMatchMaxLength(table, map); Integer differExpansionLength = maxExpansionLength - table.getRow(0).getTableCells().size(); //执行匹配,进行行列扩展 for (int i = 0; i < table.getNumberOfRows(); ++i) { XWPFTableRow row = table.getRow(i); List cells = row.getTableCells(); - //增加对该行列的检测 + //增加对该行列循环填充参数的添加 checkThisTableCellIterator(cells, table, map, i, maxExpansionLength, differExpansionLength); //检测该行的首个字母是否是 - Object listobj = this.checkThisTableIsNeedIterator((XWPFTableCell) cells.get(0), map); - if (listobj == null) { + Object listObj = this.checkThisTableIsNeedIterator(cells.get(0), map, mergeColNames); + if (listObj == null) { this.parseThisRow(cells, map); - } else if (listobj instanceof ExcelListEntity) { - (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj); - i = i + ((ExcelListEntity) listobj).getList().size() - 1; + } else if (listObj instanceof ExcelListEntity) { + (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listObj); + i = i + ((ExcelListEntity) listObj).getList().size() - 1; } else { - ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj); - i = i + ((List) listobj).size() - 1; + ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listObj); + i = i + ((List) listObj).size() - 1; } } - + //单个元合并 + mergeCell(table, mergeColNames); } - public XWPFDocument parseWord(String url, List> list) throws Exception { + public XWPFDocument parseWord(String url, List> list, List mergeColNames) throws Exception { if (list != null && list.size() != 0) { if (list.size() == 1) { - return this.parseWord(url, (Map) list.get(0)); + return this.parseWord(url, (Map) list.get(0), mergeColNames); } else { MyXWPFDocument doc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(doc, (Map) list.get(0)); + this.parseWordSetValue(doc, (Map) list.get(0), mergeColNames); doc.createParagraph().setPageBreak(true); for (int i = 1; i < list.size(); ++i) { MyXWPFDocument tempDoc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(tempDoc, (Map) list.get(i)); + this.parseWordSetValue(tempDoc, (Map) list.get(i), mergeColNames); tempDoc.createParagraph().setPageBreak(true); doc.getDocument().addNewBody().set(tempDoc.getDocument().getBody()); } @@ -349,8 +470,8 @@ } } - public void parseWord(XWPFDocument document, Map map) throws Exception { - this.parseWordSetValue((MyXWPFDocument) document, map); + public void parseWord(XWPFDocument document, Map map, List mergeColNames) throws Exception { + this.parseWordSetValue((MyXWPFDocument) document, map, mergeColNames); } /** @@ -371,17 +492,61 @@ this.parseThisParagraph((XWPFParagraph) xwpfHeader.getListParagraph().get(i), map); } } - List footerList = doc.getFooterList(); Iterator var9 = footerList.iterator(); while (var9.hasNext()) { XWPFFooter xwpfFooter = (XWPFFooter) var9.next(); - for (int i = 0; i < xwpfFooter.getListParagraph().size(); ++i) { this.parseThisParagraph((XWPFParagraph) xwpfFooter.getListParagraph().get(i), map); } } - } + + private Integer tryMatchMaxLength(XWPFTable table, Map map) throws Exception { + Integer maxExpansionLength = -1; + table.getRow(0).getTableCells().size(); + //预匹配,获取扩展的最大长度、 + for (int i = 0; i < table.getNumberOfRows(); ++i) { + XWPFTableRow row = table.getRow(i); + List cells = row.getTableCells(); + maxExpansionLength = doGetTableMaxColLength(cells, map, maxExpansionLength); + } + return maxExpansionLength; + } + + //先执行预匹配,获取最大的长度,在进行之下的扩容 + private Integer doGetTableMaxColLength(List cells, Map map, Integer maxExpansionLength) throws Exception { + int cellIndex = 0; + while (cellIndex < cells.size()) { + String text = cells.get(cellIndex).getText().trim(); + if (text != null && text.contains("#fe:") && text.startsWith("{{")) { + break; + } + cellIndex++; + } + //匹配失败 + if (cellIndex >= cells.size()) { + return maxExpansionLength; + } + String text = cells.get(cellIndex).getText().trim(); + if (text != null && text.contains("fe:") && text.startsWith("{{")) { + text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); + String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); + String[] paramKeys = keys[0].split("\\."); + Object result = PoiPublicUtil.getParamsValue(keys[0], map); + if (result instanceof List) { + List> resultMap = (List>) result; + List resultList = resultMap.stream().map(m -> m.get(paramKeys[paramKeys.length - 1])).collect(Collectors.toList()); + return maxExpansionLength > resultList.size() ? maxExpansionLength : cellIndex + 1 + resultList.size(); + } else if (result instanceof String) { + if (StringUtils.isEmpty((String) result)) { + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + } + } + } + return maxExpansionLength; + } + + } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/PdfUtils.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/PdfUtils.java new file mode 100644 index 0000000..a62fc98 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/PdfUtils.java @@ -0,0 +1,59 @@ +package com.casic.missiles.service.listeners.util; + + +import com.aspose.words.Document; +import com.aspose.words.License; +import com.aspose.words.SaveFormat; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; + +public class PdfUtils { + + + /*** doc转pdf + * + * @paramwordPath + * @parampdfPath + */ + public static void doc2pdf(String wordPath, String pdfPath) { + // 凭证 + String licenseStr = + "\n" + + " \n" + + " \n" + + " Aspose.Total for Java\n" + + " Aspose.Words for Java\n" + + " \n" + + " Enterprise\n" + + " 20991231\n" + + " 20991231\n" + + " 8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7\n" + + " \n" + + " sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=\n" + + ""; + try { + InputStream license = new ByteArrayInputStream(licenseStr.getBytes("UTF-8")); + License aposeLic = new License(); + aposeLic.setLicense(license); + long old = System.currentTimeMillis(); + //新建一个pdf文档 + File file = new File(pdfPath); + FileOutputStream os = new FileOutputStream(file); + //Address是将要被转化的word文档 + Document doc = new Document(wordPath); + //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换 + doc.save(os, SaveFormat.PDF); + long now = System.currentTimeMillis(); + os.close(); + //转化用时 + System.out.println("Word 转 Pdf 共耗时:" + ((now - old) / 1000.0) + "秒"); + } catch (Exception e) { + System.out.println("Word 转 Pdf 失败..."); + e.printStackTrace(); + } + } +} + diff --git a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java index b1ef7ae..dcebf36 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/enums/PrintFileModuleNameEnum.java @@ -12,4 +12,9 @@ String CUSTOMER_EXAMINE_FORM = "要求、委托书及合同评审表"; String CUSTOMER_RESULT_REVIEW_NOTICE = "检测结果复查通知单"; + + String SUB_CONTRACT_ORDER = "外送任务单"; + + String EXPORT_TEMPLATE = "导出模板"; + } diff --git a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java index 40b1ff8..bb85dc2 100644 --- a/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java +++ b/casic-metering-eqpt-api/src/main/java/com/casic/missiles/controller/subcontract/SubcontractOrderController.java @@ -1,6 +1,7 @@ package com.casic.missiles.controller.subcontract; import com.casic.missiles.controller.CommonApprovalController; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; @@ -13,6 +14,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + @RestController @RequestMapping("/subcontract/order") @Slf4j @@ -42,4 +46,12 @@ SubcontractOrderForm info = service.detail(id); return ReturnUtil.success(info); } + + @ApiOperation("外送任务单导出") + @PostMapping("/exportFile") + @ResponseBody + public void exportFile(@RequestBody @Valid ExportDTO exportDTO, HttpServletResponse response) { + service.exportFile(exportDTO,response); + } + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java index 9c1b7a8..3885fa2 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/ElectronicImage.java @@ -1,5 +1,6 @@ package com.casic.missiles.dto.certificate; +import com.casic.missiles.dto.minio.ImageConfig; import lombok.Builder; import lombok.Data; @@ -15,6 +16,11 @@ private String electronicSealImageUrl; /** + * 电子签名标记 + */ + private Boolean isSealImage= false; + + /** * 透明度 */ private Float diaphaneity; @@ -43,7 +49,6 @@ */ private Float stampHeight; - /** * 关键字 */ @@ -53,14 +58,18 @@ */ private Integer keyWordIndex; - // /** -// * 书签名,通过名称寻找书签文本所在位置 -// */ + /** + * 图片信息配置 + */ + private ImageConfig imageConfig; + /** + * 书签名,通过名称寻找书签文本所在位置 + */ private String bookmarkName; - // -// /** -// * 替换的文本新内容 -// */ + + /** + * 替换的文本新内容 + */ private String newBookmarkText; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java index 3660431..b2ea01c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/certificate/FilePrintRegister.java @@ -1,7 +1,10 @@ package com.casic.missiles.dto.certificate; +import cn.hutool.core.collection.CollectionUtil; import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -12,17 +15,13 @@ @Data public class FilePrintRegister { /** - * 模板文件的目录 - */ - private String templatePath; - /** * */ private String temDir; /** - * 生成文件名 + * 生成文件名,可能存在多个,需要进行合并,按list列表顺序合并 */ - private String fileName; + private List fileNames; /** * 生成文件名 */ @@ -32,11 +31,40 @@ */ private Map params; + /** + * 合并列名称信息 + */ + private List mergeColNames; + private List beDownloadedFileNames; /** * electronicSealList 填充的电子图片信息 */ - List electronicImageList; + private List electronicImageList; + + private Boolean mergeDoc; + + public void setFileNames(String fileName) { + //健壮性校验 + if (StringUtils.isEmpty(fileName)) { + return; + } + if (CollectionUtil.isEmpty(fileNames)) { + fileNames = new ArrayList<>(); + } + fileNames.add(fileName); + } + + public void setBeDownloadedFileNames(String beDownloadedFileName) { + //健壮性校验 + if (StringUtils.isEmpty(beDownloadedFileName)) { + return; + } + if (CollectionUtil.isEmpty(beDownloadedFileNames)) { + beDownloadedFileNames = new ArrayList<>(); + } + beDownloadedFileNames.add(beDownloadedFileName); + } } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java new file mode 100644 index 0000000..563227f --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/minio/ImageConfig.java @@ -0,0 +1,59 @@ +package com.casic.missiles.dto.minio; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author cz + */ +@Data +public class ImageConfig { + + /** + * 文件名称 + */ + @ApiModelProperty("文件名称") + private String filedName; + + /** + * 审批标志 + */ + @ApiModelProperty("审批标志") + private String approvalFlag; + + /** + * 文档参数名称 + */ + @ApiModelProperty("所在文件参数名称") + private String docName; + /** + * 表位置 + */ + @ApiModelProperty("表位置") + private Integer tableIndex; + + /** + * 行位置 + */ + @ApiModelProperty("行位置") + private Integer rowIndex; + + /** + * 列位置 + */ + @ApiModelProperty("列位置") + private Integer colIndex; + + /** + * 行合并数 + */ + @ApiModelProperty("行合并数") + private Integer rowSpan; + + /** + * 列合并列数 + */ + @ApiModelProperty("列合并列数") + private Integer colSpan; + +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java index 2a18d99..61e5785 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/file/ModuleFieldConfig.java @@ -1,13 +1,16 @@ package com.casic.missiles.model.file; +import com.baomidou.mybatisplus.annotation.FieldStrategy; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import com.casic.missiles.dto.minio.ImageConfig; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotNull; import java.io.Serializable; import java.time.LocalDateTime; +import java.util.List; /** @@ -39,23 +42,36 @@ private String imageJson; /** + * 工作流字段 + */ + @ApiModelProperty("工作流字段") + @TableField("flow_field") + private String flowField; + + @TableField(exist = false) + private List imageConfigs; + + @TableField("MERGE_COL_NAMES") + private String mergeColNames; + + /** * 备注描述 */ - @TableField("remark") + @TableField(value = "remark", updateStrategy = FieldStrategy.IGNORED) private String remark; /** * doc是否用到 */ @TableField("doc_use") - private Integer docUse; + private Integer docUse; /** * doc是否用到 */ @TableField("object_string") - private String objectString; + private String objectString; /** * 创建时间 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java index 634c91e..a6c52fe 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/subcontract/SubcontractOrderRelation.java @@ -33,6 +33,8 @@ @TableId("id") private Long id; + @ApiModelProperty("导出打印需要的序号") + private Integer seq; /** * 评审表id */ diff --git a/casic-metering-service/pom.xml b/casic-metering-service/pom.xml index 754e01d..40b875e 100644 --- a/casic-metering-service/pom.xml +++ b/casic-metering-service/pom.xml @@ -58,6 +58,16 @@ poi 4.1.2 + + com.itextpdf + itextpdf + 5.0.6 + + + com.aspose + aspose-words + 0.0.1-SNAPSHOT + \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java index d62a2b5..57386ec 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/equipment/EquipmentInfoServiceImpl.java @@ -345,9 +345,9 @@ rowIndex = Integer.valueOf(rowStr) + 1; colIndex = Integer.valueOf(colStr) + 1; } catch (NumberFormatException nfx) { - throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:", rowStr, "列:", colStr)); + throw new BusinessException(1500, String.format("导入日期格式错误,获取日期位置信息转换异常,行:" + rowStr, "列:"+ colStr)); } - throw new BusinessException(1500, String.format("第"+ rowIndex+ "行,第"+colIndex+ "列"+"日期格式不正确")); + throw new BusinessException(1500, String.format("第" + rowIndex + "行,第" + colIndex + "列" + "日期格式不正确")); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java index 0f473ab..9bddb75 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/impl/subcontract/SubcontractOrderServiceImpl.java @@ -9,11 +9,8 @@ import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.enums.ApprovalStatusEnum; -import com.casic.missiles.enums.plan.SampleStatusEnum; -import com.casic.missiles.model.plan.SampleStatueUpdate; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.casic.missiles.mapper.subcontract.SubcontractOrderMapper; -import com.casic.missiles.model.subcontract.SubcontractOrderRelation; import com.casic.missiles.model.subcontract.Subcontractor; import com.casic.missiles.service.impl.CommonApprovalServiceImpl; import com.casic.missiles.service.subcontract.ISubcontractOrderRelationService; @@ -25,7 +22,6 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Date; import java.util.List; import static com.casic.missiles.enums.PrefixCodeEnum.SUBCONTRACT_ORDER_PREFIX; @@ -48,6 +44,8 @@ private ISubcontractorService subcontractorService; @Autowired private ISystemDeptService systemDeptService; + @Autowired + private PrintFileRegister printFileRegister; @Override public Long saveOrUpdateApproval(SubcontractOrderForm form) { @@ -97,6 +95,31 @@ } @Override + public void exportFile(ExportDTO exportDTO, HttpServletResponse response) { + SubcontractOrder order = this.getById(exportDTO.getId()); + SubcontractOrderForm form = new SubcontractOrderForm(); + BeanUtil.copyProperties(order, form); + Subcontractor subcontractor = subcontractorService.getById(form.getSubcontractorId()); + if (ObjectUtil.isNotEmpty(subcontractor)) { + form.setSubcontractorCompanyName(subcontractor.getCompanyName()); + form.setFax(subcontractor.getFax()); + form.setAddress(subcontractor.getAddress()); + form.setPostcode(subcontractor.getPostcode()); + } + form.setEquipmentList(relationService.listByOrder(exportDTO.getId())); + int i = 1; + for (SubcontractOrderRelation orderRelation : form.getEquipmentList()) { + orderRelation.setSeq(i++); + } + Map map = BeanUtil.beanToMap(form); + //设置时间 + map.put("deviceCount", form.getEquipmentList().size()); + map.put("sendTime", new SimpleDateFormat("yyyy年MM月").format(order.getDelivererTime())); + map.put("applyTime", new SimpleDateFormat("yyyy年MM月dd日").format(order.getCreateTime())); + printFileRegister.registerPrintFile(SUB_CONTRACT_ORDER, EXPORT_TEMPLATE, null, map, exportDTO.isPdf(), response); + } + + @Override public List list(Wrapper queryWrapper) { return this.baseMapper.selectList(queryWrapper); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java new file mode 100644 index 0000000..dbe2a65 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/DocPictureProvider.java @@ -0,0 +1,140 @@ +package com.casic.missiles.service.listeners.register; + +import com.casic.missiles.dto.certificate.CropPicture; +import com.casic.missiles.dto.certificate.ElectronicImage; +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfReader; +import com.itextpdf.text.pdf.PdfStamper; +import com.spire.doc.Document; +import com.spire.doc.FieldType; +import com.spire.doc.HeaderFooter; +import com.spire.doc.documents.HorizontalAlignment; +import com.spire.doc.documents.Paragraph; +import com.spire.doc.documents.TextWrappingStyle; +import com.spire.doc.fields.DocPicture; +import lombok.extern.slf4j.Slf4j; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @author cz + */ +@Slf4j +public class DocPictureProvider { + + + /** + * 根据页数对图片的平等切割,返回切割后的图片 + * + * @param pageCount + * @param stampSealImgUrl + * @return + */ + public static List crosswiseCutting(int pageCount, String stampSealImgUrl) { + String[] imageCutOffContents = stampSealImgUrl.split("\\."); + CropPicture cropPicture = CropPicture.builder() + .targetImgUrl(stampSealImgUrl) + .cutCols(pageCount) + .cutRows(1) + .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) + .subfileType(imageCutOffContents[imageCutOffContents.length - 1]) + .build(); + List subfileUrls = null; + try { + subfileUrls = ImageTool.doCrosswiseCutting(cropPicture); + } catch (IOException ex) { + ex.getStackTrace(); + } + return subfileUrls; + } + + /** + * 骑缝章只存在一个章在进行打印 + */ + public static void wordFullSeam(String pdfNewUrl, String stampSealImgUrl, String outFilePath) { + try { + PdfReader reader = new PdfReader(pdfNewUrl);//选择需要印章的pdf + PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outFilePath));//加完印章后的pdf + Rectangle pageSize = reader.getPageSize(1);//获得第一页 + float height = pageSize.getHeight(); + float width = pageSize.getWidth(); + int nums = reader.getNumberOfPages(); + List subFileUrls = DocPictureProvider.crosswiseCutting(nums, stampSealImgUrl); + Image[] nImage = subImages(subFileUrls, nums);//生成骑缝章切割图片 + for (int n = 1; n <= nums; n++) { + PdfContentByte over = stamp.getOverContent(n);//设置在第几页打印印章 + Image img = nImage[n - 1];//选择图片 + img.scalePercent(40, 40); + img.setAbsolutePosition(width - img.getWidth() *4/ 10, height / 2 - img.getHeight()*4 / 20);//控制图片位置 + over.addImage(img); + } + stamp.close(); + } catch (Exception ex) { + log.error("骑缝章生成异常,异常信息为{}", ex); + } + } + + private static Image[] subImages(List subFileUrls, int n) throws IOException, BadElementException { + Image[] nImage = new Image[n]; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (int i = 0; i < n; i++) { + BufferedImage img = ImageIO.read(new File(subFileUrls.get(i))); + String[] framges = subFileUrls.get(i).split("\\."); + ImageIO.write(img, framges[framges.length - 1], out); + nImage[i] = Image.getInstance(out.toByteArray()); + out.flush(); + out.reset(); + } + return nImage; + } + + /** + * 填充图片信息 + * + * @param paragraph + * @param absolutePathImage + */ + public static void populateDocPicture(Paragraph paragraph, ElectronicImage absolutePathImage) { + DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); +// 指定电子章位置 +// 水平位置 + docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); +// 垂直位置 + docPicture.setVerticalPosition(absolutePathImage.getVertical()); +// 设置电子章大小 + docPicture.setWidth(absolutePathImage.getStampWidth()); + docPicture.setHeight(absolutePathImage.getStampHeight()); +// 设置图片位于文字顶层 + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + + /** + * 添加页眉 + * + * @param document + */ + public static void headerFooter(Document document) { + int sectionCounts= document.getSections().getCount(); + for(int i=0;i> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) - .collect( - Collectors.groupingBy(ElectronicImage::getKeyWord) - ); - //3、根据关键字进行添加签章和签字 - for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { - List electronicSeals = entry.getValue(); - addSameKeyWordStamp(wordOldUrl, wordOldUrl, electronicSeals); + try { + + //按关键字进行分组 + Map> sameKeyWordSealMaps = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isNotEmpty(electronicImage.getKeyWord())) + .collect( + Collectors.groupingBy(ElectronicImage::getKeyWord) + ); + log.debug("执行关键字打合成操作,打印配置为{}.......", JSON.toJSON(sameKeyWordSealMaps)); + //3、根据关键字进行添加签章和签字 + selectSeal = addSameKeyWordStamp(wordOldUrl, wordOldUrl, sameKeyWordSealMaps); + //获取没有关键字的图片,即绝对路径的图片 + List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() + .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) + .collect(Collectors.toList()); + log.debug("执行绝对打合成操作,打印配置为{}.......", JSON.toJSON(absolutePathImageList)); + //根据设置的绝对路径进行图片的填充 + addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImageList); + } catch (Exception ex) { + log.error("关键字异常,异常信息{}", ex); } - //获取没有关键字的图片,即绝对路径的图片 - List absolutePathImageList = filePrintRegister.getElectronicImageList().stream() - .filter(electronicImage -> StringUtils.isEmpty(electronicImage.getKeyWord())) - .collect(Collectors.toList()); - //根据设置的绝对路径进行图片的填充 - for (ElectronicImage absolutePathImage : absolutePathImageList) { - addAbsolutePathStamp(wordOldUrl, wordOldUrl, absolutePathImage); - } - //由于合成word总页数存在不准确,先转换为pdf进行获取合成证书总页数, 处理齐缝章 + } + log.debug("执行完路径设置操作"); + //如果有骑缝章新增骑缝章 + return checkExtendSeal(wordOldUrl, selectSeal, filePrintRegister); + } + + /** + * 检查是否需要骑缝章 + * + * @return + */ + private static String checkExtendSeal(String wordOldUrl, ElectronicImage selectSeal, FilePrintRegister filePrintRegister) { + if (ObjectUtils.isNotEmpty(selectSeal)) { + //默认转为docx,只需要进行docx的替换即可 + String pdfNewUrl = filePrintRegister.getFileNames().get(0).replaceAll("docx", "pdf"); + String tempPdfUrl = filePrintRegister.getTemDir() + pdfNewUrl; + FilePrintRegisterUtils.wordToPdf(wordOldUrl, tempPdfUrl); + DocPictureProvider.wordFullSeam(tempPdfUrl, selectSeal.getElectronicSealImageUrl(), filePrintRegister.getTemDir() + pdfNewUrl); + return filePrintRegister.getTemDir() + pdfNewUrl; } return wordOldUrl; } - /** * 将相同关键字的印章添加到同一个位置进行打印 * 1、根据关键词位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 * - * @param wordOldUrl word文件路径 - * @param wordNewUrl 新word文件路径 - * @param electronicSealList 电子印章信息 + * @param wordOldUrl word文件路径 + * @param wordNewUrl 新word文件路径 + * @param sameKeyWordSealMaps 电子印章信息 */ - private static void addSameKeyWordStamp(String wordOldUrl, String - wordNewUrl, List electronicSealList) throws RuntimeException { - if (CollectionUtils.isEmpty(electronicSealList)) { - return; - } + public static ElectronicImage addSameKeyWordStamp(String wordOldUrl, String + wordNewUrl, Map> sameKeyWordSealMaps) throws RuntimeException { + ElectronicImage selectSeal = null; // 加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取关键字位置 - TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false); - for (ElectronicImage electronicSeal : electronicSealList) { - //加签章照片 - if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { - throw new RuntimeException("image url is empty or key word not exist in the word template ..."); + for (Map.Entry> entry : sameKeyWordSealMaps.entrySet()) { + List electronicSealList = entry.getValue(); + if (CollectionUtils.isEmpty(electronicSealList)) { + continue; } - //多处关键字添加同一个签章 - for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { - Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); - textSelections[keyWordIndex].getCount(); - - //添加公司印章 - DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); - //设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); - //指定电子章位置 - //水平位置 - docPicture.setHorizontalPosition(electronicSeal.getHorizontal()); - //垂直位置 - docPicture.setVerticalPosition(electronicSeal.getVertical()); - //设置电子章大小 - docPicture.setWidth(electronicSeal.getStampWidth()); - docPicture.setHeight(electronicSeal.getStampHeight()); + //相同关键字的索引 + for (ElectronicImage electronicSeal : electronicSealList) { + //获取关键字位置 + TextSelection[] textSelections = document.findAllString(electronicSeal.getKeyWord(), false, false); + //加签章照片 + if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImageUrl())) { + log.warn("image url is empty or key word not exist in the word template ..."); + continue; + } + //多处关键字添加同一个签章 + for (int keyWordIndex = 0; keyWordIndex < textSelections.length; keyWordIndex++) { + Paragraph paragraph = textSelections[keyWordIndex].getAsOneRange().getOwnerParagraph(); + //添加公司印章 + DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImageUrl()); + //表、行、列索引是必填的,兼容之前的代码,之前的代码不用配置 + ImageConfig imageConfig = electronicSeal.getImageConfig(); + //设置图片位于文字顶层 + if (ObjectUtils.isNotEmpty(electronicSeal.getIsSealImage()) && electronicSeal.getIsSealImage()) { + docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); + } + if (ObjectUtils.isNotEmpty(imageConfig) && + (ObjectUtils.isNotEmpty(imageConfig.getTableIndex()) && imageConfig.getTableIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getRowIndex()) && imageConfig.getRowIndex() != -1) && + (ObjectUtils.isNotEmpty(imageConfig.getColIndex()) && imageConfig.getColIndex() != -1)) { + //指定电子章位置 + Section section = textSelections[keyWordIndex].getAsOneRange().getDocument().getLastSection(); + //水平位置 + docPicture.setHorizontalAlignment(ShapeHorizontalAlignment.Center); + //垂直位置 + docPicture.setVerticalAlignment(ShapeVerticalAlignment.Center); + //设置电子章大小 //宽度可以计算 + docPicture.setWidth(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getCells().get(imageConfig.getColIndex()).getWidth()); + docPicture.setHeight(section.getTables().get(imageConfig.getTableIndex()) + .getRows().get(imageConfig.getRowIndex()).getHeight()); + //合并行列是选填,需要进一步判断 + if (ObjectUtils.isNotEmpty(imageConfig.getRowSpan())) { + docPicture.setHeight(docPicture.getHeight() * imageConfig.getRowSpan()); + } + if (ObjectUtils.isNotEmpty(imageConfig.getColSpan())) { + docPicture.setWidth(docPicture.getWidth() * imageConfig.getColSpan()); + } + } else { + docPicture.setVerticalPosition(0f); + docPicture.setWidth(electronicSeal.getStampWidth()); + docPicture.setHeight(electronicSeal.getStampHeight()); + } + //带有公章的关键字且页数大于2,需要设置骑缝章 + if (INSIGNIA_KEYWORD.equals(electronicSeal.getKeyWord()) && document.getPageCount() >= 2) { + selectSeal = electronicSeal; + } + } } } - //保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); + return selectSeal; } /** @@ -156,11 +207,12 @@ * @param pdfNewUrl 存储新PDF文件路径 */ public static void wordToPdf(String wordNewUrl, String pdfNewUrl) { + PdfUtils.doc2pdf(wordNewUrl, pdfNewUrl); // 将新Word文档转换为PDF文件 - Document document = new Document(); - document.loadFromFile(wordNewUrl); - document.saveToFile(pdfNewUrl, FileFormat.PDF); - document.dispose(); +// Document document = new Document(); +// document.loadFromFile(wordNewUrl); +// document.saveToFile(pdfNewUrl, FileFormat.PDF); +// document.dispose(); } /** @@ -170,6 +222,7 @@ * @param alpha * @return */ + @Deprecated public static BufferedImage convertLayout(BufferedImage imgsrc, float alpha) { try { //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色 @@ -191,27 +244,6 @@ } } - //读取图片 - private static BufferedImage readImage(String imgpath) { - try { - BufferedImage bufferedImage = ImageIO.read(new File(imgpath)); - return bufferedImage; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - //保存图片,extent为格式,"jpg"、"png"等 - private static void saveFile(BufferedImage img, String extent, String newfile) { - try { - ImageIO.write(img, extent, new File(newfile)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** * 1、自定义位置添加电子印章 * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作 @@ -219,40 +251,26 @@ * @param wordOldUrl word文件路径 * @param wordNewUrl 新word文件路径 */ - private static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, ElectronicImage absolutePathImage) { - // 加载文档 + public static void addAbsolutePathStamp(String wordOldUrl, String wordNewUrl, List absolutePathImageList) { + //加载文档 Document document = new Document(); document.loadFromFile(wordOldUrl); - //获取指定段落 - Section section = document.getSections().get(0); - //log.info("获取文档内容段落总数{}",count); - Paragraph paragraph = section.getParagraphs().get(0); - // 判断是否需要替换书签位置文本内容 - if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { - replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + for (ElectronicImage absolutePathImage : absolutePathImageList) { + //不是骑缝章,就是认定章,获取默认段落信息,进行添加电子印章的信息位置 + Section section = document.getSections().get(DEFAULT_SEAL_INDEX); + Paragraph paragraph = section.getParagraphs().get(DEFAULT_SEAL_INDEX); + //判断是否需要替换书签位置文本内容 + if (StringUtils.isNotEmpty(absolutePathImage.getBookmarkName())) { + replaceBookmarkContent(document, absolutePathImage.getBookmarkName(), absolutePathImage.getNewBookmarkText()); + } + //添加电子印章 + DocPictureProvider.populateDocPicture(paragraph, absolutePathImage); } -// 添加电子印章 - DocPicture docPicture = paragraph.appendPicture(absolutePathImage.getElectronicSealImageUrl()); - -// 指定电子章位置 -// 水平位置 - docPicture.setHorizontalPosition(absolutePathImage.getHorizontal()); -// 垂直位置 - docPicture.setVerticalPosition(absolutePathImage.getVertical()); - -// 设置电子章大小 - docPicture.setWidth(absolutePathImage.getStampWidth()); - docPicture.setHeight(absolutePathImage.getStampHeight()); - -// 设置图片位于文字顶层 - docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text); // 保存添加电子章的Word文档 document.saveToFile(wordNewUrl); document.dispose(); -// log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl); } - /** * 替换书签名位置文本内容为图片 * @@ -280,14 +298,12 @@ */ public void replaceBookmarkContentToTable(Document document, String bookmarkName) { //声明数组内容 - String[][] data = - { - new String[]{"分类", "等级", "编号"}, - new String[]{"A", "一级", "01A"}, - new String[]{"B", "二级", "02B"}, - new String[]{"C", "三级", "03C"}, - }; - + String[][] data = { + new String[]{"分类", "等级", "编号"}, + new String[]{"A", "一级", "01A"}, + new String[]{"B", "二级", "02B"}, + new String[]{"C", "三级", "03C"}, + }; //创建表格 Table table = new Table(document, true); table.resetCells(4, 3); @@ -301,47 +317,16 @@ dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle); } } - //创建TextBodyPart对象 TextBodyPart bodyPart = new TextBodyPart(document); bodyPart.getBodyItems().add(table); - //定位到指定书签位置 BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document); bookmarkNavigator.moveToBookmark(bookmarkName); - //使用表格替换原书签的内容 bookmarkNavigator.replaceBookmarkContent(bodyPart); } - /** - * 文件转流 - * - * @param wordNewUrl - * @return - */ - public byte[] getBytesByFile(String wordNewUrl) { - try { -// byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl)); - File file = new File(wordNewUrl); - FileInputStream fis = new FileInputStream(file); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] b = new byte[1024]; - int len = -1; - while ((len = fis.read(b)) != -1) { - bos.write(b, 0, len); - } - fis.close(); - bos.close(); - byte[] bytes = bos.toByteArray(); - System.out.println("successful..."); - return bytes; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - /** * doc 转 docx @@ -398,134 +383,74 @@ /** * 按照模板 填充数据生成word 只支持docx * - * @param templatePath 模板文件路径 - * @param temDir 生成文件的目录 - * @param fileName 生成文件名 - * @param params 参数 + * @param temDir 生成文件的目录 + * @param fileNames 待处理的文件列表 + * @param params 参数 */ - public static String exportWord(String templatePath, String temDir, String fileName, Map params) { - Assert.notNull(templatePath, "模板路径不能为空"); + public static String exportWord(String temDir, List fileNames, Map params, List mergeColNames) { + //两个文档合并为fileNames[0]文档 + String fileName = mergeDoc(temDir, fileNames); Assert.notNull(temDir, "临时文件路径不能为空"); - Assert.notNull(fileName, "导出文件名不能为空"); - if (fileName.endsWith(".doc")) { - docToDocx(templatePath, templatePath + "x"); - templatePath += "x"; - fileName+="x"; - } Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式"); File dir = new File(temDir); if (!dir.getParentFile().exists()) { // 新建文件夹 dir.getParentFile().mkdirs(); } - String tmpPath = ""; + String filePath = ""; FileOutputStream fos = null; try { + //执行文件填充 ParseWord07 parseWord07 = new ParseWord07(); - XWPFDocument doc = parseWord07.parseWord(templatePath, params); - tmpPath = temDir + fileName; - fos = new FileOutputStream(tmpPath); + XWPFDocument doc = parseWord07.parseWord(temDir + fileName, params, mergeColNames); + filePath = temDir + fileName; + fos = new FileOutputStream(filePath); doc.write(fos); fos.flush(); + //增加对固定文本框的文字填充的处理一般的poi不支持,需要调用poi-tl执行文件打印操作 + ConfigureBuilder builder = Configure.builder(); + XWPFTemplate compile = XWPFTemplate.compile(temDir + fileName, builder.build()); + compile.render(params); + filePath = temDir + fileName; + compile.writeToFile(filePath); } catch (Exception e) { e.printStackTrace(); } finally { try { - fos.close(); + if (fos != null) { + fos.close(); + } } catch (IOException e) { e.printStackTrace(); } } - return tmpPath; + return filePath; } - - public static void main(String[] args) throws RuntimeException { - String pathUrl = "D:\\casic"; - String localPathUrl = "D:\\casic\\"; - // 目标文件地址 - String wordOldUrl = pathUrl + "\\工作记录单.docx"; - Map params = new HashMap<>(); - List> assetList = new ArrayList<>(); - for (int i = 0; i < 8; i++) { - Map assetMap = new HashMap<>(); - assetMap.put("assetName", "我不是设备名称"); - assetMap.put("model", "我不是型号"); - assetMap.put("assetNo", "我是设备编号"); - assetList.add(assetMap); + /** + * 多个docx文档合并功能,合并为第一个文档 + * + * @param localPathUrl + * @param fileNames + * @return + */ + private static String mergeDoc(String localPathUrl, List fileNames) { + //doc合并 + if (CollectionUtils.isEmpty(fileNames)) { + return null; } - params.put("assetList", assetList); - params.put("logNo", "本编号"); - params.put("laboratoryName", "此去半生"); - params.put("executiveAddress", "猜猜我在哪里"); - - params.put("test", new TextRenderData("R", new Style("Wingdings 2", 14))); - params.put("error", new TextRenderData("*", new Style("Wingdings 2", 14))); - - String newOldUrl = exportWord(wordOldUrl, localPathUrl, "temp.docx", params); - //默认转为docx,只需要进行docx的替换即可 - String pdfNewUrl = newOldUrl.replaceAll("docx", "pdf"); - wordToPdf(newOldUrl, pdfNewUrl); -// //WORD转PDF存放位置 -// String pdfNewUrl = localPathUrl + "\\tem.pdf"; -// //电子印章图片地址 -// String stampNameImgUr = localPathUrl + "\\name1_1678844060471.png"; -// //电子签名图片地址 -// String stampSealImgUrl = localPathUrl + "\\ceshi.jpg"; -// // word文档内容关键字 -// FilePrintRegisterUtils addStampUtils = new FilePrintRegisterUtils(); -// List electronicSealList = new ArrayList(11); -// ElectronicImage electronicImage = defaultElectronicSignName("批准人"); -// electronicImage.setElectronicSealImageUrl(stampNameImgUr); -// electronicSealList.add(electronicImage); -// addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList); -// //加载文档 -// Document document = new Document(); -// document.loadFromFile(wordOldUrl); -// //获取段落总数 -// int count = document.getPageCount(); -// System.out.println(count); -// String[] imageCutOffContents = stampSealImgUrl.split("\\."); -// CropPicture cropPicture = CropPicture.builder() -// .targetImgUrl(stampSealImgUrl) -// .cutCols(count) -// .cutRows(1) -// .subfileUrl(imageCutOffContents[imageCutOffContents.length - 2]) -// .subfileType("." + imageCutOffContents[imageCutOffContents.length - 1]) -// .build(); -// try { -// ImageTool.crosswiseCutting(cropPicture); -// } catch (IOException ex) { -// -// } -//// 将新word转化为pdf文件 -//// addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl); - } - - protected static ElectronicImage defaultElectronicSignSeal(String keyWord, float horizontal) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-50f) - .horizontal(450f) - .stampHeight(100f) - .stampWidth(100f) - .diaphaneity(150f) - .build(); - return electronicImage; - } - - protected static ElectronicImage defaultElectronicSignName(String keyWord) { - ElectronicImage electronicImage = ElectronicImage.builder() - .keyWordIndex(-1) - .keyWord(keyWord) - .vertical(-10f) - .horizontal(60f) - .stampHeight(40f) - .stampWidth(60f) - .diaphaneity(150f) - .build(); - return electronicImage; + if (fileNames.size() > 1) { + String word1Url = localPathUrl + fileNames.get(0); + Document mainDoc = new Document(word1Url); + for (int i = 1; i < fileNames.size(); ) { + String word2Url = localPathUrl + fileNames.get(i++); + mainDoc.insertTextFromFile(word2Url, FileFormat.Docx_2010); + } + DocPictureProvider.headerFooter(mainDoc); + //保存合并后的文档 + mainDoc.saveToFile(word1Url, FileFormat.Docx_2010); + } + return fileNames.get(0); } } \ No newline at end of file diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java index 319a11a..535145d 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/ImageTool.java @@ -2,7 +2,6 @@ import com.casic.missiles.dto.certificate.CropPicture; import javax.imageio.ImageIO; -import javax.imageio.ImageReader; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; @@ -14,18 +13,17 @@ public class ImageTool { - public static List crosswiseCutting(CropPicture cropPicture) throws IOException { + public static List doCrosswiseCutting(CropPicture cropPicture) throws IOException { // 读入大图 File file = new File(cropPicture.getTargetImgUrl()); FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); +// System.out.println(file.exists()); BufferedImage image = ImageIO.read(fis); int chunks = cropPicture.getCutRows() * cropPicture.getCutCols(); - ImageReader imageReader=ImageIO.getImageReadersBySuffix(cropPicture.getTargetImgUrl()).next(); // 计算每个小图的宽度和高度 int chunkWidth = image.getWidth() / cropPicture.getCutCols(); int chunkHeight = image.getHeight() / cropPicture.getCutRows(); - System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 +// System.out.println("图片的宽度为:" + chunkWidth * cropPicture.getCutRows() + "图片的高度为:" + chunkHeight * cropPicture.getCutCols());//230,278 BufferedImage imgs[] = new BufferedImage[chunks]; for (int x = 0,count = 0; x < cropPicture.getCutRows(); x++) { for (int y = 0; y < cropPicture.getCutCols(); y++) { @@ -34,14 +32,14 @@ //写入图像内容 Graphics2D gr = imgs[count++].createGraphics(); gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); - System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); +// System.out.println("源矩阵第一个角的坐标" + chunkWidth * y + "+" + chunkHeight * x + "源矩阵第二个角的坐标" + chunkWidth * (y + 1) + "+" + chunkHeight * (x + 1)); gr.dispose(); } } List subfileUrls = new ArrayList<>(); // 输出小图 for (int i = 0; i < imgs.length; i++) { - subfileUrls.add(cropPicture.getSubfileUrl() + i + cropPicture.getSubfileType()); + subfileUrls.add(cropPicture.getSubfileUrl() + i +"."+cropPicture.getSubfileType()); ImageIO.write(imgs[i], cropPicture.getSubfileType(), new File(subfileUrls.get(subfileUrls.size() - 1))); System.out.println(i); } @@ -49,29 +47,5 @@ return subfileUrls; } - public static void main(String[] agrs) throws IOException { - String originalImg = "D:\\casic\\tmp\\1645701777117741057\\ceshi.jpg"; - // 读入大图 - File file = new File(originalImg); - FileInputStream fis = new FileInputStream(file); - System.out.println(file.exists()); - BufferedImage image = ImageIO.read(fis); - /* - * 假设我需要切割的四点坐标为a(20,30)b(200,40)c(30,200)d(200,210) - * 起始坐标为(最小的x,最小的y) - * 此时的实际切割坐标应为由a为起始坐标,width为(x坐标最大的点的x - a的x坐标),height为(y坐标最大的点的y - a的y坐标) - * 此时的width为180,height为180 - */ - //切割图片 - BufferedImage bf = new BufferedImage(image.getWidth(), image.getHeight(), image.getType()); - Graphics2D graphics2D = bf.createGraphics(); - graphics2D.drawImage(image, 20, 30, 180, 180, 0, 0, 180, 180, null); - graphics2D.dispose(); - //输出图片 - Random random = new Random(); - int j = random.nextInt(1000); - ImageIO.write(bf, "jpg", new File("D:\\casic\\tmp\\1645701777117741057" + j + ".jpg")); - System.out.println("完成切割"); - } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java index d63c5ae..04c3b87 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/ElectronicSignSeal.java @@ -1,21 +1,16 @@ package com.casic.missiles.service.listeners.register.data; -import cn.hutool.core.lang.Assert; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.dto.certificate.ElectronicImage; import com.casic.missiles.dto.certificate.FilePrintRegister; import com.casic.missiles.dto.flowable.ApprovalLogResponse; -import com.casic.missiles.enums.BusinessExceptionEnum; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.enums.system.FilePrintEnum; -import com.casic.missiles.exception.BusinessException; import com.casic.missiles.mapper.file.PrintFileRegisterMapper; -import com.casic.missiles.service.IBaseApprovalService; import com.casic.missiles.utils.SpringContextUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @@ -28,17 +23,19 @@ /** * 有关键字的非工作流人员章 * - * @param extendImageMapList + * @param extendImageList * @return */ - private static List electronicKeySignSeals(List extendImageMapList, Map metaDataMap, FilePrintRegister filePrintRegister) { + private static List electronicKeySignSeals(List extendImageList, Map metaDataMap, FilePrintRegister filePrintRegister) { List electronicImageSeals = new ArrayList<>(); - for (Map extendImageMap : extendImageMapList) { - ElectronicImage electronicImage = defaultElectronicImage((String) extendImageMap.get(DOC_NAME)); - if (metaDataMap.containsKey((String) extendImageMap.get(FILED_NAME)) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageMap.get(FILED_NAME)))) { - electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + for (ImageConfig extendImageConfig : extendImageList) { + ElectronicImage electronicImage = defaultElectronicImage(extendImageConfig.getDocName()); + if (metaDataMap.containsKey(extendImageConfig.getFiledName()) && ObjectUtils.isNotEmpty(metaDataMap.get(extendImageConfig.getFiledName()))) { + electronicImage.setImageConfig(extendImageConfig); + electronicImage.setIsSealImage(true); + electronicImage.setElectronicSealImageUrl(filePrintRegister.getTemDir() + (String) metaDataMap.get(extendImageConfig.getFiledName())); //放入待下载的文件集合 - filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageMap.get(FILED_NAME))); + filePrintRegister.getBeDownloadedFileNames().add((String) metaDataMap.get(extendImageConfig.getFiledName())); electronicImageSeals.add(electronicImage); } } @@ -80,50 +77,6 @@ return electronicImage; } - public static void approvalImage(Map metaDataMap, JSONObject imageMap, List imageMapList, FilePrintRegister filePrintRegister) { - - if (StringUtils.isNotEmpty(imageMap.get(APPROVAL_FIELD).toString())) { - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString()), - () -> { - throw new BusinessException(BusinessExceptionEnum.APPROVAL_FIELD_ERROR); - }); - IBaseApprovalService approvalOperateService = SpringContextUtil.getBean(IBaseApprovalService.class); - - if (!metaDataMap.containsKey(imageMap.get(APPROVAL_FIELD).toString())) { - Iterator> it = metaDataMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue() instanceof List) { - List innerMetaDataList = (List) entry.getValue(); - if (ObjectUtils.isNotEmpty(innerMetaDataList)) { - for (Object innerMetaDataObject : innerMetaDataList) { - List> approvalLogList = null; - Field[] fields = innerMetaDataObject.getClass().getDeclaredFields(); - for (Field field : fields) { - if (!field.isAccessible()) { - field.setAccessible(true); - } - try { - if (imageMap.get(APPROVAL_FIELD).equals(field.getName()) && field.get(innerMetaDataObject) != null) { - approvalLogList = approvalOperateService.approvalLog(field.get(innerMetaDataObject).toString()); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } catch (Exception ie) { - throw new BusinessException(500, "字段映射异常"); - } - } - } - } - } - } - } else { - //获取 - List> approvalLogList = approvalOperateService.approvalLog((String) metaDataMap.get(imageMap.get(APPROVAL_FIELD).toString())); - bindSignPictureKey(filePrintRegister, imageMapList, approvalLogList); - } - } - } /** * 构建带有关键字的工作流签名图片方法 @@ -148,15 +101,14 @@ /** * 构建带有关键字的图片方法 */ - public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageMapList, Map metaDataMap) { + public static void bindPictureKey(FilePrintRegister filePrintRegister, List imageConfigList, Map metaDataMap) { //处理文中的章 - List extendImageMapList = imageMapList.stream() - .filter(imageMap -> "0".equals(imageMap.get(APPROVAL_FLAG))) + List extendImageList = imageConfigList.stream() + .filter(imageMap -> StringUtils.isEmpty(imageMap.getApprovalFlag()) || "0".equals(imageMap.getApprovalFlag())) .collect(Collectors.toList()); - filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageMapList, metaDataMap, filePrintRegister)); + filePrintRegister.getElectronicImageList().addAll(ElectronicSignSeal.electronicKeySignSeals(extendImageList, metaDataMap, filePrintRegister)); } - /** * 电子签名创建器 */ diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java index fbbca76..dc4a642 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/register/data/FilePrintSupport.java @@ -1,13 +1,14 @@ package com.casic.missiles.service.listeners.register.data; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.casic.missiles.core.application.service.AbstractDictService; import com.casic.missiles.dto.certificate.FilePrintRegister; +import com.casic.missiles.dto.minio.ImageConfig; import com.casic.missiles.dto.system.FieldTableDTO; import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.system.FilePrintEnum; @@ -45,21 +46,13 @@ * 3、设置文件id,作为操作空间文件名称,防止对其他同时处理的证书形成影响 */ protected final FilePrintRegister initialization(String templateFileDir, - Long id, ModuleTemplatePrintConfig moduleTemplatePrintConfig) { + Long id, + ModuleTemplatePrintConfig moduleTemplatePrintConfig) { FilePrintRegister filePrintRegister = new FilePrintRegister(); templateFileDir = templateFileDir + id + File.separator; - - PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); - //查询模板id,获取模板的minFileName - String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); - filePrintRegister.setFileName(templateName); - filePrintRegister.setTemDir(templateFileDir); - filePrintRegister.setTemplatePath(templateFileDir + templateName); + //处理待填充模板 + templateFile(moduleTemplatePrintConfig, templateFileDir, filePrintRegister); filePrintRegister.setFileNameId(id); - //添加模板到待下载列表 - List fileNames = new ArrayList<>(); - fileNames.add(templateName); - filePrintRegister.setBeDownloadedFileNames(fileNames); //这里需要添加电子签章 ElectronicSignSeal.electronicNoKeySignSeals(moduleTemplatePrintConfig.getSigns(), filePrintRegister); //添加默认的参数 @@ -68,6 +61,27 @@ } /** + * 处理模板文件 + * + * @param moduleTemplatePrintConfig + * @param templateFileDir + * @param filePrintRegister + */ + private void templateFile(ModuleTemplatePrintConfig moduleTemplatePrintConfig, String templateFileDir, FilePrintRegister filePrintRegister) { + PrintFileRegisterMapper fileRegisterMapper = SpringContextUtil.getBean(PrintFileRegisterMapper.class); + //设置目录、路径 + filePrintRegister.setTemDir(templateFileDir); + //查询模板id,获取模板的minFileName + if (ObjectUtils.isNotEmpty(moduleTemplatePrintConfig.getTemplateFileId())) { + String templateName = fileRegisterMapper.getTemplateFileById(moduleTemplatePrintConfig.getTemplateFileId()); + //添加到文件目录 + filePrintRegister.setFileNames(templateName); + //添加模板到待下载列表 + filePrintRegister.setBeDownloadedFileNames(templateName); + } + } + + /** * 新增填充默认参数 */ private Map populateDefaultParam() { @@ -160,8 +174,11 @@ if (ObjectUtils.isNotEmpty(moduleFieldId)) { //获取当前模块配置 ModuleFieldConfig moduleFieldConfig = moduleFieldMapper.selectById(moduleFieldId); - //构建图片元素 - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + if (ObjectUtils.isNotEmpty(moduleFieldConfig)) { + //构建图片元素 + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); + } } //通过模块ids集合,进行关联模块参数的获取 String relateModuleIds = moduleTemplatePrintConfig.getRelateModuleFieldIds(); @@ -169,7 +186,8 @@ List moduleFieldConfigs = getRelateModuleFieldConfig(relateModuleIds); //构建图片元素 for (ModuleFieldConfig moduleFieldConfig : moduleFieldConfigs) { - buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig.getImageJson()); + populateMergeColNames(moduleFieldConfig, filePrintRegister); + buildDocImageElement(customParam, filePrintRegister, moduleFieldConfig); } } //处理map中的自带的图片参数 @@ -178,9 +196,21 @@ } else { filePrintRegister.setParams(customParam); } - } + + protected void populateMergeColNames(ModuleFieldConfig moduleFieldConfig, FilePrintRegister filePrintRegister) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getMergeColNames())) { + if (CollectionUtil.isNotEmpty(filePrintRegister.getMergeColNames())) { + filePrintRegister.getMergeColNames().addAll(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } else { + filePrintRegister.setMergeColNames(Arrays.asList(moduleFieldConfig.getMergeColNames().split(","))); + } + } + } + + + /** * 相当于消费存在一定的顺序 * @@ -382,32 +412,24 @@ /** * 构建图片json元素 */ - buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig.getImageJson()); + buildDocImageElement(metaDataMap, filePrintRegister, moduleFieldConfig); } + /** * 构建文件图片元素 * * @param metaDataMap * @param filePrintRegister - * @param imageJson */ - private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, String imageJson) { - if (StringUtils.isNotEmpty(imageJson)) { - //获取审批流程的bean - JSONObject imageMap = JSON.parseObject(imageJson); - //处理图片信息 - List imageMapList = (List) imageMap.get(BIND_KEY_LIST); - //判断是否有工作流字段(approvalField,工作流map取出 - ElectronicSignSeal.approvalImage(metaDataMap,imageMap,imageMapList,filePrintRegister); - //健壮性校验,没有绑定的list结合去掉 - Assert.isFalse(ObjectUtils.isEmpty(imageMap.get(BIND_KEY_LIST)), - () -> { - throw new BusinessException(BusinessExceptionEnum.BIND_KEY_LIST_NULL); - }); + private void buildDocImageElement(Map metaDataMap, FilePrintRegister filePrintRegister, ModuleFieldConfig moduleFieldConfig) { + if (StringUtils.isNotEmpty(moduleFieldConfig.getImageJson())) { + //转换图片实体配置 + List imageConfig = JSON.parseArray(moduleFieldConfig.getImageJson(), ImageConfig.class); + //遍历判断是否有工作流字段(approvalField),工作流map取出 //执行构建关键字图片集合,默认为不会在列表中构建图片 - ElectronicSignSeal.bindPictureKey(filePrintRegister, imageMapList, metaDataMap); + ElectronicSignSeal.bindPictureKey(filePrintRegister, imageConfig, metaDataMap); } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java index 9b01b5c..1ebba81 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/ParseWord07.java @@ -7,24 +7,27 @@ import cn.afterturn.easypoi.word.entity.params.ExcelListEntity; import cn.afterturn.easypoi.word.parse.excel.ExcelEntityParse; import cn.afterturn.easypoi.word.parse.excel.ExcelMapParse; +import cn.hutool.core.collection.CollectionUtil; +import liquibase.pro.packaged.A; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.xwpf.usermodel.*; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; import java.math.BigInteger; import java.util.*; +import java.util.stream.Collector; import java.util.stream.Collectors; /** * poi 类不满足列循环格式插入,修改源码后满足 */ public class ParseWord07 { - private static final Logger LOGGER = LoggerFactory.getLogger(cn.afterturn.easypoi.word.parse.ParseWord07.class); + + private static final Logger LOGGER = LoggerFactory.getLogger(ParseWord07.class); public ParseWord07() { } @@ -37,9 +40,9 @@ * @return * @throws Exception */ - public XWPFDocument parseWord(String url, Map map) throws Exception { + public XWPFDocument parseWord(String url, Map map, List mergeColNames) throws Exception { MyXWPFDocument doc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(doc, map); + this.parseWordSetValue(doc, map, mergeColNames); return doc; } @@ -51,7 +54,7 @@ * @param map * @throws Exception */ - private void parseWordSetValue(MyXWPFDocument doc, Map map) throws Exception { + private void parseWordSetValue(MyXWPFDocument doc, Map map, List mergeColNames) throws Exception { this.parseAllParagraph(doc.getParagraphs(), map); this.parseHeaderAndFoot(doc, map); Iterator itTable = doc.getTablesIterator(); @@ -59,7 +62,7 @@ while (itTable.hasNext()) { XWPFTable table = (XWPFTable) itTable.next(); if (table.getText().indexOf("{{") != -1) { - this.parseThisTable(table, map); + this.parseThisTable(table, map, mergeColNames); } } } @@ -122,35 +125,6 @@ } //先执行预匹配,获取最大的长度,在进行之下的扩容 - private Integer checkTableMaxColLength(List cells, Map map, Integer maxExpansionLength) throws Exception { - int cellIndex = 0; - while (cellIndex < cells.size()) { - String text = cells.get(cellIndex).getText().trim(); - if (text != null && text.contains("#fe:") && text.startsWith("{{")) { - break; - } - cellIndex++; - } - //匹配失败 - if (cellIndex >= cells.size()) { - return maxExpansionLength; - } - String text = cells.get(cellIndex).getText().trim(); - if (text != null && text.contains("fe:") && text.startsWith("{{")) { - text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); - String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); - String[] paramKeys = keys[0].split("\\."); - Object result = PoiPublicUtil.getParamsValue(keys[0], map); - if (result instanceof List) { - List> resultMap = (List>) result; - List resultList = resultMap.stream().map(m -> m.get(paramKeys[paramKeys.length - 1])).collect(Collectors.toList()); - return maxExpansionLength > resultList.size() ? maxExpansionLength : cellIndex + 1 + resultList.size(); - } - } - return maxExpansionLength; - } - - //先执行预匹配,获取最大的长度,在进行之下的扩容 private Boolean checkThisTableCellIterator(List cells, XWPFTable table, Map map, int row, Integer maxExpansionLength, Integer differExpansionLength) throws Exception { int cellIndex = 0; @@ -175,6 +149,14 @@ return false; } String text = cells.get(cellIndex).getText().trim(); + return parseNextColAndAddCol(cells, text, cellIndex, map, table); + } + + + /** + * 解析列,并自动增加列 + */ + private Boolean parseNextColAndAddCol(List cells, String text, int cellIndex, Map map, XWPFTable table) throws Exception { if (text != null && text.contains("fe:") && text.startsWith("{{")) { text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); @@ -209,6 +191,130 @@ return false; } + /** + * 合并行的算法 + */ + private void mergeCell(XWPFTable table, List mergeColNames) { + //表头检测 + if (CollectionUtil.isNotEmpty(mergeColNames)) { + //遍寻列,同时增加下标超值判断 + int positionIndex = tryGetInitialMergeRow(table); + //查询合并索引的列 + List mergeIndexList = checkThisTableCellMergeIndex(positionIndex, table, mergeColNames); + + Map mergeIndexMap = mergeIndexList.stream().collect(Collectors.toMap(e -> e, e -> e)); + //直到查询的上下列不一样的时候,停止遍历列的循环,停止遍历 + while (positionIndex < table.getNumberOfRows()) { + XWPFTableRow row = table.getRow(positionIndex); + if (row == null) { + return; + } + int startIndex = positionIndex, maxEndIndex = positionIndex; + for (int i = 0; i < row.getTableCells().size(); i++) { + if (!mergeIndexMap.containsKey(i)) { + continue; + } + int endIndex = positionIndex; + int rowIndex = positionIndex + 1; + while ((maxEndIndex > positionIndex && rowIndex <= maxEndIndex) || + (maxEndIndex == positionIndex && rowIndex < table.getNumberOfRows())) { + if (table.getRow(rowIndex).getTableCells().get(i).getText().equals(row.getCell(i).getText())) { + endIndex = rowIndex; + rowIndex++; + } else { + break; + } + } + maxEndIndex = i == 0 ? endIndex : maxEndIndex; + if (endIndex > startIndex) { + doMergeCell(table, startIndex, endIndex, i); + } + } + positionIndex = maxEndIndex + 1; + } + } + } + + private Integer tryGetInitialMergeRow(XWPFTable table) { + int positionIndex = 1, initialMergeRow = 0; + while (positionIndex < table.getNumberOfRows()) { + if (StringUtils.isEmpty(table.getRow(positionIndex).getTableCells().get(0).getText())) { + initialMergeRow = ++positionIndex; + } else { + return initialMergeRow; + } + } + return initialMergeRow; + } + + private List checkThisTableCellMergeIndex(int positionIndex, XWPFTable table, List mergeColNames) { + Map mergeColNameMap = mergeColNames.stream().collect( + Collectors.toMap(e -> e, e -> e) + ); + int colIndex = 0; + List mergeIndexList = new ArrayList<>(); + for (int i = 0; i <= positionIndex; i++) { + XWPFTableRow row = table.getRow(i); + if (ObjectUtils.isEmpty(row)) { + continue; + } + //标题合并行 + while (colIndex < row.getTableCells().size()) { + String titleText = row.getTableCells().get(colIndex).getText(); + if (StringUtils.isNotEmpty(titleText)) { + if (mergeColNameMap.containsKey(titleText)) { + //合并两行的存在 + if (i < positionIndex) { + Integer mergerIndex = 0; + List cells = table.getRow(positionIndex).getTableCells(); + for (int j = 0; j < cells.size(); ) { + //获取当前所在行为空, + if (StringUtils.isNotEmpty(cells.get(j).getText())) { + if (++mergerIndex > colIndex) { + mergeIndexList.add(j - 1); + break; + } + while (StringUtils.isNotEmpty(cells.get(++j).getText())) { + } + } else { + j++; + if (++mergerIndex > colIndex) { + mergeIndexList.add(j - 1); + break; + } + } + } + } else { + mergeIndexList.add(colIndex); + } + } + } + colIndex++; + } + } + return mergeIndexList; + } + + /** + * 执行合并行列算法的核心方法 + */ + private static void doMergeCell(XWPFTable table, int beginRowIndex, int endRowIndex, int colIndex) { + if (beginRowIndex == endRowIndex || beginRowIndex > endRowIndex) { + return; + } + //合并行单元格的第一个单元格 + CTVMerge startMerge = CTVMerge.Factory.newInstance(); + startMerge.setVal(STMerge.RESTART); + //合并行单元格的第一个单元格之后的单元格 + CTVMerge endMerge = CTVMerge.Factory.newInstance(); + endMerge.setVal(STMerge.CONTINUE); + table.getRow(beginRowIndex).getCell(colIndex).getCTTc().getTcPr().setVMerge(startMerge); + for (int i = beginRowIndex + 1; i <= endRowIndex; i++) { + table.getRow(i).getCell(colIndex).getCTTc().getTcPr().setVMerge(endMerge); + } + } + + public void mergeCellsHorizontal(List cells, int fromCell, int toCell) { for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) { XWPFTableCell cell = cells.get(cellIndex); @@ -232,13 +338,24 @@ }); } - private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map map) throws Exception { + /** + * 行循环检测 + */ + private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map map, List mergeColNames) throws + Exception { + //增加嵌套表格的填充数据 + List tableNestList = cell.getTables(); + for (XWPFTable nestTable : tableNestList) { + if (nestTable.getText().indexOf("{{") != -1) { + this.parseThisTable(nestTable, map, mergeColNames); + } + } String text = cell.getText().trim(); - if (text != null && text.contains("fe:") && text.startsWith("{{")) { + if (StringUtils.isNotEmpty(text) && text.contains("fe:") && text.startsWith("{{")) { text = text.replace("!fe:", "").replace("$fe:", "").replace("fe:", "").replace("{{", ""); String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); Object result = PoiPublicUtil.getParamsValue(keys[0], map); - return Objects.nonNull(result) ? result : new ArrayList(0); + return Objects.isNull(result) ? null : result instanceof String ? null : result; } else { return null; } @@ -286,58 +403,62 @@ } private void parseThisRow(List cells, Map map) throws Exception { - Iterator var3 = cells.iterator(); - while (var3.hasNext()) { - XWPFTableCell cell = (XWPFTableCell) var3.next(); + int cellIndex = 0; + if (cells != null && cells.get(0).getText().contains("{{") && !cells.get(0).getText().contains("}}")) { + for (; cellIndex < cells.size(); cellIndex++) { + if (cells.get(cellIndex).getText().contains("}}")) { + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + break; + } + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + } + } + //去除{{,继续执行此行的处理 + for (; cellIndex < cells.size(); cellIndex++) { + XWPFTableCell cell = cells.get(cellIndex); this.parseAllParagraph(cell.getParagraphs(), map); } - } - private void parseThisTable(XWPFTable table, Map map) throws Exception { + private void parseThisTable(XWPFTable table, Map map, List mergeColNames) throws Exception { //默认为当前单元格的长度 - Integer maxExpansionLength = table.getRow(0).getTableCells().size(); -// //预匹配,获取扩展的最大长度 - for (int i = 0; i < table.getNumberOfRows(); ++i) { - XWPFTableRow row = table.getRow(i); - List cells = row.getTableCells(); - maxExpansionLength = checkTableMaxColLength(cells, map, maxExpansionLength); - } + Integer maxExpansionLength = tryMatchMaxLength(table, map); Integer differExpansionLength = maxExpansionLength - table.getRow(0).getTableCells().size(); //执行匹配,进行行列扩展 for (int i = 0; i < table.getNumberOfRows(); ++i) { XWPFTableRow row = table.getRow(i); List cells = row.getTableCells(); - //增加对该行列的检测 + //增加对该行列循环填充参数的添加 checkThisTableCellIterator(cells, table, map, i, maxExpansionLength, differExpansionLength); //检测该行的首个字母是否是 - Object listobj = this.checkThisTableIsNeedIterator((XWPFTableCell) cells.get(0), map); - if (listobj == null) { + Object listObj = this.checkThisTableIsNeedIterator(cells.get(0), map, mergeColNames); + if (listObj == null) { this.parseThisRow(cells, map); - } else if (listobj instanceof ExcelListEntity) { - (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj); - i = i + ((ExcelListEntity) listobj).getList().size() - 1; + } else if (listObj instanceof ExcelListEntity) { + (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listObj); + i = i + ((ExcelListEntity) listObj).getList().size() - 1; } else { - ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj); - i = i + ((List) listobj).size() - 1; + ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listObj); + i = i + ((List) listObj).size() - 1; } } - + //单个元合并 + mergeCell(table, mergeColNames); } - public XWPFDocument parseWord(String url, List> list) throws Exception { + public XWPFDocument parseWord(String url, List> list, List mergeColNames) throws Exception { if (list != null && list.size() != 0) { if (list.size() == 1) { - return this.parseWord(url, (Map) list.get(0)); + return this.parseWord(url, (Map) list.get(0), mergeColNames); } else { MyXWPFDocument doc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(doc, (Map) list.get(0)); + this.parseWordSetValue(doc, (Map) list.get(0), mergeColNames); doc.createParagraph().setPageBreak(true); for (int i = 1; i < list.size(); ++i) { MyXWPFDocument tempDoc = WordCache.getXWPFDocument(url); - this.parseWordSetValue(tempDoc, (Map) list.get(i)); + this.parseWordSetValue(tempDoc, (Map) list.get(i), mergeColNames); tempDoc.createParagraph().setPageBreak(true); doc.getDocument().addNewBody().set(tempDoc.getDocument().getBody()); } @@ -349,8 +470,8 @@ } } - public void parseWord(XWPFDocument document, Map map) throws Exception { - this.parseWordSetValue((MyXWPFDocument) document, map); + public void parseWord(XWPFDocument document, Map map, List mergeColNames) throws Exception { + this.parseWordSetValue((MyXWPFDocument) document, map, mergeColNames); } /** @@ -371,17 +492,61 @@ this.parseThisParagraph((XWPFParagraph) xwpfHeader.getListParagraph().get(i), map); } } - List footerList = doc.getFooterList(); Iterator var9 = footerList.iterator(); while (var9.hasNext()) { XWPFFooter xwpfFooter = (XWPFFooter) var9.next(); - for (int i = 0; i < xwpfFooter.getListParagraph().size(); ++i) { this.parseThisParagraph((XWPFParagraph) xwpfFooter.getListParagraph().get(i), map); } } - } + + private Integer tryMatchMaxLength(XWPFTable table, Map map) throws Exception { + Integer maxExpansionLength = -1; + table.getRow(0).getTableCells().size(); + //预匹配,获取扩展的最大长度、 + for (int i = 0; i < table.getNumberOfRows(); ++i) { + XWPFTableRow row = table.getRow(i); + List cells = row.getTableCells(); + maxExpansionLength = doGetTableMaxColLength(cells, map, maxExpansionLength); + } + return maxExpansionLength; + } + + //先执行预匹配,获取最大的长度,在进行之下的扩容 + private Integer doGetTableMaxColLength(List cells, Map map, Integer maxExpansionLength) throws Exception { + int cellIndex = 0; + while (cellIndex < cells.size()) { + String text = cells.get(cellIndex).getText().trim(); + if (text != null && text.contains("#fe:") && text.startsWith("{{")) { + break; + } + cellIndex++; + } + //匹配失败 + if (cellIndex >= cells.size()) { + return maxExpansionLength; + } + String text = cells.get(cellIndex).getText().trim(); + if (text != null && text.contains("fe:") && text.startsWith("{{")) { + text = text.replace("#fe:", "").replace("{{", "").replace("}}", ""); + String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" "); + String[] paramKeys = keys[0].split("\\."); + Object result = PoiPublicUtil.getParamsValue(keys[0], map); + if (result instanceof List) { + List> resultMap = (List>) result; + List resultList = resultMap.stream().map(m -> m.get(paramKeys[paramKeys.length - 1])).collect(Collectors.toList()); + return maxExpansionLength > resultList.size() ? maxExpansionLength : cellIndex + 1 + resultList.size(); + } else if (result instanceof String) { + if (StringUtils.isEmpty((String) result)) { + clearParagraphText((cells.get(cellIndex)).getParagraphs()); + } + } + } + return maxExpansionLength; + } + + } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/PdfUtils.java b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/PdfUtils.java new file mode 100644 index 0000000..a62fc98 --- /dev/null +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/listeners/util/PdfUtils.java @@ -0,0 +1,59 @@ +package com.casic.missiles.service.listeners.util; + + +import com.aspose.words.Document; +import com.aspose.words.License; +import com.aspose.words.SaveFormat; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; + +public class PdfUtils { + + + /*** doc转pdf + * + * @paramwordPath + * @parampdfPath + */ + public static void doc2pdf(String wordPath, String pdfPath) { + // 凭证 + String licenseStr = + "\n" + + " \n" + + " \n" + + " Aspose.Total for Java\n" + + " Aspose.Words for Java\n" + + " \n" + + " Enterprise\n" + + " 20991231\n" + + " 20991231\n" + + " 8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7\n" + + " \n" + + " sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=\n" + + ""; + try { + InputStream license = new ByteArrayInputStream(licenseStr.getBytes("UTF-8")); + License aposeLic = new License(); + aposeLic.setLicense(license); + long old = System.currentTimeMillis(); + //新建一个pdf文档 + File file = new File(pdfPath); + FileOutputStream os = new FileOutputStream(file); + //Address是将要被转化的word文档 + Document doc = new Document(wordPath); + //全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换 + doc.save(os, SaveFormat.PDF); + long now = System.currentTimeMillis(); + os.close(); + //转化用时 + System.out.println("Word 转 Pdf 共耗时:" + ((now - old) / 1000.0) + "秒"); + } catch (Exception e) { + System.out.println("Word 转 Pdf 失败..."); + e.printStackTrace(); + } + } +} + diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/subcontract/ISubcontractOrderService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/subcontract/ISubcontractOrderService.java index 8bf9102..a773f0f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/subcontract/ISubcontractOrderService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/subcontract/ISubcontractOrderService.java @@ -2,12 +2,17 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.casic.missiles.dto.ExportDTO; import com.casic.missiles.dto.subcontract.SubcontractOrderForm; import com.casic.missiles.dto.subcontract.SubcontractOrderQueryForm; import com.casic.missiles.dto.subcontract.SubcontractReviewForm; import com.casic.missiles.model.subcontract.SubcontractOrder; import com.baomidou.mybatisplus.extension.service.IService; import com.casic.missiles.service.ICommonApprovalService; +import org.springframework.web.bind.annotation.RequestBody; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; /** *

@@ -22,4 +27,6 @@ Long saveOrUpdateApproval(SubcontractOrderForm form); SubcontractOrderForm detail(Long orderId); + + void exportFile(ExportDTO exportDTO, HttpServletResponse response); }