Parcourir la source

订单审核全部功能的开发

dongxin il y a 1 an
Parent
commit
98a9f22e66
37 fichiers modifiés avec 2956 ajouts et 5 suppressions
  1. 11 0
      commons/pom.xml
  2. 11 0
      commons/src/main/java/com/jzg/commons/entity/dto/FeeAuditAddParam.java
  3. 108 0
      commons/src/main/java/com/jzg/commons/entity/dto/FeeAuditParam.java
  4. 18 0
      commons/src/main/java/com/jzg/commons/entity/dto/VerifyOrderParam.java
  5. 53 0
      commons/src/main/java/com/jzg/commons/entity/orders/po/InsFeeAudit.java
  6. 94 0
      commons/src/main/java/com/jzg/commons/entity/orders/po/InsFeeOrderRecord.java
  7. 48 0
      commons/src/main/java/com/jzg/commons/entity/orders/po/InsOrderReadPdf.java
  8. 54 0
      commons/src/main/java/com/jzg/commons/entity/orders/vo/AuditCostInfoVo.java
  9. 95 0
      commons/src/main/java/com/jzg/commons/entity/orders/vo/FeeAuditVo.java
  10. 9 0
      commons/src/main/java/com/jzg/commons/entity/quote/vo/aggregated/QuoteEchoVo.java
  11. 4 0
      commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsOrdersVo.java
  12. 2 1
      commons/src/main/java/com/jzg/commons/entity/vo/OrdersTrackVo.java
  13. 36 0
      commons/src/main/java/com/jzg/commons/util/Base64Convert.java
  14. 209 0
      commons/src/main/java/com/jzg/commons/util/CompressUtil.java
  15. 340 0
      commons/src/main/java/com/jzg/commons/util/FileUtil.java
  16. 678 0
      commons/src/main/java/com/jzg/commons/util/PDFUtil.java
  17. 30 0
      commons/src/main/java/com/jzg/commons/util/http/HttpUtils.java
  18. 1 1
      gateway/src/main/resources/application-dev.yml
  19. 11 0
      platform/src/main/java/com/jzg/controller/EsmInsCompanyController.java
  20. 22 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/EsmInsCompanyClient.java
  21. 2 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java
  22. 137 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeAuditController.java
  23. 23 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsFeeAuditMapper.java
  24. 18 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsFeeOrderRecordMapper.java
  25. 18 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsOrderReadPdfMapper.java
  26. 94 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeAuditService.java
  27. 14 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeOrderRecordService.java
  28. 13 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrderReadPdfService.java
  29. 470 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java
  30. 22 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeOrderRecordServiceImpl.java
  31. 22 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrderReadPdfServiceImpl.java
  32. 6 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java
  33. 39 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/state/AuditState.java
  34. 34 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/state/config/AuditStateConfig.java
  35. 78 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/state/listener/AuditStateListener.java
  36. 4 1
      tenant/insurance/quotation-summary/src/main/resources/application.yaml
  37. 128 0
      tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeAuditMapper.xml

+ 11 - 0
commons/pom.xml

@@ -87,6 +87,17 @@
             <artifactId>httpclient5</artifactId>
             <version>5.2.1</version> <!-- 请使用最新版本 -->
         </dependency>
+        <!--读取pdf-->
+        <dependency>
+            <groupId>org.apache.pdfbox</groupId>
+            <artifactId>pdfbox</artifactId>
+            <version>2.0.28</version>
+        </dependency>
+        <dependency>
+            <groupId>net.lingala.zip4j</groupId>
+            <artifactId>zip4j</artifactId>
+            <version>1.3.2</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

+ 11 - 0
commons/src/main/java/com/jzg/commons/entity/dto/FeeAuditAddParam.java

@@ -0,0 +1,11 @@
+package com.jzg.commons.entity.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(description = "订单审核新增dto")
+public class FeeAuditAddParam {
+
+
+}

+ 108 - 0
commons/src/main/java/com/jzg/commons/entity/dto/FeeAuditParam.java

@@ -0,0 +1,108 @@
+package com.jzg.commons.entity.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jzg.commons.core.base.PageRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "订单审核表分页查询dto")
+@Data
+public class FeeAuditParam extends PageRequest {
+
+    @Schema(description = "车牌号")
+    private String licenseNo;
+
+    @Schema(description = "业务员类型1.前线人员 2:后线人员 3:合伙人 4:工作室管理员 5:团队 6:个代 7:电销 8 渠道")
+    private String attrType;
+
+    @Schema(description = "业务员")
+    private String salesman;
+
+    @Schema(description = "订单状态  1 车险录入 2 待客录单 3 外部订单")
+    private String orderStatus;
+
+    @Schema(description = "订单类型  1 车险录入 2 待客录单 3 外部订单")
+    private String orderType;
+
+    @Schema(description = "保险公司id")
+    private String companyId;
+
+    @Schema(description = "保险公司id列表")
+    private List<String> companyIdList;
+
+    @Schema(description = "出单机构id")
+    private String deptId;
+
+    @Schema(description = "被保人姓名")
+    private String insurName;
+
+    @Schema(description = "报价时间开始")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime quotationTimeStart;
+
+    @Schema(description = "报价时间结束")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime quotationTimeEnd;
+
+    @Schema(description = "签单时间开始")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate signingTimeStart;
+
+    @Schema(description = "签单时间开始")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate signingTimeEnd;
+
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "出单协议Id")
+    private String agreementId;
+
+    @Schema(description = "险种")
+    private String productName;
+
+    @Schema(description = "支付时间开始")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime payTimeStart;
+
+    @Schema(description = "支付时间结束")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime payTimeEnd;
+
+    @Schema(description = "交强保单号")
+    private String ciPolicyNumber;
+
+    @Schema(description = "商业保单号")
+    private String biPolicyNumber;
+
+    @Schema(description = "驾意险保单号")
+    private String niPolicyNumber;
+
+    @Schema(description = "审核时间开始")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime auditTimeStart;
+
+    @Schema(description = "审核时间结束")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDateTime auditTimeEnd;
+
+    @Schema(description = "审核人")
+    private String auditUser;
+
+    @Schema(description = "领取人")
+    private String receiveUser;
+
+    @Schema(description = "审核方式 1 人工审核 2 自动审核")
+    private Integer auditType;
+
+    @Schema(description = "费用审核状态0未审核 1审核通过 2.审核不通过")
+    private Integer auditStatus;
+
+
+
+}

+ 18 - 0
commons/src/main/java/com/jzg/commons/entity/dto/VerifyOrderParam.java

@@ -0,0 +1,18 @@
+package com.jzg.commons.entity.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "审核订单dto")
+@Data
+public class VerifyOrderParam {
+
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "费用审核状态 1审核通过 2.审核不通过")
+    private Integer auditStatus;
+
+    @Schema(description = "驳回原因")
+    private String refuse;
+}

+ 53 - 0
commons/src/main/java/com/jzg/commons/entity/orders/po/InsFeeAudit.java

@@ -0,0 +1,53 @@
+
+package com.jzg.commons.entity.orders.po;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jzg.commons.core.base.BaseModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 订单审核表
+ * @TableName ins_fee_audit
+ */
+@Data
+@Schema(description = "订单审核表")
+public class InsFeeAudit extends BaseModel {
+
+    @TableId(value = "order_no")
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "费用审核状态0未审核 1审核通过 2.审核不通过")
+    private Integer auditStatus;
+
+    @Schema(description = "审核时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime auditTime;
+
+    @Schema(description = "审核人")
+    private String auditUser;
+
+    @Schema(description = "领取时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime receiveTime;
+
+    @Schema(description = "领取人")
+    private String receiveUser;
+
+    @Schema(description = "是否是疑问订单 0.否 1.是")
+    private Integer isProblem;
+
+    @Schema(description = "驳回原因")
+    private String refuse;
+
+    @Schema(description = "审核方式 1 人工审核 2 自动审核")
+    private Integer auditType;
+
+}

+ 94 - 0
commons/src/main/java/com/jzg/commons/entity/orders/po/InsFeeOrderRecord.java

@@ -0,0 +1,94 @@
+package com.jzg.commons.entity.orders.po;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.jzg.commons.core.base.BaseModel;
+import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 订单费用调整记录表
+ * @TableName ins_fee_order_record
+ */
+@Data
+@Schema(description = "订单费用调整记录表")
+@NoArgsConstructor
+public class InsFeeOrderRecord extends BaseModel {
+
+    @TableId(value = "order_no")
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "交强入口比例")
+    private BigDecimal jqInletRadio;
+
+    @Schema(description = "交强入口手续费比例")
+    private BigDecimal jqEntranceFeeRatio;
+
+    @Schema(description = "交强跟单比例")
+    private BigDecimal jqFollowRatio;
+
+    @Schema(description = "交强加投比例")
+    private BigDecimal jqAddThrowRadio;
+
+    @Schema(description = "交强留点比例")
+    private BigDecimal jqKeepPointRatio;
+
+    @Schema(description = "商业入口比例")
+    private BigDecimal syInletRadio;
+
+    @Schema(description = "商业入口手续费比例")
+    private BigDecimal syEntranceFeeRatio;
+
+    @Schema(description = "商业跟单比例")
+    private BigDecimal syFollowRatio;
+
+    @Schema(description = "商业加投比例")
+    private BigDecimal syAddThrowRadio;
+
+    @Schema(description = "商业留点比例")
+    private BigDecimal syKeepPointRatio;
+
+    @Schema(description = "非车入口比例")
+    private BigDecimal noInletRadio;
+
+    @Schema(description = "非车入口手续费比例")
+    private BigDecimal noEntranceFeeRatio;
+
+    @Schema(description = "非车跟单比例")
+    private BigDecimal noFollowRatio;
+
+    @Schema(description = "非车加投比例")
+    private BigDecimal noAddThrowRadio;
+
+    @Schema(description = "非车留点比例")
+    private BigDecimal noKeepPointRatio;
+
+
+    public InsFeeOrderRecord(PtlAgreementCostRatioVo param) {
+        this.orderNo = param.getOrderNo();
+        this.jqInletRadio = param.getJqInletRatio();
+        this.jqEntranceFeeRatio = param.getJqCommissionRatio();
+        this.jqFollowRatio = param.getJqFollowRatio();
+        this.jqAddThrowRadio = param.getJqAdditionalRatio();
+        this.jqKeepPointRatio = param.getJqKeepPointRatio();
+
+        this.syInletRadio = param.getSyInletRatio();
+        this.syEntranceFeeRatio = param.getSyCommissionRatio();
+        this.syFollowRatio = param.getSyFollowRatio();
+        this.syAddThrowRadio = param.getSyAdditionalRatio();
+        this.syKeepPointRatio = param.getSyKeepPointRatio();
+
+        this.noInletRadio = param.getJyInletRatio();
+        this.noEntranceFeeRatio = param.getJyCommissionRatio();
+        this.noFollowRatio = param.getJyFollowRatio();
+        this.noAddThrowRadio = param.getJyAdditionalRatio();
+        this.noKeepPointRatio = param.getJyKeepPointRatio();
+
+    }
+}

+ 48 - 0
commons/src/main/java/com/jzg/commons/entity/orders/po/InsOrderReadPdf.java

@@ -0,0 +1,48 @@
+package com.jzg.commons.entity.orders.po;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.jzg.commons.core.base.BaseModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ *
+ * @TableName ins_order_read_pdf
+ */
+@Data
+@Schema(description = "保单读取信息配置表")
+public class InsOrderReadPdf extends BaseModel {
+
+    @Schema(description = "主键")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private String id;
+
+    @Schema(description = "保险公司id")
+    private String companyId;
+
+    @Schema(description = "保险公司名称")
+    private String companyName;
+
+    @Schema(description = "读取pdf字段")
+    private String readName;
+
+    @Schema(description = "截取前缀")
+    private String readBegin;
+
+    @Schema(description = "截取后缀")
+    private String readEnd;
+
+    @Schema(description = "1.yyyy-mm-dd 2.年月日 3. yyyy/mm/dd ")
+    private String readType;
+
+    @Schema(description = "保单字段信息")
+    private String orderMsg;
+
+    @Schema(description = "1.交强 2.商业")
+    private String type;
+
+}

+ 54 - 0
commons/src/main/java/com/jzg/commons/entity/orders/vo/AuditCostInfoVo.java

@@ -0,0 +1,54 @@
+package com.jzg.commons.entity.orders.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "订单审核表费用详情VO")
+@Data
+public class AuditCostInfoVo {
+
+    @Schema(description = "费用类型1-交强险2-商业险3-驾意险")
+    private String costType;
+
+    @Schema(description = "保费")
+    private BigDecimal premium;
+
+    @Schema(description = "入口比例")
+    private BigDecimal inletRadio;
+
+    @Schema(description = "入口费用")
+    private BigDecimal inletPremium;
+
+    @Schema(description = "入口手续费比例")
+    private BigDecimal entranceFeeRatio;
+
+    @Schema(description = "入口手续费")
+    private BigDecimal entranceFeePremium;
+
+    @Schema(description = "跟单费用比例")
+    private BigDecimal followRatio;
+
+    @Schema(description = "跟单费用")
+    private BigDecimal followPremium;
+
+    @Schema(description = "加投比例")
+    private BigDecimal addThrowRatio;
+
+    @Schema(description = "加投费用")
+    private BigDecimal addThrowPremium;
+
+    @Schema(description = "出口比例")
+    private BigDecimal exportRatio;
+
+    @Schema(description = "出口费用")
+    private BigDecimal exportPremium;
+
+    @Schema(description = "留点比例")
+    private BigDecimal keepPointRatio;
+
+    @Schema(description = "留点费用")
+    private BigDecimal keepPointPremium;
+
+}

+ 95 - 0
commons/src/main/java/com/jzg/commons/entity/orders/vo/FeeAuditVo.java

@@ -0,0 +1,95 @@
+package com.jzg.commons.entity.orders.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jzg.commons.core.base.BaseModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+@Schema(description = "订单审核表VO")
+@Data
+public class FeeAuditVo extends BaseModel {
+
+    @Schema(description = "订单号")
+    private String orderNo;
+
+    @Schema(description = "保险公司")
+    private String companyName;
+
+    @Schema(description = "车牌号")
+    private String licenseNo;
+
+    @Schema(description = "被保人姓名")
+    private String insurName;
+
+    @Schema(description = "订单类型  1 车险录入 2 待客录单 3 外部订单")
+    private Integer orderType;
+
+    @Schema(description = "业务员姓名")
+    private String name;
+
+    @Schema(description = "业务员手机号")
+    private String mobile;
+
+    @Schema(description = "业务员类型1.前线人员 2:后线人员 3:合伙人 4:工作室管理员 5:团队 6:个代 7:电销 8 渠道")
+    private String attrType;
+
+    @Schema(description = "签单时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDate signingTime;
+
+    @Schema(description = "报价时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime quotationTime;
+
+    @Schema(description = "对接人")
+    private String dockingPerson;
+
+    @Schema(description = "出单协议")
+    private String agreementName;
+
+    @Schema(description = "险种")
+    private String productName;
+
+    @Schema(description = "出单机构")
+    private String deptName;
+
+    @Schema(description = "录单时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    @Schema(description = "录单人")
+    private String createBy;
+
+    @Schema(description = "支付时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime payTime;
+
+    @Schema(description = "交强险保费")
+    private BigDecimal jqPremium;
+
+    @Schema(description = "商业险保费")
+    private BigDecimal syPremium;
+
+    @Schema(description = "驾意险保费")
+    private BigDecimal jyPremium;
+
+    @Schema(description = "总保费")
+    private BigDecimal sumPremium;
+
+    @Schema(description = "审核时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime auditTime;
+
+    @Schema(description = "审核人")
+    private String auditUser;
+
+    @Schema(description = "驳回原因")
+    private String refuse;
+
+
+}

+ 9 - 0
commons/src/main/java/com/jzg/commons/entity/quote/vo/aggregated/QuoteEchoVo.java

@@ -194,6 +194,15 @@ public class QuoteEchoVo extends QuoteVo {
      */
     private PtlAgreementCostRatioVo costRatio;
 
+    /**
+     * 录入状态 1 车险录入 2 待客录单 3 外部订单
+     */
+    private Integer entryStatus;
+
+    /**
+     * 费用审核状态0未审核 1审核通过 2.审核不通过
+     */
+    private Integer auditStatus;
 
     /**
      * 订单数据库查询数据转 QuoteVo对象

+ 4 - 0
commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsOrdersVo.java

@@ -44,6 +44,10 @@ public class InsOrdersVo extends QuoteVo {
     @Schema(description = "审核状态")
     private byte auditStatus;
 
+    @Schema(description = "录入状态 1 车险录入 2 待客录单 3 外部订单")
+    private byte entryStatus;
+
+
     @Schema(description = "审核内容")
     private String auditComments;
 

+ 2 - 1
commons/src/main/java/com/jzg/commons/entity/vo/OrdersTrackVo.java

@@ -2,12 +2,13 @@ package com.jzg.commons.entity.vo;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.jzg.commons.core.base.BaseModel;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 @Data
 @Schema(description = "订单轨迹列表VO")
-public class OrdersTrackVo {
+public class OrdersTrackVo extends BaseModel {
 
     @Schema(description = "轨迹ID")
     private String id;

+ 36 - 0
commons/src/main/java/com/jzg/commons/util/Base64Convert.java

@@ -0,0 +1,36 @@
+package com.jzg.commons.util;
+
+import org.apache.commons.codec.binary.Base64;
+
+/**
+ *  @version  将字节流转换为Base64字符串。
+ *  解决使用jdk的base64转码打包错误的问题
+ *  处理平安保单文件加密预览
+ *  @author: hxl
+ *  @Date: 2024/4/2 14:32
+ *  @Description:
+ */
+public class Base64Convert {
+
+    /**
+     * 将字节流转换为Base64字符串。
+     * @param data 字节流数据
+     * @return Base64编码后的字符串
+     */
+    public static String byteToBase64(byte[] data) {
+        return Base64.encodeBase64String(data);
+    }
+
+    /**
+    * @Description 将base64为字符串转为字节数组
+    * @Author  hxl
+    * @Date   2024/4/2 16:28
+    * @Param
+    * @Return
+    * @Exception
+    *
+    */
+    public static byte[] encodeToString(String base64Str) {
+        return Base64.decodeBase64(base64Str);
+    }
+}

+ 209 - 0
commons/src/main/java/com/jzg/commons/util/CompressUtil.java

@@ -0,0 +1,209 @@
+package com.jzg.commons.util;
+
+import lombok.extern.slf4j.Slf4j;
+import net.lingala.zip4j.core.ZipFile;
+import net.lingala.zip4j.exception.ZipException;
+import net.lingala.zip4j.model.FileHeader;
+import net.lingala.zip4j.model.ZipParameters;
+import net.lingala.zip4j.util.Zip4jConstants;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * @Author CXP
+ * @Date 2023/11/9 11:18
+ */
+@Slf4j
+public class CompressUtil {
+
+
+    /**
+     * GZip 解压缩
+     *
+     * @param byteArray GZip格式的压缩字节数组
+     * @return 解压缩后的字符串结果
+     */
+    public static String unCompress(byte[] byteArray) {
+        if (byteArray == null || byteArray.length == 0) {
+            return null;
+        }
+        String unCompressString = null;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ByteArrayInputStream in = new ByteArrayInputStream(byteArray);
+        try {
+            GZIPInputStream gzip = new GZIPInputStream(in);
+            byte[] buffer = new byte[256];
+            int n;
+            while ((n = gzip.read(buffer)) >= 0) {
+                out.write(buffer, 0, n);
+            }
+            unCompressString = out.toString();
+            gzip.close();
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        } finally {
+            try {
+                out.close();
+                in.close();
+            } catch (IOException e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        return unCompressString;
+    }
+
+    /**
+     * 使用给定密码压缩指定文件或文件夹到指定位置.
+     * <p>
+     * dest可传最终压缩文件存放的绝对路径,也可以传存放目录,也可以传null或者""
+     * 如果传null或者""则将压缩文件存放在当前目录,即跟源文件同目录,压缩文件名取源文件名,以.zip为后缀;
+     * 如果以路径分隔符(File.separator)结尾,则视为目录,压缩文件名取源文件名,以.zip为后缀,否则视为文件名.
+     *
+     * @param src         要压缩的文件或文件夹路径
+     * @param dest        压缩文件存放路径
+     * @param isCreateDir 是否在压缩文件里创建目录,仅在压缩文件为目录时有效.
+     *                    如果为false,将直接压缩目录下文件到压缩文件.
+     * @param passwd      压缩使用的密码
+     * @return 最终的压缩文件存放的绝对路径, 如果为null则说明压缩失败.
+     */
+    public static String zip(String src, String dest, boolean isCreateDir, String passwd) {
+        File srcFile = new File(src);
+        dest = buildDestinationZipFilePath(srcFile, dest);
+        ZipParameters parameters = new ZipParameters();
+        // 压缩方式
+        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
+        // 压缩级别
+        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
+        if (!StringUtils.isEmpty(passwd)) {
+            parameters.setEncryptFiles(true);
+            // 加密方式
+            parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
+            parameters.setPassword(passwd.toCharArray());
+        }
+        try {
+            ZipFile zipFile = new ZipFile(dest);
+            if (srcFile.isDirectory()) {
+                // 如果不创建目录的话,将直接把给定目录下的文件压缩到压缩文件,即没有目录结构
+                if (!isCreateDir) {
+                    File[] subFiles = srcFile.listFiles();
+                    ArrayList<File> temp = new ArrayList<File>();
+                    Collections.addAll(temp, subFiles);
+                    zipFile.addFiles(temp, parameters);
+                    return dest;
+                }
+                zipFile.addFolder(srcFile, parameters);
+            } else {
+                zipFile.addFile(srcFile, parameters);
+            }
+            return dest;
+        } catch (ZipException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * @param source   原始文件路径
+     * @param dest     解压路径
+     * @param password 解压文件密码(可以为空)
+     */
+    public static void unZip(String source, String dest, String password, String fileName, String licensePlate,Boolean isBz) {
+        try {
+            File zipFile = new File(source);
+            // 首先创建ZipFile指向磁盘上的.zip文件
+            ZipFile zFile = new ZipFile(zipFile);
+            zFile.setFileNameCharset("UTF-8");
+            File destDir = new File(dest);
+            if (!destDir.exists()) {
+                destDir.mkdirs();
+            }
+            if (zFile.isEncrypted()) {
+                // 设置密码
+                zFile.setPassword(password.toCharArray());
+            }
+            // 将文件抽出到解压目录(解压)
+            zFile.extractAll(dest);
+            List<FileHeader> headerList = zFile.getFileHeaders();
+            List<File> extractedFileList = new ArrayList<File>();
+            for (FileHeader fileHeader : headerList) {
+                if (!fileHeader.isDirectory()) {
+                    extractedFileList.add(new File(destDir, fileHeader.getFileName()));
+                }
+            }
+            File[] extractedFiles = new File[extractedFileList.size()];
+            extractedFileList.toArray(extractedFiles);
+            extractedFileList = extractedFileList.stream().filter(x->{
+                if(isBz) {
+                    return x.getName().contains("_bz");
+                }else{
+                    return !x.getName().contains("_bz");
+                }
+            }).collect(Collectors.toList());
+            for (File f : extractedFileList) {
+                f.renameTo(new File(dest + fileName));
+                System.out.println(f.getAbsolutePath() + "文件解压成功!");
+            }
+            zipFile.delete();
+        } catch (ZipException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 构建压缩文件存放路径,如果不存在将会创建
+     * 传入的可能是文件名或者目录,也可能不传,此方法用以转换最终压缩文件的存放路径
+     *
+     * @param srcFile   源文件
+     * @param destParam 压缩目标路径
+     * @return 正确的压缩文件存放路径
+     */
+    private static String buildDestinationZipFilePath(File srcFile, String destParam) {
+        if (StringUtils.isEmpty(destParam)) {
+            if (srcFile.isDirectory()) {
+                destParam = srcFile.getParent() + File.separator + srcFile.getName() + ".zip";
+            } else {
+                String fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
+                destParam = srcFile.getParent() + File.separator + fileName + ".zip";
+            }
+        } else {
+            // 在指定路径不存在的情况下将其创建出来
+            createDestDirectoryIfNecessary(destParam);
+            if (destParam.endsWith(File.separator)) {
+                String fileName = "";
+                if (srcFile.isDirectory()) {
+                    fileName = srcFile.getName();
+                } else {
+                    fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf("."));
+                }
+                destParam += fileName + ".zip";
+            }
+        }
+        return destParam;
+    }
+
+    /**
+     * 在必要的情况下创建压缩文件存放目录,比如指定的存放路径并没有被创建
+     *
+     * @param destParam 指定的存放路径,有可能该路径并没有被创建
+     */
+    private static void createDestDirectoryIfNecessary(String destParam) {
+        File destDir = null;
+        if (destParam.endsWith(File.separator)) {
+            destDir = new File(destParam);
+        } else {
+            destDir = new File(destParam.substring(0, destParam.lastIndexOf(File.separator)));
+        }
+        if (!destDir.exists()) {
+            destDir.mkdirs();
+        }
+    }
+}

+ 340 - 0
commons/src/main/java/com/jzg/commons/util/FileUtil.java

@@ -0,0 +1,340 @@
+package com.jzg.commons.util;
+
+import com.jzg.commons.util.http.HttpUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URLEncoder;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 文件读取工具类
+ */
+@Slf4j
+public class FileUtil {
+
+    /**
+     * 读取文件内容,作为字符串返回
+     */
+    public static String readFileAsString(String filePath) throws IOException {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new FileNotFoundException(filePath);
+        }
+
+        if (file.length() > 1024 * 1024 * 1024) {
+            throw new IOException("File is too large");
+        }
+
+        StringBuilder sb = new StringBuilder((int) (file.length()));
+        // 创建字节输入流
+        FileInputStream fis = new FileInputStream(filePath);
+        // 创建一个长度为10240的Buffer
+        byte[] bbuf = new byte[10240];
+        // 用于保存实际读取的字节数
+        int hasRead = 0;
+        while ((hasRead = fis.read(bbuf)) > 0) {
+            sb.append(new String(bbuf, 0, hasRead));
+        }
+        fis.close();
+        return sb.toString();
+    }
+
+    /**
+     * 根据文件路径读取byte[] 数组
+     */
+    public static byte[] readFileByBytes(String filePath) throws IOException {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            throw new FileNotFoundException(filePath);
+        } else {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length());
+            BufferedInputStream in = null;
+
+            try {
+                in = new BufferedInputStream(new FileInputStream(file));
+                short bufSize = 1024;
+                byte[] buffer = new byte[bufSize];
+                int len1;
+                while (-1 != (len1 = in.read(buffer, 0, bufSize))) {
+                    bos.write(buffer, 0, len1);
+                }
+
+                byte[] var7 = bos.toByteArray();
+                return var7;
+            } finally {
+                try {
+                    if (in != null) {
+                        in.close();
+                    }
+                } catch (IOException var14) {
+                    var14.printStackTrace();
+                }
+
+                bos.close();
+            }
+        }
+    }
+
+
+    /**
+     * 网络url转文件
+     *
+     * @param url     保司返回的保单地址
+     * @param dir     目录 杠结束  carInsPolicy/
+     * @param path    文件真实目录 D:/upload/
+     * @param showUrl 展示地址 http://sxzgkj.baoxianzhanggui.com/web-api/晋A12345/晋A12345-交强险保单.pdf
+     *                修改   以车牌生成的保单会覆盖,同一个车牌每年会生成一个保单
+     *                展示地址 http://sxzgkj.baoxianzhanggui.com/web-api/子订单号/子订单号-车牌号-保单号-交强险保单.pdf
+     * @author: lig
+     * @date: 2023年09月21日 0021
+     */
+    public static String netUrlToFile(String url, String dir, String fileName, String path, String showUrl) {
+//        String s = "http://eserviceinterface.ciitc.com.cn/ePolicyServices/insurancePolicy.do?downFiles=key&amp&pkid=a7370fea493945868b8ca847d3ef9d9e";
+//        String path = "D:/upload/";
+//        String dir = "carInsPolicy/";
+        if (StringUtils.isEmpty(url)) return "";
+        String showPath = String.format("%s%s%s", showUrl, dir, fileName);
+        String uploadPath = path + dir;
+
+        try {
+
+            //存在
+            File existFile = new File(uploadPath + fileName);
+            if (existFile.exists()) {
+                log.error("存在的文件:" + existFile.getPath());
+                log.error("存在的文件的展示地址:" + showPath);
+                return showPath;
+            }
+
+            File folder = new File(uploadPath);
+            if (!folder.isDirectory()) {
+                folder.mkdirs();
+            }
+
+            String encodeUrl = urlEncodeChinese(url);
+            URI u = URI.create(encodeUrl);
+            InputStream inputStream = u.toURL().openStream();
+            File file = new File(uploadPath + fileName);
+            copyInputStreamToFile(inputStream, file);
+
+            log.error("文件路径:" + file.getPath());
+            return showPath;
+
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+
+
+    /**
+     * 文件存在
+     *
+     * @param dir     目录 杠结束  carInsPolicy/
+     * @param path    文件真实目录 D:/upload/
+     * @param showUrl 展示地址 http://sxzgkj.baoxianzhanggui.com/web-api/晋A12345/晋A12345-交强险保单.pdf
+     * @author: lig
+     * @date: 2023年09月21日 0021
+     */
+    public static String fileExist(String dir, String fileName, String path, String showUrl) {
+        String showPath = String.format("%s%s%s", showUrl, dir, fileName);
+        String uploadPath = path + dir;
+
+
+        //存在
+        File existFile = new File(uploadPath + fileName);
+        if (existFile.exists()) {
+            log.error("存在的文件:" + existFile.getPath());
+            log.error("存在的文件的展示地址:" + showPath);
+            return showPath;
+        }
+        return "";
+
+
+    }
+
+
+    // InputStream -> File
+    public static void copyInputStreamToFile(InputStream inputStream, File file)
+            throws IOException {
+
+        try (FileOutputStream outputStream = new FileOutputStream(file)) {
+
+            int read;
+            byte[] bytes = new byte[1024];
+
+            while ((read = inputStream.read(bytes)) != -1) {
+                outputStream.write(bytes, 0, read);
+            }
+
+            // commons-io
+            //IOUtils.copy(inputStream, outputStream);
+
+        }
+
+    }
+
+    public static String netUrlStoreToLocal(String url, String dir, String fileName, String path, String showUrl, String password,String licensePlate,Boolean isBz) {
+        if (StringUtils.isEmpty(url)) return "";
+        String showPath = String.format("%s%s%s", showUrl, dir, fileName);
+        String uploadPath = path + dir;
+
+        try {
+
+            //存在
+            File existFile = new File(uploadPath + fileName);
+            if (existFile.exists()) {
+                log.error("存在的文件:" + existFile.getPath());
+                log.error("存在的文件的展示地址:" + showPath);
+                return showPath;
+            }
+
+            File folder = new File(uploadPath);
+            if (!folder.isDirectory()) {
+                folder.mkdirs();
+            }
+
+            URI u = URI.create(url);
+            InputStream inputStream = u.toURL().openStream();
+            File file = new File(uploadPath + licensePlate + ".zip");
+            copyInputStreamToFile(inputStream, file);
+
+            CompressUtil.unZip(file.getPath(), uploadPath, password, fileName, licensePlate,isBz);
+            file.delete();
+            return showPath;
+
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    /**
+     * 将 url 中的 中文转码
+     *
+     * @param url url链接
+     * @return 转码后的url
+     */
+    public static String urlEncodeChinese(String url) {
+        try {
+            Matcher matcher = Pattern.compile("[\\u4e00-\\u9fa5]").matcher(url);
+            String tmp;
+            while (matcher.find()) {
+                tmp = matcher.group();
+                url = url.replaceAll(tmp, URLEncoder.encode(tmp, "UTF-8"));
+            }
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return url;
+    }
+
+    /**
+     * 网络url转文件
+     *
+     * @param url     保司返回的保单地址
+     * @param dir     目录 杠结束  carInsPolicy/
+     * @param path    文件真实目录 D:/upload/
+     * @param showUrl 展示地址 http://sxzgkj.baoxianzhanggui.com/web-api/晋A12345/晋A12345-交强险保单.pdf
+     *                修改   以车牌生成的保单会覆盖,同一个车牌每年会生成一个保单
+     *                展示地址 http://sxzgkj.baoxianzhanggui.com/web-api/子订单号/子订单号-车牌号-保单号-交强险保单.pdf
+     * @author: lig
+     * @date: 2023年09月21日 0021
+     */
+    public static String netUrlToFileNew(String url, String dir, String fileName, String path, String showUrl,boolean flag) {
+//        String s = "http://eserviceinterface.ciitc.com.cn/ePolicyServices/insurancePolicy.do?downFiles=key&amp&pkid=a7370fea493945868b8ca847d3ef9d9e";
+//        String path = "D:/upload/";
+//        String dir = "carInsPolicy/";
+        if (StringUtils.isEmpty(url)) return "";
+        String showPath = String.format("%s%s%s", showUrl, dir, fileName);
+        String uploadPath = path + dir;
+
+        try {
+
+            //存在
+            File existFile = new File(uploadPath + fileName);
+            if (existFile.exists()) {
+                if(!flag){
+                    log.error("存在的文件:" + existFile.getPath());
+                    log.error("存在的文件的展示地址:" + showPath);
+                    return showPath;
+                }else{
+                    //刪除重新生成
+                    existFile.delete();
+                    existFile = new File(uploadPath + fileName);
+                }
+            }
+
+            File folder = new File(uploadPath);
+            if (!folder.isDirectory()) {
+                folder.mkdirs();
+            }
+
+            String encodeUrl = urlEncodeChinese(url);
+            URI u = URI.create(encodeUrl);
+            HttpUtils.disableSSLCertificateChecking();
+            InputStream inputStream = u.toURL().openStream();
+            File file = new File(uploadPath + fileName);
+            copyInputStreamToFile(inputStream, file);
+
+            log.error("文件路径:" + file.getPath());
+            return showPath;
+
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    public static String netUrlStoreToLocalNew(String url, String dir, String fileName, String path, String showUrl, String password,String licensePlate,boolean flag,Boolean isBz) {
+        if (StringUtils.isEmpty(url)){ return "";}
+        String showPath = String.format("%s%s%s", showUrl, dir, fileName);
+        String uploadPath = path + dir;
+        try {
+
+            //存在
+            File existFile = new File(uploadPath + fileName);
+            if (existFile.exists()) {
+                if(!flag){
+                    log.error("存在的文件:" + existFile.getPath());
+                    log.error("存在的文件的展示地址:" + showPath);
+                    return showPath;
+                }else{
+                    //刪除重新生成
+                    existFile.delete();
+                    existFile = new File(uploadPath + fileName);
+                }
+            }
+
+            File folder = new File(uploadPath);
+            if (!folder.isDirectory()) {
+                folder.mkdirs();
+            }
+
+            URI u = URI.create(url);
+            InputStream inputStream = u.toURL().openStream();
+            File file = new File(uploadPath + licensePlate + ".zip");
+            copyInputStreamToFile(inputStream, file);
+
+            CompressUtil.unZip(file.getPath(), uploadPath, password, fileName, licensePlate,isBz);
+            file.delete();
+            return showPath;
+
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+    }
+}

+ 678 - 0
commons/src/main/java/com/jzg/commons/util/PDFUtil.java

@@ -0,0 +1,678 @@
+package com.jzg.commons.util;
+
+import com.jzg.commons.constants.quote.enums.base.InsuranceEnum;
+import com.jzg.commons.util.http.HttpUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.text.PDFTextStripper;
+import org.slf4j.Logger;
+
+import java.io.*;
+import java.net.URI;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ *  @version
+ *  @author: hxl
+ *  @Date: 2024/3/27 17:24
+ *  @Description: pdf解密
+ */
+@Slf4j
+public class PDFUtil {
+
+
+    /**
+     * 解除PDF口令
+     * @param filePath
+     * @throws IOException
+     */
+    public static void decipher(String filePath,String password) throws IOException {
+
+        File encryptFile = new File(filePath);
+        String parentPath = encryptFile.getParent();
+        String name = encryptFile.getName();
+        String fileName = name.split("\\.")[0] + "-decipher.pdf";
+        //PDDocument load = PDDocument.load(encryptFile, password);
+        //load.setAllSecurityToBeRemoved(true);
+        //String decodeFilePath = parentPath + File.separator+fileName;
+       // load.save(decodeFilePath);
+       // load.close();
+    }
+
+    /**
+     * 将base64编码转换成PDF
+     * @param base64sString
+     * @param filePath
+     *    
+     */
+    public static void base64StringToPDF(String base64sString, String filePath) {
+        BufferedInputStream bin = null;
+        FileOutputStream fout = null;
+        BufferedOutputStream bout = null;
+        try {
+            //将base64编码的字符串解码成字节数组
+            byte[] bytes = Base64Convert.encodeToString(base64sString);
+            //创建一个将bytes作为其缓冲区的ByteArrayInputStream对象
+            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+            //创建从底层输入流中读取数据的缓冲输入流对象
+            bin = new BufferedInputStream(bais);
+            //指定输出的文件
+            File file = new File(filePath);
+            File parentDir = file.getParentFile();
+            if (!parentDir.exists()) {
+                parentDir.mkdirs();
+            }
+            //创建到指定文件的输出流
+            fout = new FileOutputStream(file);
+            //为文件输出流对接缓冲输出流对象
+            bout = new BufferedOutputStream(fout);
+            byte[] buffers = new byte[1024];
+            int len = bin.read(buffers);
+            while (len != -1) {
+                bout.write(buffers, 0, len);
+                len = bin.read(buffers);
+            }
+            //刷新此输出流并强制写出所有缓冲的输出字节,必须这行代码,否则有可能有问题
+            bout.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }  finally {
+            try {
+                bin.close();
+                fout.close();
+                bout.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+        *  将PDF转换成base64编码
+        *  @param filePath
+        * */
+    public static String getPDFBinary(String filePath) {
+        System.out.println("加密PDF路径:" + filePath);
+        FileInputStream fin =null;
+        BufferedInputStream bin =null;
+        ByteArrayOutputStream baos = null;
+        BufferedOutputStream bout =null;
+        File encriptPath = new File(filePath);
+        try {
+            //建立读取文件的文件输出流
+            fin = new FileInputStream(encriptPath);
+            //在文件输出流上安装节点流(更大效率读取)
+            bin = new BufferedInputStream(fin);
+            // 创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量
+            baos = new ByteArrayOutputStream();
+            //创建一个新的缓冲输出流,以将数据写入指定的底层输出流
+            bout = new BufferedOutputStream(baos);
+            byte[] buffer = new byte[1024];
+            int len = bin.read(buffer);
+            while(len != -1){
+                bout.write(buffer, 0, len);
+                len = bin.read(buffer);
+            }
+            //刷新此输出流并强制写出所有缓冲的输出字节,必须这行代码,否则有可能有问题
+            bout.flush();
+            byte[] bytes = baos.toByteArray();
+        //    return encoder.encodeBuffer(bytes).trim();
+            return Base64Convert.byteToBase64(bytes);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }finally{
+            try {
+                fin.close();
+                bin.close();
+                bout.close();
+//              deleteDir(encriptPath.getParent());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+    /**
+    * @Description
+    * @Author  hxl
+    * @Date   2024/4/2 15:02
+    * @Param  encryptPdfStr  待解密的base64字符串
+     * @Param  targetPath  输出路径
+     * @Param  password  密钥
+    * @Return
+    * @Exception
+    *
+    */
+    public static void decryptFileByPassword(String encryptPdfStr, String targetPath, String password) throws IOException {
+        /**
+         * base64字符转换PDF
+         */
+        base64StringToPDF(encryptPdfStr,targetPath);
+        /**
+         * 解除PDF口令
+         */
+        decipher(targetPath,password);
+    }
+
+    public static String getPdfText(String pdfFilePath) {
+        PDDocument document = null;
+        String text ="";
+        try {
+            document = PDDocument.load(new File(pdfFilePath));
+            PDFTextStripper pdfStripper = new PDFTextStripper();
+            pdfStripper.setSortByPosition(true); // 设置为true以按照文档中的顺序提取文本
+            pdfStripper.setShouldSeparateByBeads(true);
+            text= pdfStripper.getText(document);
+            text = text.replaceAll("\\s+", " ");
+            log.info(text);
+            document.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+       return text;
+    }
+
+    public static String getPdfContentStr(String pdfText, String beginStr,String endStr,String dateType) {
+        if("end".equals(endStr)){
+            return getEndString(pdfText, beginStr);
+        }
+        String contentStr = getContentStr(pdfText, beginStr, endStr);
+        if(StringUtils.isNotBlank(contentStr)){
+            contentStr=contentStr.replaceAll(" ", "");
+            contentStr=contentStr.replaceAll("\\n+", "");
+            contentStr=contentStr.replaceAll("\\t+", "");
+            contentStr=contentStr.replaceAll("\\r+", "");
+            contentStr = contentStr.replaceAll("\\s+", "");
+            contentStr = contentStr.replaceAll("[^\u4E00-\u9FA50-9年月日:-]+", "");
+            contentStr = contentStr.replaceAll("时", "");
+            String longestRepeat = getRepeatedData(contentStr);
+            if(StringUtils.isNotBlank(longestRepeat)){
+                contentStr = longestRepeat;
+            }
+        }
+        return contentStr;
+    }
+
+    public static LocalDateTime getPdfContentDate(String pdfText, String beginStr,String endStr,String dateType) {
+        if("end".equals(endStr)){
+            String substring = getEndString(pdfText, beginStr);
+            String patten ="";
+            if("1".equals(dateType)){
+                patten ="yyyy-MM-dd HH:mm:ss";
+            }else if("2".equals(dateType)){
+                patten = "yyyy/MM/dd HH:mm:ss";
+            }else if("3".equals(dateType)){
+                patten = "yyyy年MM月dd日 HH:mm:ss";
+            }
+            return LocalDateTime.parse(substring, DateTimeFormatter.ofPattern(patten));
+        }
+        String payDate = getContentStr(pdfText, beginStr, endStr);
+        LocalDateTime payDateTime = null;
+        if("1".equals(dateType)){
+            payDateTime = getStringTranferDate(payDate);
+        }else if("2".equals(dateType)){
+            payDateTime = getStringTranferDateCPIC(payDate);
+        }else if("3".equals(dateType)){
+            payDateTime = getStringTranferDatePinAn(payDate);
+        }
+        return payDateTime;
+    }
+    /**
+     *  @version
+     *  @author: hxl
+     *  @Date: 2024/10/23 9:26
+     *  @Description: 截取开始到字符串结尾的字符
+     */
+    private static String getEndString(String pdfText, String beginStr) {
+        String substring = pdfText.substring(pdfText.indexOf(beginStr), pdfText.length());
+        substring=substring.replaceAll(beginStr, "");
+        substring=substring.replaceAll(beginStr, "");
+        substring = substring.replaceAll(" ", "");
+        substring = substring.replaceAll("\\n+", "");
+        substring = substring.replaceAll("\\t+", "");
+        substring = substring.replaceAll("\\r+", "");
+        substring = substring.replaceAll("\\s+", "");
+        if(substring.length() == 18){
+            substring = substring.substring(0,10)+" "+ substring.substring(10,18);
+        }else if(substring.length() == 15){
+            substring = substring.substring(0,10)+" "+ substring.substring(10,15)+":00";
+        }else if(substring.length() == 10){
+            substring = substring+" 00:00:00";
+        }
+        return substring;
+    }
+
+    public static HashMap<String,LocalDateTime> getPdfContent(String pdfPath, String companyId){
+        HashMap<String,LocalDateTime>  map =new  HashMap<String,LocalDateTime>();
+        String pdfText = getPdfText(pdfPath);
+        System.out.println(pdfText);
+        String payDate=null;
+        String signDate=null;
+        if(StringUtils.isNotBlank(pdfText)){
+            //缴费时间、签单时间 payDate signingTime
+            //中煤  ===================== 11
+           if(companyId.contains(InsuranceEnum.ZMBX.getCode())){
+               payDate = getContentStr(pdfText, "收付确认时间:", "保单生成时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           //永诚 ----------------------------11
+           }else if(companyId.contains(InsuranceEnum.AICS.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "电子保单生成时间");
+               //payDate = getContentStr(pdfText, "收费确认时间:", "业 电子保单生成时间:");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           //安盛  ================================11
+           }else if(companyId.contains(InsuranceEnum.TPBX.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间", "微信二维码");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           //恒邦    ====================   11
+           }else if(companyId.contains(InsuranceEnum.HBIC.getCode())){
+               payDate = getContentStr(pdfText, "保费确认时间:", "保单打印时间");
+               signDate = getContentStr(pdfText, "签单日期:", "核保");
+           }
+           //国任   =========================  11
+           else if(companyId.contains(InsuranceEnum.XDCX.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "核保");
+           }
+           //平安 =================================33
+           else if(companyId.contains(InsuranceEnum.PAIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           // 华农   ============================1.1
+           else if(companyId.contains(InsuranceEnum.HNIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "有效保单生成时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+
+           // 华泰   ============================  1  1
+           else if(companyId.contains(InsuranceEnum.HTIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "有效保单生成时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           // 众安   ================================ 2.2
+           else if(companyId.contains(InsuranceEnum.ZAPA.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //诚泰    ========================   1.2
+           else if(companyId.contains(InsuranceEnum.CHAC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //大家   ======================   111
+           else if(companyId.contains(InsuranceEnum.DJPC.getCode())){
+               payDate = getContentStr(pdfText, "收付确认时间:", "投保确认码");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //泰康   =================================   1.2
+           else if(companyId.contains(InsuranceEnum.TKIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认码");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //紫金   =============================   1.1
+           else if(companyId.contains(InsuranceEnum.ZKIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "确认码");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //渤海  ===========================  11
+           else if(companyId.contains(InsuranceEnum.BPIC.getCode())){
+               payDate = getContentStr(pdfText, "收款确认时间:", "投保确认码");
+               signDate = getContentStr(pdfText, "签单日期:", "核保");
+           }
+           //太平   ===================   1.2
+           else if(companyId.contains(InsuranceEnum.TPIC.getCode())){
+               payDate = getContentStr(pdfText, "保费确认时间:", "确认码");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //天安   ==============================1.1
+           else if(companyId.contains(InsuranceEnum.TAIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "生成保单时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //人保 ================================1.1
+           else if(companyId.contains(InsuranceEnum.PICC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //人寿   ===========================1 ,2
+           else if(companyId.contains(InsuranceEnum.GPIC.getCode())){
+               payDate = getContentStr(pdfText, "收付确认时间:", "保单打印时间");
+               signDate = getContentStr(pdfText, "签单日期:", "保险人签章");
+           }
+
+           //阳光  ===========================  11
+           else if(companyId.contains(InsuranceEnum.YGBX.getCode())){
+               payDate = getContentStr(pdfText, "收款确认:", "电子保单流水号");
+               signDate = getContentStr(pdfText, "签单日期:", "经办");
+           }
+
+           //太平洋  ================================2.2
+           else if(companyId.contains(InsuranceEnum.CPIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "保单生成时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+            // 泰山   =========================  1.1
+           else if(companyId.contains(InsuranceEnum.TSBX.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "保单生成时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           //中华  ============================  3.1
+           else if(companyId.contains(InsuranceEnum.CICP.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "核保");
+           }
+
+           // 华安  ===================   1.1
+           else if(companyId.contains(InsuranceEnum.HAIC.getCode())){
+               payDate = getContentStr(pdfText, "收费时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           // 大地  ===========================1.1
+           else if(companyId.contains(InsuranceEnum.CCIC.getCode())){
+               payDate = getContentStr(pdfText, "收费确认时间:", "投保确认时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+           // 安诚 ======================  1.3
+           else if(companyId.contains(InsuranceEnum.ACIC.getCode())){
+               payDate = getContentStr(pdfText, "缴费确认时间:", "保单生成时间");
+               signDate = getContentStr(pdfText, "签单日期:", "(保");
+           }
+           // 永安   ===============================  11
+           else if(companyId.contains(InsuranceEnum.YAIC.getCode())){
+               payDate = getContentStr(pdfText, "支付确认时间:", "投保确认码");
+               signDate = getContentStr(pdfText, "签单日期:", "(保险人签章)");
+           }
+        }
+        LocalDateTime payDateTime = null;
+        LocalDateTime signDateTime = null;
+        if(companyId.contains(InsuranceEnum.PAIC.getCode()) || companyId.contains(InsuranceEnum.ZAPA.getCode())){
+            payDateTime = getStringTranferDatePinAn(payDate);
+            signDateTime = getStringTranferDatePinAn(signDate);
+        }else if(companyId.contains(InsuranceEnum.CHAC.getCode()) || companyId.contains(InsuranceEnum.TKIC.getCode()) || companyId.contains(InsuranceEnum.TPIC.getCode())
+         || companyId.contains(InsuranceEnum.GPIC.getCode()) || companyId.contains(InsuranceEnum.ACIC.getCode())){
+            payDateTime = getStringTranferDate(payDate);
+            signDateTime = getStringTranferDatePinAn(signDate);
+        }else if(companyId.contains(InsuranceEnum.CPIC.getCode())){
+            payDateTime = getStringTranferDateCPIC(payDate);
+            signDateTime = getStringTranferDateCPIC(signDate);
+        }else if(companyId.contains(InsuranceEnum.CICP.getCode())){
+            payDateTime = getStringTranferDatePinAn(payDate);
+            signDateTime = getStringTranferDate(signDate);
+        }
+        else{
+            payDateTime = getStringTranferDate(payDate);
+            signDateTime = getStringTranferDate(signDate);
+        }
+
+        map.put("payDate",payDateTime);
+        map.put("signDate",signDateTime);
+        return map;
+    }
+    private static LocalDateTime getStringTranferDateCPIC(String payDate) {
+        if (StringUtils.isNotBlank(payDate)) {
+            payDate = payDate.replaceAll(" ", "");
+            payDate = payDate.replaceAll("\\n+", "");
+            payDate = payDate.replaceAll("\\t+", "");
+            payDate = payDate.replaceAll("\\r+", "");
+            payDate = payDate.replaceAll("\\s+", "");
+            payDate = payDate.replaceAll("[\u4e00-\u9fa5]", "");
+            System.out.println(payDate.length());
+            if (payDate.length() == 18) {
+                payDate = payDate.substring(0, 10) + " " + payDate.substring(10, 18);
+            } else if (payDate.length() == 15) {
+                payDate = payDate.substring(0, 10) + " " + payDate.substring(10, 15) + ":00";
+            } else if (payDate.length() == 10) {
+                payDate = payDate + " 00:00:00";
+            }
+            return LocalDateTime.parse(payDate, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
+        }
+        return null;
+    }
+    private static LocalDateTime getStringTranferDate(String payDate) {
+        if(StringUtils.isNotBlank(payDate)){
+            payDate=payDate.replaceAll(" ", "");
+            payDate=payDate.replaceAll("\\n+", "");
+            payDate=payDate.replaceAll("\\t+", "");
+            payDate=payDate.replaceAll("\\r+", "");
+            payDate = payDate.replaceAll("\\s+", "");
+            payDate = payDate.replaceAll("[\u4e00-\u9fa5]", "");
+            System.out.println(payDate.length());
+            if(payDate.length() == 18){
+                payDate = payDate.substring(0,10)+" "+ payDate.substring(10,18);
+            }else if(payDate.length() == 15){
+                    payDate = payDate.substring(0,10)+" "+ payDate.substring(10,15)+":00";
+            }else if(payDate.length() == 10){
+                payDate = payDate+" 00:00:00";
+            }
+            return LocalDateTime.parse(payDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        }
+        return null;
+    }
+
+    private static LocalDateTime getStringTranferDatePinAn(String payDate) {
+        if(StringUtils.isNotBlank(payDate)){
+            payDate=payDate.replaceAll(" ", "");
+            payDate=payDate.replaceAll("\\n+", "");
+            payDate=payDate.replaceAll("\\t+", "");
+            payDate=payDate.replaceAll("\\r+", "");
+            payDate = payDate.replaceAll("\\s+", "");
+            payDate = payDate.replaceAll("[^\u4E00-\u9FA50-9年月日:]+", "");
+            payDate = payDate.replaceAll("时", "");
+            String longestRepeat = getRepeatedData(payDate);
+            if(StringUtils.isNotBlank(longestRepeat)){
+                payDate = longestRepeat;
+            }
+            int count = 0;
+            int index = 0;
+            while ((index = payDate.indexOf(":", index)) != -1) {
+                index += ":".length();
+                count++;
+            }
+            System.out.println(payDate.length());
+            if((payDate.length() == 17 && count==2 ) || (payDate.length() == 18 && count==2 ) || ( payDate.length() == 19 && count==2 ) ) {
+                String minnute = payDate.substring(payDate.indexOf("日") + 1, payDate.length());
+                String day = payDate.substring(0, payDate.indexOf("日") + 1);
+                payDate = getContentStr(day) + " " + minnute;
+            }else if((payDate.length() == 14 && count==1 ) || ( payDate.length() == 15 && count==1 ) || ( payDate.length() == 16 && count==1 )){
+                String minnute = payDate.substring(payDate.indexOf("日")+1, payDate.length());
+                String day = payDate.substring(0, payDate.indexOf("日")+1);
+                payDate = getContentStr(day)+" "+ minnute+":00";
+            }else if(payDate.length() == 9 ||payDate.length() == 10 || payDate.length() == 11){
+                payDate = getContentStr(payDate)+" 00:00:00";
+            }
+            return LocalDateTime.parse(payDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        }
+        return null;
+    }
+
+    public static String  getContentStr(String input){
+        Pattern pattern = Pattern.compile("(\\d{4})年(\\d{1,2})月(\\d{1,2})日");
+        Matcher matcher = pattern.matcher(input);
+        if (matcher.matches()) {
+            String year = matcher.group(1);
+            String month = matcher.group(2);
+            String day = matcher.group(3);
+            return year+"-"+((Integer.parseInt(month)<10 && month.length()==1) ?"0"+month:month)+"-"+((Integer.parseInt(day)<10 && day.length()==1)  ?"0"+day:day);
+        } else {
+            return null;
+        }
+    }
+
+    public static String  getContentStr(String input, String beginStr, String endStr){
+        // 创建正则表达式,其中"(?s)"表示忽略换行符,"."匹配任何字符(包括换行符)
+        String regex = "(?s)" + Pattern.quote(beginStr) + "(.+?)" + Pattern.quote(endStr);
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(input);
+
+        if (matcher.find()) {
+            return matcher.group(1);
+        } else {
+            return null;
+        }
+    }
+    /**
+     *  @version
+     *  @author: hxl
+     *  @Date: 2024/10/22 15:08
+     *  @Description: 找出字符串中的重复值
+     */
+    private static String getRepeatedData(String input) {
+        String repeatedData = "";
+        Pattern pattern = Pattern.compile("(\\d{4}年\\d{1,2}月\\d{1,2}日)\\s*\\1");
+        Matcher matcher = pattern.matcher(input);
+        if (matcher.find()) {
+            repeatedData= matcher.group(1);
+        }
+        return repeatedData;
+    }
+    public static String trafferHttpToLocalPath(String path) {
+        if (path.contains("http") || path.contains("https")) {
+            //转成本地路径
+            String os = System.getProperty("os.name").toLowerCase();
+            String tempDir="";
+            if (os.contains("linux")) {
+                tempDir = "/tmp";
+            } else if (os.contains("windows")) {
+                tempDir = System.getProperty("java.io.tmpdir");
+            }
+            String last = path.substring(path.lastIndexOf(".") + 1);
+            File file =new File(tempDir+ UUID.randomUUID()+"."+last);
+            String encodeUrl = FileUtil.urlEncodeChinese(path);
+            URI u = URI.create(encodeUrl);
+            HttpUtils.disableSSLCertificateChecking();
+            try{
+                InputStream inputStream = u.toURL().openStream();
+                FileUtil.copyInputStreamToFile(inputStream, file);
+            }catch(Exception e){
+
+            }
+            return file.getPath();
+        } else {
+            return path;
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        //中煤
+        //String pdfFilePath = "D:\\nasData\\carInsPolicy\\晋AC692F\\晋AC692F-商业险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "ZMBX");
+        //永城
+        // String pdfFilePath = "D:\\nasData\\carInsPolicy\\1834183151125594114\\晋LD580R114B4032620240026390-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "AICS");
+        //安盛
+       // String pdfFilePath = "D:\\nasData\\carInsPolicy\\1823634528262541312\\晋JH6836-交强险保单.pdf"; // PDF文件路径
+        //  HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "TPBX");
+        //恒邦
+       // String pdfFilePath = "D:\\nasData\\carInsPolicy\\晋KLY103\\晋KLY103-交强险保单.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "HBIC");
+        //国任
+        // String pdfFilePath = "D:\\nasData\\carInsPolicy\\晋A139LV\\晋A139LV-交强险保单.pdf"; // PDF文件路径
+        //  HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "XDCX");
+        //平安
+        // String pdfFilePath = "D:\\nasData\\carInsPolicy\\晋C5523Q\\晋C5523Q-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "PAIC");
+
+        //华农
+        //String pdfFilePath = "D:\\bx\\huanong\\晋KME755-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "HNIC");
+
+        // 华泰
+        //String pdfFilePath = "D:\\bx\\huatai\\晋AH15L3-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "HTIC");
+
+        //众安
+       // String pdfFilePath = "D:\\bx\\zongan\\晋JTT447-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "ZAPA");
+
+        //诚泰
+       // String pdfFilePath = "D:\\bx\\chengtai\\晋A1WJ61-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "CHAC");
+
+        //大家
+        //String pdfFilePath = "D:\\bx\\dajia\\晋FH3550-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "DJPC");
+
+        //泰康
+        //String pdfFilePath = "D:\\bx\\taikang\\晋BB0233-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "TKIC");
+
+        //紫荆
+        //String pdfFilePath = "D:\\bx\\zijin\\晋KTY710-交强险保单.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "ZKIC");
+
+        //渤海
+       // String pdfFilePath = "D:\\bx\\bohai\\晋C1358S-2141103302024015981-交强险保单.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "BPIC");
+
+       //太平
+       // String pdfFilePath = "D:\\bx\\taiping\\63fe59c9f37a2a1ab62fe8f23f63943c.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "TPIC");
+
+        //天安
+        //String pdfFilePath = "D:\\bx\\tianan\\829d3f8efdc565b61092cc675d8ac316.pdf"; // PDF文件路径
+        //HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "TAIC");
+
+        //人民
+        //String pdfFilePath = "D:\\bx\\renbao\\b504310a9897db5be1745c76463d9e0a.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "PICC");
+
+        //人寿
+       // String pdfFilePath = "D:\\bx\\renshou\\4d36d1b7f19059ffb14a59d04ae140fb.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "GPIC");
+
+      //  String pdfFilePath = "D:\\bx\\renshou\\4d36d1b7f19059ffb14a59d04ae140fb.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "GPIC");
+
+       // String pdfFilePath = "D:\\bx\\renshou\\4d36d1b7f19059ffb14a59d04ae140fb.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "GPIC");
+
+        //阳光
+       // String pdfFilePath = "D:\\bx\\yangguang\\e364a2ea5b29b5056005c084c69fbcde.pdf"; // PDF文件路径
+       // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "YGBX");
+
+        //太平洋
+        // String pdfFilePath = "D:\\bx\\taipingyang\\31f92fc448ef7aab3127a6d7fa07621c.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "CPIC");
+
+
+        //泰山
+        // String pdfFilePath = "D:\\bx\\taishan\\2c46d1bd604efe4d1894bf826af30e0a.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "TSBX");
+
+        // String pdfFilePath = "D:\\bx\\taishan\\2c46d1bd604efe4d1894bf826af30e0a.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "TSBX");
+
+
+        //中华
+        // String pdfFilePath = "D:\\bx\\zhonghua\\e3358efb60e4924c65d28971f4a01f94.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "CICP");
+
+        // 华安
+       //  String pdfFilePath = "D:\\bx\\huaan\\9560fc38737dc922db73bf8ffaa56482.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "HAIC");
+        // 大地
+        // String pdfFilePath = "D:\\bx\\dadi\\24f9830c1807fa47ecb933b78e155ed5.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "CCIC");
+        // 安诚
+        // String pdfFilePath = "D:\\bx\\ancheng\\f0b6430219fe3f32b2d63ab41dba95c4.pdf"; // PDF文件路径
+        // HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "ACIC");
+        // 永安
+        String pdfFilePath = "D:\\bx\\yongan\\交强.pdf"; // PDF文件路径
+           HashMap<String, LocalDateTime> zmbx = getPdfContent(pdfFilePath, "YAIC");
+
+        System.out.println(zmbx.toString());
+
+    }
+
+
+
+}

+ 30 - 0
commons/src/main/java/com/jzg/commons/util/http/HttpUtils.java

@@ -12,6 +12,7 @@ import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
 import java.security.cert.X509Certificate;
 
 /**
@@ -263,4 +264,33 @@ public class HttpUtils
             return true;
         }
     }
+
+    public static void disableSSLCertificateChecking() {
+        try {
+            TrustManager[] trustAllCerts = new TrustManager[]{
+                    new X509TrustManager() {
+                        public X509Certificate[] getAcceptedIssuers() {
+                            return null;
+                        }
+                        public void checkClientTrusted(X509Certificate[] certs, String authType) {
+                        }
+                        public void checkServerTrusted(X509Certificate[] certs, String authType) {
+                        }
+                    }
+            };
+
+            SSLContext sc = SSLContext.getInstance("TLS");
+            sc.init(null, trustAllCerts, new SecureRandom());
+            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+
+            // 还需要信任主机名
+            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
+                public boolean verify(String hostname, SSLSession session) {
+                    return true;
+                }
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }

+ 1 - 1
gateway/src/main/resources/application-dev.yml

@@ -38,7 +38,7 @@ spring:
         - id: summary_route
           uri: http://localhost:9898/
           predicates:
-            - Path= /order/identify/** ,/supplementOrder/**,/order/carModel/**,/unify/**,/order/taskImages/**,/order/qrCode/**
+            - Path= /order/identify/** ,/supplementOrder/**,/order/carModel/**,/unify/**,/order/taskImages/**,/order/qrCode/**,/orderTrack/**
 
         - id: costsorrule_route
           uri: http://localhost:8085/

+ 11 - 0
platform/src/main/java/com/jzg/controller/EsmInsCompanyController.java

@@ -66,6 +66,17 @@ public class EsmInsCompanyController extends BaseController {
         return HttpResult.ok(list);
     }
 
+    /**
+     * 通过保险公司id查询下级id及本级id
+     * @return
+     */
+    @GetMapping("getChildCompanyId")
+    @Operation(summary = "通过保险公司id查询下级id及本级id")
+    public HttpResult<List<String>> getChildCompanyId(String companyId) {
+        List<String> list = esmInsCompanyService.getByLowerId(companyId);
+        return HttpResult.ok(list);
+    }
+
     @GetMapping("getAllTopCompanyList")
     @Operation(summary = "获取订单报价完成的保险公司")
     public HttpResult getAllTopCompanyList() {

+ 22 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/EsmInsCompanyClient.java

@@ -0,0 +1,22 @@
+package com.jzg.quotation.commons.client;
+
+import com.jzg.commons.core.page.HttpResult;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+@FeignClient(name="jzg-platform",url = "http://192.168.0.250:8001/")
+public interface EsmInsCompanyClient {
+
+
+    /**
+     * 通过保险公司id查询下级id及本级id
+     * @param companyId
+     * @return
+     */
+    @GetMapping("/esmInsCompany/getChildCompanyId")
+    public HttpResult<List<String>> getChildCompanyId(@RequestParam String companyId);
+
+}

+ 2 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java

@@ -19,6 +19,7 @@ import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.reflect.MethodSignature;
+import org.hibernate.validator.internal.util.stereotypes.Lazy;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.expression.EvaluationContext;
 import org.springframework.expression.ExpressionParser;
@@ -35,8 +36,8 @@ import java.util.Objects;
 @Component
 public class OrderOperationLogAspect {
 
-    public static final ExpressionParser PARSER = new SpelExpressionParser();
     @Autowired
+    @Lazy
     private InsOrdersService orderService;
 
     @Autowired

+ 137 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeAuditController.java

@@ -0,0 +1,137 @@
+package com.jzg.quotation.summary.controller;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.dto.FeeAuditAddParam;
+import com.jzg.commons.entity.dto.FeeAuditParam;
+import com.jzg.commons.entity.dto.VerifyOrderParam;
+import com.jzg.commons.entity.orders.vo.AuditCostInfoVo;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
+import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
+import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
+import com.jzg.quotation.summary.service.InsFeeAuditService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Tag(name="订单审核接口")
+@RestController
+@RequestMapping("/feeAudit")
+public class InsFeeAuditController {
+
+    @Autowired
+    private InsFeeAuditService insFeeAuditService;
+
+    /**
+     * 订单列表分页
+     * @return
+     */
+    @PostMapping("/auditList")
+    @Operation(summary = "订单审核列表分页")
+    public HttpResult auditList(@RequestBody FeeAuditParam param){
+        Page<FeeAuditVo> result = insFeeAuditService.queryPage(param);
+        return HttpResult.ok(result);
+    }
+
+    /**
+     * 订单审核详情
+     * @return
+     */
+    @GetMapping("/auditInfo")
+    @Operation(summary = "订单审核详情")
+    public HttpResult auditInfo(String orderNo){
+        QuoteEchoVo detailVo = insFeeAuditService.auditInfo(orderNo);
+        return HttpResult.ok(detailVo);
+    }
+
+    /**
+     * 判断领取按钮是否锁定
+     * @return
+     */
+    @GetMapping("/isLock")
+    @Operation(summary = "判断领取按钮是否锁定")
+    public HttpResult isLock(String orderNo){
+        return HttpResult.ok(insFeeAuditService.isLock(orderNo));
+    }
+
+    /**
+     * 领取审核订单
+     * @return
+     */
+    @PostMapping("/auditReceive")
+    @Operation(summary = "领取审核订单")
+    public HttpResult auditReceive(@RequestParam("orderNo") String orderNo){
+        insFeeAuditService.auditReceive(orderNo);
+        return HttpResult.ok();
+    }
+
+    /**
+     * 放弃审核订单
+     * @return
+     */
+    @PostMapping("/auditCancel")
+    @Operation(summary = "放弃领取审核订单")
+    public HttpResult auditCancel(@RequestParam("orderNo") String orderNo){
+        insFeeAuditService.auditCancel(orderNo);
+        return HttpResult.ok();
+    }
+
+    /**
+     * 更新签单时间
+     * @return
+     */
+    @PostMapping("/updateSigningTime")
+    @Operation(summary = "更新签单时间")
+    public HttpResult updateSigningTime(@RequestParam("orderNo") String orderNo){
+        insFeeAuditService.updateSigningTime(orderNo);
+        return HttpResult.ok();
+    }
+
+    /**
+     * 审核订单
+     * @return
+     */
+    @PostMapping("/verifyOrder")
+    @Operation(summary = "审核订单")
+    public HttpResult verifyOrder(@RequestBody VerifyOrderParam param){
+        insFeeAuditService.verifyOrder(param);
+        return HttpResult.ok();
+    }
+
+    /**
+     * 设置为疑问订单
+     * @return
+     */
+    @PostMapping("/updateToQuestionOrder")
+    @Operation(summary = "设置为疑问订单")
+    public HttpResult updateToQuestionOrder(@RequestParam("orderNo") String orderNo){
+        insFeeAuditService.updateToQuestionOrder(orderNo);
+        return HttpResult.ok("已设为疑问订单,可前往疑问订单列表查看");
+    }
+
+    /**
+     * 订单审核费用详情
+     * @return
+     */
+    @GetMapping("/auditCostInfo")
+    @Operation(summary = "订单审核费用详情")
+    public HttpResult auditCostInfo(String orderNo){
+        List<AuditCostInfoVo> costInfoVos = insFeeAuditService.auditCostInfo(orderNo);
+        return HttpResult.ok(costInfoVos);
+    }
+
+    /**
+     * 保存调整的费用
+     * @return
+     */
+    @PostMapping("/saveCostInfo")
+    @Operation(summary = "保存调整的费用")
+    public HttpResult saveCostInfo(@RequestBody PtlAgreementCostRatioVo param){
+        insFeeAuditService.saveCostInfo(param);
+        return HttpResult.ok();
+    }
+}

+ 23 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsFeeAuditMapper.java

@@ -0,0 +1,23 @@
+package com.jzg.quotation.summary.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.entity.dto.FeeAuditParam;
+import com.jzg.commons.entity.orders.po.InsFeeAudit;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+* @author dongxin
+* @description 针对表【ins_fee_audit(订单审核表)】的数据库操作Mapper
+* @createDate 2025-07-02 14:35:50
+* @Entity generator.domain.InsFeeAudit
+*/
+public interface InsFeeAuditMapper extends BaseMapper<InsFeeAudit> {
+
+    Page<FeeAuditVo> queryPage(Page page, @Param("param") FeeAuditParam param);
+}
+
+
+
+

+ 18 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsFeeOrderRecordMapper.java

@@ -0,0 +1,18 @@
+package com.jzg.quotation.summary.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.commons.entity.orders.po.InsFeeOrderRecord;
+
+/**
+* @author dongxin
+* @description 针对表【ins_fee_order_record(订单费用调整记录表)】的数据库操作Mapper
+* @createDate 2025-07-10 11:07:17
+* @Entity generator.domain.InsFeeOrderRecord
+*/
+public interface InsFeeOrderRecordMapper extends BaseMapper<InsFeeOrderRecord> {
+
+}
+
+
+
+

+ 18 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsOrderReadPdfMapper.java

@@ -0,0 +1,18 @@
+package com.jzg.quotation.summary.mapper;
+
+import com.jzg.commons.entity.orders.po.InsOrderReadPdf;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author dongxin
+* @description 针对表【ins_order_read_pdf(保单读取信息配置表)】的数据库操作Mapper
+* @createDate 2025-07-08 15:16:31
+* @Entity generator.domain.InsOrderReadPdf
+*/
+public interface InsOrderReadPdfMapper extends BaseMapper<InsOrderReadPdf> {
+
+}
+
+
+
+

+ 94 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeAuditService.java

@@ -0,0 +1,94 @@
+package com.jzg.quotation.summary.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jzg.commons.entity.dto.FeeAuditParam;
+import com.jzg.commons.entity.dto.VerifyOrderParam;
+import com.jzg.commons.entity.orders.po.InsFeeAudit;
+import com.jzg.commons.entity.orders.po.InsOrders;
+import com.jzg.commons.entity.orders.vo.AuditCostInfoVo;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
+import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
+import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
+
+import java.util.List;
+
+/**
+* @author dongxin
+* @description 针对表【ins_fee_audit(费用审核表)】的数据库操作Service
+* @createDate 2025-07-02 14:35:50
+*/
+public interface InsFeeAuditService extends IService<InsFeeAudit> {
+
+    /**
+     * 订单列表分页
+     * @param param
+     * @return
+     */
+    Page<FeeAuditVo> queryPage(FeeAuditParam param);
+
+    /**
+     * 新增待审核订单
+     *
+     * @param orders
+     */
+    void feeAuditAdd(InsOrders orders);
+
+    /**
+     * 订单详情
+     * @param orderNo
+     * @return
+     */
+    QuoteEchoVo auditInfo(String orderNo);
+
+    /**
+     * 领取审核订单
+     * @param orderNo
+     */
+    void auditReceive(String orderNo);
+
+
+    /**
+     * 放弃领取审核订单
+     * @param orderNo
+     */
+    void auditCancel(String orderNo);
+
+    /**
+     * 判断领取按钮是否锁定
+     * @param orderNo
+     * @return
+     */
+    Boolean isLock(String orderNo);
+
+    /**
+     * 更新签单时间
+     * @param orderNo
+     */
+    void updateSigningTime(String orderNo);
+
+    /**
+     * 审核订单
+     * @param param
+     */
+    void verifyOrder(VerifyOrderParam param);
+
+    /**
+     * 设置为疑问订单
+     * @param orderNo
+     */
+    void updateToQuestionOrder(String orderNo);
+
+    /**
+     * 订单审核费用详情
+     * @param orderNo
+     * @return
+     */
+    List<AuditCostInfoVo> auditCostInfo(String orderNo);
+
+    /**
+     * 保存调整的费用
+     * @param param
+     */
+    void saveCostInfo(PtlAgreementCostRatioVo param);
+}

+ 14 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeOrderRecordService.java

@@ -0,0 +1,14 @@
+
+package com.jzg.quotation.summary.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jzg.commons.entity.orders.po.InsFeeOrderRecord;
+
+/**
+* @author dongxin
+* @description 针对表【ins_fee_order_record(订单费用调整记录表)】的数据库操作Service
+* @createDate 2025-07-10 11:07:17
+*/
+public interface InsFeeOrderRecordService extends IService<InsFeeOrderRecord> {
+
+}

+ 13 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrderReadPdfService.java

@@ -0,0 +1,13 @@
+package com.jzg.quotation.summary.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.jzg.commons.entity.orders.po.InsOrderReadPdf;
+
+/**
+* @author dongxin
+* @description 针对表【ins_order_read_pdf(保单读取信息配置表)】的数据库操作Service
+* @createDate 2025-07-08 15:16:31
+*/
+public interface InsOrderReadPdfService extends IService<InsOrderReadPdf> {
+
+}

+ 470 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java

@@ -0,0 +1,470 @@
+package com.jzg.quotation.summary.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jzg.commons.core.base.BaseController;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.dto.FeeAuditParam;
+import com.jzg.commons.entity.dto.VerifyOrderParam;
+import com.jzg.commons.entity.orders.po.*;
+import com.jzg.commons.entity.orders.vo.AuditCostInfoVo;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
+import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
+import com.jzg.commons.entity.vo.AgreementInfoVo;
+import com.jzg.commons.entity.vo.AgreementVo;
+import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
+import com.jzg.commons.entity.vo.PtlAgreementCostTypeVo;
+import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.AssertionUtils;
+import com.jzg.commons.util.PDFUtil;
+import com.jzg.commons.util.StringUtils;
+import com.jzg.quotation.commons.client.EsmInsCompanyClient;
+import com.jzg.quotation.commons.client.OrgClient;
+import com.jzg.quotation.summary.mapper.InsFeeAuditMapper;
+import com.jzg.quotation.summary.service.*;
+import lombok.RequiredArgsConstructor;
+import org.hibernate.validator.internal.util.stereotypes.Lazy;
+import org.redisson.api.RBucket;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+* @author dongxin
+* @description 针对表【ins_fee_audit(费用审核表)】的数据库操作Service实现
+* @createDate 2025-07-02 14:35:50
+*/
+@Service
+@RequiredArgsConstructor
+public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFeeAudit>
+    implements InsFeeAuditService {
+
+    @Autowired
+    private OrgClient orgClient;
+
+    @Autowired
+    private EsmInsCompanyClient companyClient;
+
+    @Autowired
+    private BaseController baseController;
+
+    @Autowired
+    @Lazy
+    private InsOrdersService insOrdersService;
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @Autowired
+    private InsOrdersPdfUrlService ordersPdfUrlService;
+
+    @Autowired
+    private InsOrderReadPdfService ordersReadPdfService;
+
+    @Autowired
+    private InsOrdersCostsService ordersCostsService;
+
+    @Autowired
+    private InsFeeOrderRecordService recordService;
+
+    @Autowired
+    private InsFeeOrdersService feeOrdersService;
+
+
+    private static final String ORDER_LOCK_PREFIX = "orderLock:";
+
+
+    @Override
+    public Page<FeeAuditVo> queryPage(FeeAuditParam param) {
+        // 获取选中的保险公司条件
+        String companyId = param.getCompanyId();
+        HttpResult<List<String>> result = companyClient.getChildCompanyId(companyId);
+        AssertionUtils.isFail(Objects.isNull(result.getData()),"获取保险公司下级失败!");
+        List<String> companyIdList = result.getData();
+        param.setCompanyIdList(companyIdList);
+        Page<FeeAuditVo> page = baseMapper.queryPage(param.getPage(), param);
+        return page;
+    }
+
+    @Override
+    public void feeAuditAdd(InsOrders orders) {
+        InsFeeAudit insFeeAudit = new InsFeeAudit();
+        insFeeAudit.setOrderNo(orders.getId());
+
+        // 获取协议信息
+        HttpResult<AgreementInfoVo> result = orgClient.queryAgreementById(orders.getAgreementId()
+                ,baseController.getToken(), baseController.getAppSystemCode());
+        AssertionUtils.isFail(Objects.isNull(result.getData()),"获取协议失败!");
+        AgreementInfoVo agreementInfoVo = result.getData();
+        AgreementVo agreementVo = agreementInfoVo.getAgreement();
+        insFeeAudit.setAuditType(Integer.parseInt(agreementVo.getAuditType()));
+        if(agreementVo.getAuditType().equals(1)){ // 人工审核
+            insFeeAudit.setAuditStatus(0);
+        }else{ // 自动审核
+            insFeeAudit.setAuditStatus(1);
+        }
+        this.save(insFeeAudit);
+    }
+
+    @Override
+    public QuoteEchoVo auditInfo(String orderNo) {
+        QuoteEchoVo detailVo = insOrdersService.getOrderDetail(orderNo);
+        InsFeeAudit audit = this.getById(orderNo);
+        detailVo.setAuditStatus(audit.getAuditStatus());
+        return detailVo;
+    }
+
+    @Override
+    public void auditReceive(String orderNo) {
+        InsFeeAudit audit = this.getById(orderNo);
+        if(audit.getAuditStatus() > 0){
+            if(audit.getAuditStatus() == 1){
+                AssertionUtils.isFail(true, "订单已审核通过,刷新订单列表");
+            }else{
+                AssertionUtils.isFail(true, "订单审核驳回,刷新订单列表");
+            }
+        // 未审核
+        }else{
+            String userName = baseController.getUserName();
+            if(StringUtils.isNotBlank(audit.getReceiveUser())){
+                if(userName.equals(audit.getReceiveUser())){
+                    // redis 锁定按钮
+                    RBucket<Object> bucket = redissonClient.getBucket(ORDER_LOCK_PREFIX + orderNo);
+                    bucket.set(1, 30, TimeUnit.MINUTES);
+                }else{
+                    AssertionUtils.isFail(true, "订单已被" + audit.getReceiveUser() + "领取!");
+                }
+            }else{
+                LambdaQueryWrapper<InsFeeAudit> wrapper = new LambdaQueryWrapper<>();
+                wrapper.like(InsFeeAudit::getReceiveUser, userName);
+                long count = this.count(wrapper);
+                if(count >= 10){
+                    AssertionUtils.isFail(true, "超出10次领取限制,请先审核后再领取订单!");
+                }else{
+                    // 领取订单
+                    audit.setReceiveUser(userName);
+                    audit.setReceiveTime(LocalDateTime.now());
+                    this.updateById(audit);
+
+                    // redis 锁定按钮
+                    RBucket<Object> bucket = redissonClient.getBucket(ORDER_LOCK_PREFIX + orderNo);
+                    bucket.set(1, 30, TimeUnit.MINUTES);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void auditCancel(String orderNo) {
+        InsFeeAudit audit = this.getById(orderNo);
+        if(audit.getAuditStatus() > 0){
+            AssertionUtils.isFail(true, "订单已审核!");
+        }
+        String userName = baseController.getUserName();
+        if (userName.equals(audit.getReceiveUser())) {
+            AssertionUtils.isFail(true, "已放弃订单审核任务!");
+        }
+
+        LambdaUpdateWrapper<InsFeeAudit> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.set(InsFeeAudit::getReceiveUser,null);
+        wrapper.set(InsFeeAudit::getReceiveTime,null);
+        wrapper.eq(InsFeeAudit::getOrderNo,orderNo);
+        this.update(wrapper);
+
+        // 清空锁定缓存
+        RBucket<Object> bucket = redissonClient.getBucket(ORDER_LOCK_PREFIX + orderNo);
+        if(bucket.isExists()){
+            bucket.delete();
+        }
+    }
+
+    @Override
+    public Boolean isLock(String orderNo) {
+        RBucket<Object> bucket = redissonClient.getBucket(ORDER_LOCK_PREFIX + orderNo);
+        return bucket.isExists();
+    }
+
+    @Override
+    public void updateSigningTime(String orderNo) {
+        InsOrders orders = insOrdersService.getById(orderNo);
+        // 查询电子保单路径
+        InsOrdersPdfUrl pdfUrl = ordersPdfUrlService.getById(orderNo);
+        AssertionUtils.isFail(Objects.isNull(pdfUrl), "未生成电子保单!");
+        String url = null;
+        Integer type = 0;
+        if(StringUtils.isNotBlank(pdfUrl.getJqUrl())){
+            url = pdfUrl.getJqUrl();
+            type = 1;
+        }else{
+            url = pdfUrl.getSyUrl();
+            type = 2;
+        }
+        AssertionUtils.isFail(StringUtils.isBlank(url), "未生成电子保单!");
+
+        // 转为本地路径
+        String localUrl = PDFUtil.trafferHttpToLocalPath(url);
+        //通过保险公司配置读取截取的前缀和后缀
+        LambdaQueryWrapper<InsOrderReadPdf> qws = new LambdaQueryWrapper<>();
+        qws.eq(InsOrderReadPdf::getCompanyId, orders.getCompanyId());
+        qws.eq(InsOrderReadPdf::getType, type);
+        List<InsOrderReadPdf> list = ordersReadPdfService.list(qws);
+
+        HashMap<String, LocalDateTime> map = new HashMap<>();
+        String pdfText = PDFUtil.getPdfText(localUrl);
+        if (StringUtils.isNotBlank(pdfText)) {
+            if (CollUtil.isNotEmpty(list)) {
+                for (InsOrderReadPdf insOrderReadPdf : list) {
+                    LocalDateTime pdfContentDate = PDFUtil.getPdfContentDate(pdfText, insOrderReadPdf.getReadBegin(), insOrderReadPdf.getReadEnd(), insOrderReadPdf.getReadType());
+                    map.put(insOrderReadPdf.getOrderMsg(), pdfContentDate);
+                }
+            }
+        }
+
+        //刪除临时文件
+        if (url.contains("http") || url.contains("https")) {
+            File file = new File(localUrl);
+            file.delete();
+        }
+        if (map.get("payDate") != null) {
+            orders.setPayTime(map.get("payDate"));
+        }
+        if (map.get("signingTime") != null) {
+            orders.setSigningTime(map.get("signingTime").toLocalDate());
+        }
+        //更新时间表
+        insOrdersService.updateById(orders);
+
+
+    }
+
+    @Override
+    public void verifyOrder(VerifyOrderParam param) {
+        InsFeeAudit audit = this.getById(param.getOrderNo());
+        if(audit.getAuditStatus() > 0){
+            AssertionUtils.isFail(true, "订单已审核刷新订单详情页!");
+        }
+        if(StringUtils.isBlank(audit.getReceiveUser())){
+            AssertionUtils.isFail(true, "请领取订单后再进行审核退出详情页,返回待审核订单列表!");
+        }
+        String userName = baseController.getUserName();
+        if (!userName.equals(audit.getReceiveUser())) {
+            AssertionUtils.isFail(true, "订单已被"+audit.getReceiveUser()+"领取返回待审核订单列表!");
+        }
+
+        audit.setAuditStatus(param.getAuditStatus());
+        audit.setRefuse(param.getRefuse());
+        audit.setIsProblem(0);
+        this.updateById(audit);
+    }
+
+    @Override
+    public void updateToQuestionOrder(String orderNo) {
+        InsFeeAudit audit = this.getById(orderNo);
+        if(audit.getAuditStatus() > 0){
+            AssertionUtils.isFail(true, "订单已审核刷新订单详情页!");
+        }
+
+        if(StringUtils.isBlank(audit.getReceiveUser())){
+            AssertionUtils.isFail(true, "请领取订单后再进行审核退出详情页,返回待审核订单列表!");
+        }
+        String userName = baseController.getUserName();
+        if (!userName.equals(audit.getReceiveUser())) {
+            AssertionUtils.isFail(true, "订单已被"+audit.getReceiveUser()+"领取返回待审核订单列表!");
+        }
+
+        audit.setIsProblem(1);
+        this.updateById(audit);
+    }
+
+    @Override
+    public List<AuditCostInfoVo> auditCostInfo(String orderNo) {
+        // 获取保费
+        InsOrdersCosts costs = ordersCostsService.getById(orderNo);
+        // 获取比例
+        LambdaQueryWrapper<InsFeeOrderRecord> qws = new LambdaQueryWrapper<>();
+        qws.eq(InsFeeOrderRecord::getOrderNo, orderNo)
+                .orderByDesc(InsFeeOrderRecord::getCreateTime);
+        List<InsFeeOrderRecord> records = recordService.list(qws);
+        InsFeeOrderRecord record = new InsFeeOrderRecord();
+
+        // 获取订单关联协议的相关比例
+        InsFeeOrders feeOrders = feeOrdersService.getById(orderNo);
+        List<PtlAgreementCostTypeVo> costTypeVos = orgClient.queryByCostId(feeOrders.getCostId());
+        List<AuditCostInfoVo> auditCostInfoVos = new ArrayList<>();
+        if(CollUtil.isNotEmpty(records)){
+            record = records.get(0);
+            this.getRecordCost(auditCostInfoVos, record, costTypeVos,feeOrders);
+        }else {
+            // 获取协议信息
+            HttpResult<AgreementInfoVo> result = orgClient.queryAgreementById(feeOrders.getAgreementId()
+                    ,baseController.getToken(), baseController.getAppSystemCode());
+            AssertionUtils.isFail(Objects.isNull(result.getData()),"获取协议失败!");
+            AgreementInfoVo agreementInfoVo = result.getData();
+            this.getAuditCost(auditCostInfoVos,costTypeVos,feeOrders,agreementInfoVo.getAgreement());
+        }
+        return auditCostInfoVos;
+    }
+
+    @Override
+    public void saveCostInfo(PtlAgreementCostRatioVo param) {
+        try {
+            feeOrdersService.calcCosts(param);
+        } catch (ReflectiveOperationException e) {
+            e.printStackTrace();
+            throw new SystemException("费用计算异常:"+ e.getMessage());
+        }
+        // 保存比例调整记录
+        InsFeeOrderRecord record = new InsFeeOrderRecord(param);
+        recordService.save(record);
+    }
+
+
+    private void getAuditCost(List<AuditCostInfoVo> auditCostInfoVos,
+                              List<PtlAgreementCostTypeVo> costTypeVos,
+                              InsFeeOrders feeOrders,
+                              AgreementVo agreement) {
+        for (PtlAgreementCostTypeVo costTypeVo : costTypeVos) {
+            if(costTypeVo.getCostType().equals("1")){
+                AuditCostInfoVo jqInfoVo = new AuditCostInfoVo();
+                jqInfoVo.setCostType(costTypeVo.getCostType());
+                jqInfoVo.setPremium(feeOrders.getJqPremium());
+                jqInfoVo.setInletRadio(costTypeVo.getInlet());
+                jqInfoVo.setInletPremium(feeOrders.getJqReceivablePremium());
+                jqInfoVo.setEntranceFeeRatio(agreement.getJqEntranceFeeRatio());
+                jqInfoVo.setEntranceFeePremium(feeOrders.getJqCommissionPremium());
+                BigDecimal followRatio = costTypeVo.getInlet().subtract(agreement.getJqEntranceFeeRatio()); // 计算跟单比例
+                jqInfoVo.setFollowRatio(followRatio);
+                jqInfoVo.setFollowPremium(feeOrders.getJqFollowPremium());
+                jqInfoVo.setAddThrowRatio(costTypeVo.getAddThrow());
+                jqInfoVo.setAddThrowPremium(feeOrders.getJqAdditionalPremium());
+                jqInfoVo.setExportRatio(costTypeVo.getExport());
+                jqInfoVo.setExportPremium(feeOrders.getJqPayablePremium());
+                jqInfoVo.setKeepPointRatio(costTypeVo.getKeepPointRatio());
+                jqInfoVo.setKeepPointPremium(feeOrders.getJqKeepPointPremium());
+                auditCostInfoVos.add(jqInfoVo);
+            }else if(costTypeVo.getCostType().equals("2")){
+                AuditCostInfoVo syInfoVo = new AuditCostInfoVo();
+                syInfoVo.setCostType(costTypeVo.getCostType());
+                syInfoVo.setPremium(feeOrders.getSyPremium());
+                syInfoVo.setInletRadio(costTypeVo.getInlet());
+                syInfoVo.setInletPremium(feeOrders.getSyReceivablePremium());
+                syInfoVo.setEntranceFeeRatio(agreement.getSyEntranceFeeRatio());
+                syInfoVo.setEntranceFeePremium(feeOrders.getSyCommissionPremium());
+                BigDecimal followRatio = costTypeVo.getInlet().subtract(agreement.getSyEntranceFeeRatio()); // 计算跟单比例
+                syInfoVo.setFollowRatio(followRatio);
+                syInfoVo.setFollowPremium(feeOrders.getSyFollowPremium());
+                syInfoVo.setAddThrowRatio(costTypeVo.getAddThrow());
+                syInfoVo.setAddThrowPremium(feeOrders.getSyAdditionalPremium());
+                syInfoVo.setExportRatio(costTypeVo.getExport());
+                syInfoVo.setExportPremium(feeOrders.getSyPayablePremium());
+                syInfoVo.setKeepPointRatio(costTypeVo.getKeepPointRatio());
+                syInfoVo.setKeepPointPremium(feeOrders.getSyKeepPointPremium());
+                auditCostInfoVos.add(syInfoVo);
+            }else{
+                AuditCostInfoVo noInfoVo = new AuditCostInfoVo();
+                noInfoVo.setCostType(costTypeVo.getCostType());
+                noInfoVo.setPremium(feeOrders.getJyPremium());
+                noInfoVo.setInletRadio(costTypeVo.getInlet());
+                noInfoVo.setInletPremium(feeOrders.getJyReceivablePremium());
+                noInfoVo.setEntranceFeeRatio(agreement.getJyEntranceFeeRatio());
+                noInfoVo.setEntranceFeePremium(feeOrders.getJyCommissionPremium());
+                BigDecimal followRatio = costTypeVo.getInlet().subtract(agreement.getJyEntranceFeeRatio()); // 计算跟单比例
+                noInfoVo.setFollowRatio(followRatio);
+                noInfoVo.setFollowPremium(feeOrders.getJyFollowPremium());
+                noInfoVo.setAddThrowRatio(costTypeVo.getAddThrow());
+                noInfoVo.setAddThrowPremium(feeOrders.getJyAdditionalPremium());
+                noInfoVo.setExportRatio(costTypeVo.getExport());
+                noInfoVo.setExportPremium(feeOrders.getJyPayablePremium());
+                noInfoVo.setKeepPointRatio(costTypeVo.getKeepPointRatio());
+                noInfoVo.setKeepPointPremium(feeOrders.getJyKeepPointPremium());
+                auditCostInfoVos.add(noInfoVo);
+            }
+        }
+    }
+
+    /**
+     * 修改记录展示费用信息
+     * @param auditCostInfoVos
+     * @param record
+     * @param costTypeVos
+     * @param feeOrders
+     */
+    private void getRecordCost(List<AuditCostInfoVo> auditCostInfoVos,
+                           InsFeeOrderRecord record,
+                           List<PtlAgreementCostTypeVo> costTypeVos,
+                           InsFeeOrders feeOrders) {
+        for (PtlAgreementCostTypeVo costTypeVo : costTypeVos) {
+            if(costTypeVo.getCostType().equals("1")){
+                AuditCostInfoVo jqInfoVo = new AuditCostInfoVo();
+                jqInfoVo.setCostType(costTypeVo.getCostType());
+                jqInfoVo.setPremium(feeOrders.getJqPremium());
+                jqInfoVo.setInletRadio(record.getJqInletRadio());
+                jqInfoVo.setInletPremium(feeOrders.getJqReceivablePremium());
+                jqInfoVo.setEntranceFeeRatio(record.getJqEntranceFeeRatio());
+                jqInfoVo.setEntranceFeePremium(feeOrders.getJqCommissionPremium());
+                jqInfoVo.setFollowRatio(record.getJqFollowRatio());
+                jqInfoVo.setFollowPremium(feeOrders.getJqFollowPremium());
+                jqInfoVo.setAddThrowRatio(record.getJqAddThrowRadio());
+                jqInfoVo.setAddThrowPremium(feeOrders.getJqAdditionalPremium());
+                jqInfoVo.setExportRatio(costTypeVo.getExport());
+                jqInfoVo.setExportPremium(feeOrders.getJqPayablePremium());
+                jqInfoVo.setKeepPointRatio(record.getJqKeepPointRatio());
+                jqInfoVo.setKeepPointPremium(feeOrders.getJqKeepPointPremium());
+                auditCostInfoVos.add(jqInfoVo);
+            }else if(costTypeVo.getCostType().equals("2")){
+                AuditCostInfoVo syInfoVo = new AuditCostInfoVo();
+                syInfoVo.setCostType(costTypeVo.getCostType());
+                syInfoVo.setPremium(feeOrders.getSyPremium());
+                syInfoVo.setInletRadio(record.getSyInletRadio());
+                syInfoVo.setInletPremium(feeOrders.getSyReceivablePremium());
+                syInfoVo.setEntranceFeeRatio(record.getSyEntranceFeeRatio());
+                syInfoVo.setEntranceFeePremium(feeOrders.getSyCommissionPremium());
+                syInfoVo.setFollowRatio(record.getSyFollowRatio());
+                syInfoVo.setFollowPremium(feeOrders.getSyFollowPremium());
+                syInfoVo.setAddThrowRatio(record.getSyAddThrowRadio());
+                syInfoVo.setAddThrowPremium(feeOrders.getSyAdditionalPremium());
+                syInfoVo.setExportRatio(costTypeVo.getExport());
+                syInfoVo.setExportPremium(feeOrders.getSyPayablePremium());
+                syInfoVo.setKeepPointRatio(record.getSyKeepPointRatio());
+                syInfoVo.setKeepPointPremium(feeOrders.getSyKeepPointPremium());
+                auditCostInfoVos.add(syInfoVo);
+            }else{
+                AuditCostInfoVo noInfoVo = new AuditCostInfoVo();
+                noInfoVo.setCostType(costTypeVo.getCostType());
+                noInfoVo.setPremium(feeOrders.getJyPremium());
+                noInfoVo.setInletRadio(record.getNoInletRadio());
+                noInfoVo.setInletPremium(feeOrders.getJyReceivablePremium());
+                noInfoVo.setEntranceFeeRatio(record.getNoEntranceFeeRatio());
+                noInfoVo.setEntranceFeePremium(feeOrders.getJyCommissionPremium());
+                noInfoVo.setFollowRatio(record.getNoFollowRatio());
+                noInfoVo.setFollowPremium(feeOrders.getJyFollowPremium());
+                noInfoVo.setAddThrowRatio(record.getNoAddThrowRadio());
+                noInfoVo.setAddThrowPremium(feeOrders.getJyAdditionalPremium());
+                noInfoVo.setExportRatio(costTypeVo.getExport());
+                noInfoVo.setExportPremium(feeOrders.getJyPayablePremium());
+                noInfoVo.setKeepPointRatio(record.getNoKeepPointRatio());
+                noInfoVo.setKeepPointPremium(feeOrders.getJyKeepPointPremium());
+                auditCostInfoVos.add(noInfoVo);
+            }
+        }
+
+
+    }
+}
+
+
+
+

+ 22 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeOrderRecordServiceImpl.java

@@ -0,0 +1,22 @@
+package com.jzg.quotation.summary.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jzg.commons.entity.orders.po.InsFeeOrderRecord;
+import com.jzg.quotation.summary.mapper.InsFeeOrderRecordMapper;
+import com.jzg.quotation.summary.service.InsFeeOrderRecordService;
+import org.springframework.stereotype.Service;
+
+/**
+* @author dongxin
+* @description 针对表【ins_fee_order_record(订单费用调整记录表)】的数据库操作Service实现
+* @createDate 2025-07-10 11:07:17
+*/
+@Service
+public class InsFeeOrderRecordServiceImpl extends ServiceImpl<InsFeeOrderRecordMapper, InsFeeOrderRecord>
+    implements InsFeeOrderRecordService {
+
+}
+
+
+
+

+ 22 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrderReadPdfServiceImpl.java

@@ -0,0 +1,22 @@
+package com.jzg.quotation.summary.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.jzg.commons.entity.orders.po.InsOrderReadPdf;
+import com.jzg.quotation.summary.mapper.InsOrderReadPdfMapper;
+import com.jzg.quotation.summary.service.InsOrderReadPdfService;
+import org.springframework.stereotype.Service;
+
+/**
+* @author dongxin
+* @description 针对表【ins_order_read_pdf(保单读取信息配置表)】的数据库操作Service实现
+* @createDate 2025-07-08 15:16:31
+*/
+@Service
+public class InsOrderReadPdfServiceImpl extends ServiceImpl<InsOrderReadPdfMapper, InsOrderReadPdf>
+    implements InsOrderReadPdfService {
+
+}
+
+
+
+

+ 6 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java

@@ -54,6 +54,7 @@ import lombok.Setter;
 import org.apache.commons.beanutils.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -98,7 +99,9 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
 
     private final BaseController baseController;
 
-    private final InsOrdersTrackService insOrdersTrackService;
+    @Autowired
+    @Lazy
+    private InsFeeAuditService insFeeAuditService; // ✅ 改为字段注入 + 延迟加载
 
     @Setter(onMethod_ = @Autowired)
     private OrderMessageTemplate orderMessageTemplate;
@@ -1014,6 +1017,8 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
                     insOrdersCarInfo,costs,
                     baseController.getToken(), MessageCodeEnum.TEMPLATE_5);
         } else if(orderStatusResultVo.getOrderStatus().equals(InsOrderStatusEnum.UNDERWRITED)){
+            // 增加财务审核
+            insFeeAuditService.feeAuditAdd(insOrders);
             // 发送订单状态变更消息
             this.orderStatusMessage(insOrders,
                     insOrdersCarInfo,costs,

+ 39 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/state/AuditState.java

@@ -0,0 +1,39 @@
+package com.jzg.quotation.summary.state;
+
+public class AuditState {
+
+    public enum AuditStateEnum {
+        // 待审核
+        NO_AUDIT(0),
+        // 审核通过
+        SUCCESS_AUDIT(1),
+        // 审核失败
+        FAIL_AUDIT(1);
+
+        private final int value;
+
+        AuditStateEnum(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+
+        public static AuditState.AuditStateEnum fromValue(int value) {
+            for (AuditState.AuditStateEnum costStateEnum : AuditState.AuditStateEnum.values()) {
+                if (costStateEnum.getValue() == value) {
+                    return costStateEnum;
+                }
+            }
+            return null;
+        }
+    }
+
+    public enum AuditStateEvent {
+        //审核失败事件
+        AUDIT_FAIL_EVENT,
+        //审核成功事件
+        AUDIT_SUCCESS_EVENT;
+    }
+}

+ 34 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/state/config/AuditStateConfig.java

@@ -0,0 +1,34 @@
+package com.jzg.quotation.summary.state.config;
+
+import com.jzg.quotation.summary.state.AuditState;
+import com.jzg.quotation.summary.state.OrderState;
+import org.springframework.context.annotation.Bean;
+import org.springframework.statemachine.StateMachine;
+import org.springframework.statemachine.config.StateMachineBuilder;
+import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
+
+import java.util.EnumSet;
+
+public class AuditStateConfig extends StateMachineConfigurerAdapter<AuditState.AuditStateEnum, AuditState.AuditStateEvent> {
+
+
+    @Bean(name = "auditStateMachine")
+    public StateMachine<AuditState.AuditStateEnum, AuditState.AuditStateEvent> costStateMachine() throws Exception {
+        StateMachineBuilder.Builder<AuditState.AuditStateEnum, AuditState.AuditStateEvent> builder = StateMachineBuilder.builder();
+        builder.configureStates()
+                .withStates()
+                .initial(AuditState.AuditStateEnum.NO_AUDIT)
+                .states(EnumSet.allOf(AuditState.AuditStateEnum.class));
+        builder.configureTransitions()
+                .withExternal()
+                // 待审核 -> 审核通过
+                .source(AuditState.AuditStateEnum.NO_AUDIT).target(AuditState.AuditStateEnum.SUCCESS_AUDIT).event(AuditState.AuditStateEvent.AUDIT_SUCCESS_EVENT)
+                .and()
+                .withExternal()
+                // 待审核 -> 审核失败
+                .source(AuditState.AuditStateEnum.NO_AUDIT).target(AuditState.AuditStateEnum.FAIL_AUDIT).event(AuditState.AuditStateEvent.AUDIT_FAIL_EVENT)
+        ;
+
+        return builder.build();
+    }
+}

+ 78 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/state/listener/AuditStateListener.java

@@ -0,0 +1,78 @@
+package com.jzg.quotation.summary.state.listener;
+
+import com.jzg.commons.core.base.StateResult;
+import com.jzg.quotation.summary.state.AuditState;
+import jakarta.annotation.Resource;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.statemachine.StateMachine;
+import org.springframework.statemachine.StateMachineEventResult;
+import org.springframework.statemachine.support.DefaultStateMachineContext;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class AuditStateListener {
+
+    @Resource
+    private StateMachine<AuditState.AuditStateEnum, AuditState.AuditStateEvent> costStateMachine;
+
+    private synchronized boolean sendEvent(Mono<Message<AuditState.AuditStateEvent>> message) {
+        AtomicBoolean result = new AtomicBoolean(false);
+        try {
+            costStateMachine.stop(); // 停止状态机
+            Message<AuditState.AuditStateEvent> block = message.block();
+            String orderStatus = (String) block.getHeaders().get("entity");
+            costStateMachine.getStateMachineAccessor().doWithAllRegions(accessor -> {
+                accessor.resetStateMachineReactively(new DefaultStateMachineContext<>(
+                        // 目标状态
+                        AuditState.AuditStateEnum.fromValue(Integer.parseInt(orderStatus)),
+                        null, // 当前事件(可以为 null)
+                        null, // 扩展上下文(可以为 null)
+                        null  // 转换历史(通常为 null)
+                )).block();
+            });
+            Mono<Void> startMono = costStateMachine.startReactively(); //启用状态机
+            startMono.block();
+
+            Flux<StateMachineEventResult<AuditState.AuditStateEnum, AuditState.AuditStateEvent>> stateMachineEventResultFlux = costStateMachine.sendEvent(message);
+            StateMachineEventResult<AuditState.AuditStateEnum, AuditState.AuditStateEvent> eventResult = stateMachineEventResultFlux.blockFirst();
+
+            if (eventResult != null && eventResult.getResultType() == StateMachineEventResult.ResultType.ACCEPTED) {
+                result.set(true);
+            }
+        } catch (Exception e) {
+
+        } finally {
+            costStateMachine.stopReactively();
+            return result.get();
+        }
+    }
+
+    private StateResult callEvent(String auditStatus, AuditState.AuditStateEvent event) {
+        StateResult stateResult = new StateResult();
+        Mono<Message<AuditState.AuditStateEvent>> message = Mono.just(MessageBuilder.withPayload(event).setHeader("entity",auditStatus).build());
+        stateResult.setResult(sendEvent(message));
+        stateResult.setCurrentState(costStateMachine.getState().getId().getValue());
+        return stateResult;
+    }
+
+    /**
+     * 审核失败
+     * @param cureentStatus
+     * @return
+     */
+    public StateResult auditFail(String cureentStatus) {
+        return callEvent(cureentStatus, AuditState.AuditStateEvent.AUDIT_FAIL_EVENT);
+    }
+
+    /**
+     * 审核成功
+     * @param currentStatus
+     * @return
+     */
+    public StateResult auditSuccess(String currentStatus) {
+        return callEvent(currentStatus, AuditState.AuditStateEvent.AUDIT_SUCCESS_EVENT);
+    }
+}

+ 4 - 1
tenant/insurance/quotation-summary/src/main/resources/application.yaml

@@ -4,6 +4,9 @@ server:
 spring:
   application:
     name: quotation-summary
+  main:
+    allow-circular-references: true
+    allow-bean-definition-overriding: true
   profiles:
     active: dev
   servlet:
@@ -51,4 +54,4 @@ rocketmq:
     # 启动后会自动在topic上拼接激活的配置文件,达到自动隔离的效果
     enabledIsolation: true
     # 隔离环境名称,拼接到topic后,topic_dev,默认空字符串
-    environment: dev
+    environment: dev

+ 128 - 0
tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeAuditMapper.xml

@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jzg.quotation.summary.mapper.InsFeeAuditMapper">
+
+    <resultMap id="BaseResultMap" type="com.jzg.commons.entity.orders.po.InsFeeAudit">
+            <id property="orderNo" column="order_no" jdbcType="VARCHAR"/>
+            <result property="auditStatus" column="audit_status" jdbcType="VARCHAR"/>
+            <result property="auditTime" column="audit_time" jdbcType="TIMESTAMP"/>
+            <result property="auditUser" column="audit_user" jdbcType="VARCHAR"/>
+            <result property="receiveTime" column="receive_time" jdbcType="TIMESTAMP"/>
+            <result property="receiveUser" column="receive_user" jdbcType="VARCHAR"/>
+            <result property="isDelete" column="is_delete" jdbcType="TINYINT"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+            <result property="createBy" column="create_by" jdbcType="VARCHAR"/>
+            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+            <result property="updateBy" column="update_by" jdbcType="VARCHAR"/>
+            <result property="isProblem" column="is_problem" jdbcType="TINYINT"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        order_no,audit_status,audit_time,
+        audit_user,receive_time,receive_user,
+        is_delete,create_time,create_by,
+        update_time,update_by,is_problem
+    </sql>
+    <select id="queryPage" resultType="com.jzg.commons.entity.orders.vo.FeeAuditVo">
+        SELECT ifa.order_no as orderNo,io.company_name as companyName,
+               ioci.license_no AS licenseNo,iocui.name as insurName,
+               io.entry_status as orderType,suji.name as name, su.mobile as mobile,
+               suji.type_attr as attrType,io.signing_time as signingTime,
+               io.create_time as quotationTime, sua.username as dockingPerson,
+               pa.agreement_abbreviation as agreementName,io.product_name as productName,
+               ioc.jq_premium as jqPremium, ioc.sy_premium as syPremium, ioc.jy_premium as jyPremium,
+               ioc.sum_premium as sumPremium,sd.name as deptName,ifa.create_time as createTime,
+               ifa.create_by as createBy,io.pay_time as payTime, ifa.audit_time as auditTime,
+               ifa.audit_user as auditUser, ifa.refuse
+        FROM ins_fee_audit ifa
+        LEFT JOIN ins_orders as io on ifa.order_no = io.id
+        LEFT JOIN ins_orders_car_info as ioci on io.id = ioci.order_no
+        LEFT JOIN ins_orders_car_user_info as iocui on io.id = iocui.order_no and iocui.policy_person_type = 3
+        LEFT JOIN sys_user_jzg_info suji on suji.user_id = io.real_quote_user_id
+        LEFT JOIN sys_user su on su.id = io.real_quote_user_id
+        LEFT JOIN sys_dept sd on suji.dept_id on sd.id
+        LEFT JOIN ptl_agreement pa on io.agreement_id = pa.id
+        LEFT JOIN sys_user sua on sua.id = pa.custodian_id
+        LEFT JOIN ins_orders_costs ioc on ioc.order_no = io.id
+        LEFT JOIN ins_orders_external_policy ioep on ioep.order_no = io.id
+        <where>
+            <choose>
+                <when test="param.receiveUser != null and param.receiveUser != ''">
+                    and ifa.receive_user = #{param.receiveUser}
+                </when>
+                <otherwise>
+                    and ifa.receive_user = null
+                </otherwise>
+            </choose>
+            <if test="param.auditType != null">
+                and ifa.audit_type = #{param.auditType}
+            </if>
+            <if test="param.licenseNo != null and param.licenseNo != ''">
+                and ioci.license_no like concat('%',#{param.licenseNo},'%')
+            </if>
+            <if test="param.licenseNo != null and param.licenseNo != ''">
+                and ioci.license_no like concat('%',#{param.licenseNo},'%')
+            </if>
+            <if test="param.attrType != null ">
+                and suji.type_attr = #{param.attrType}
+            </if>
+            <if test="param.salesman != null and param.salesman != ''">
+                and (su.username = #{param.salesman} or su.mobile = #{param.salesman})
+            </if>
+            <if test="param.orderStatus != null ">
+                and io.order_status = #{param.orderStatus}
+            </if>
+            <if test="param.orderType != null ">
+                and io.entry_status = #{param.orderType}
+            </if>
+            <if test="companyIdList != null and companyIdList.size()" >
+                AND io.company_id in
+                <foreach collection="companyIdList" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="param.deptId != null and param.deptId != ''">
+                and suji.dept_id = #{param.deptId}
+            </if>
+            <if test="param.insurName != null and param.insurName != ''">
+                and iocui.name = #{param.insurName}
+            </if>
+            <if test="param.quotationTimeStart != null and param.quotationTimeEnd != null">
+                and DATE_FORMAT(io.create_time, '%Y-%m-%d') between #{param.quotationTimeStart} AND #{param.quotationTimeEnd}
+            </if>
+            <if test="param.signingTimeStart != null and param.signingTimeEnd != null">
+                and DATE_FORMAT(io.signing_time, '%Y-%m-%d') between #{param.signingTimeStart} AND #{param.signingTimeEnd}
+            </if>
+            <if test="param.orderNo != null and param.orderNo != ''">
+                and ifa.order_no = #{param.orderNo}
+            </if>
+            <if test="param.agreementId != null and param.agreementId != ''">
+                and pa.id = #{param.agreementId}
+            </if>
+            <if test="param.productName != null and param.productName != ''">
+                and io.product_name = #{param.productName}
+            </if>
+            <if test="param.payTimeStart != null and param.payTimeEnd != null">
+                and DATE_FORMAT(io.pay_time, '%Y-%m-%d') between #{param.payTimeStart} AND #{param.payTimeEnd}
+            </if>
+            <if test="param.ciPolicyNumber != null and param.ciPolicyNumber != ''">
+                and ioep.jq_policy = #{param.ciPolicyNumber}
+            </if>
+            <if test="param.biPolicyNumber != null and param.biPolicyNumber != ''">
+                and ioep.sy_policy = #{param.biPolicyNumber}
+            </if>
+            <if test="param.niPolicyNumber != null and param.niPolicyNumber != ''">
+                and ioep.no_policy = #{param.niPolicyNumber}
+            </if>
+            <if test="param.auditTimeStart != null and param.auditTimeEnd != null">
+                and DATE_FORMAT(ifa.audit_time, '%Y-%m-%d') between #{param.auditTimeStart} AND #{param.auditTimeEnd}
+            </if>
+            <if test="param.auditUser != null and param.auditUser != ''">
+                and ifa.audit_user = #{param.auditUser}
+            </if>
+        </where>
+        ORDER BY create_time desc
+    </select>
+</mapper>