Explorar el Código

Merge branch 'master' into dev_jzg_lipf_v20260518

lipf hace 3 meses
padre
commit
3c82ce1dbf
Se han modificado 67 ficheros con 2317 adiciones y 426 borrados
  1. 3 5
      commons/src/main/java/com/jzg/commons/entity/dto/AgreementRulesAddParam.java
  2. 8 5
      commons/src/main/java/com/jzg/commons/entity/dto/AgreementRulesEditParam.java
  3. 22 0
      commons/src/main/java/com/jzg/commons/entity/dto/RulesGroupParam.java
  4. 4 0
      commons/src/main/java/com/jzg/commons/entity/po/PtlAgreementUndwrtRules.java
  5. 4 0
      commons/src/main/java/com/jzg/commons/entity/po/jyxSetting.java
  6. 8 1
      commons/src/main/java/com/jzg/commons/entity/quote/vo/base/LoginBase.java
  7. 8 0
      commons/src/main/java/com/jzg/commons/entity/vo/AgreementRulesVo.java
  8. 7 0
      tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/service/impl/AnShengCrawlerRequestImpl.java
  9. 7 0
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerRequestImpl.java
  10. 7 0
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerRequestImpl.java
  11. 9 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/entity/GetCaptchaRequest.java
  12. 3 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/service/QuotationCrawlerBaseService.java
  13. 7 0
      tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/crawler/service/impl/DaJiaCrawlerRequestImpl.java
  14. 8 0
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/build/GuoRenCrawlerQuoteResultsVoBuild.java
  15. 0 1
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/request/GuoRenCrawlerProposalNoSaveRequest.java
  16. 623 1
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/response/GuoRenCrawlerCalculationPremiumData.java
  17. 7 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/service/Impl/GuoshouCrawlerRequestImpl.java
  18. 7 0
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/service/Impl/HengBangCrawlerRequestImpl.java
  19. 8 2
      tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/build/HuaNongCrawlerQuoteResultsVoBuild.java
  20. 120 131
      tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/service/impl/HuaNongCrawlerRequestImpl.java
  21. 7 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java
  22. 7 0
      tenant/insurance/quotation-renbao/src/main/java/com/jzg/quotation/renbao/crawler/service/impl/RenBaoCrawlerRequestImpl.java
  23. 7 0
      tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestImpl.java
  24. 7 0
      tenant/insurance/quotation-shenneng/src/main/java/com/jzg/quotation/shenneng/crawler/service/impl/ShenNengCrawlerRequestImpl.java
  25. 10 2
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/UnifyOrderManager.java
  26. 34 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/factory/CompanyFactory.java
  27. 7 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/impl/TKQuotationBaseServiceImpl.java
  28. 7 0
      tenant/insurance/quotation-taipingyang/src/main/java/com/jzg/quotation/taipingyang/crawler/service/impl/TaiPingYangCrawlerRequestImpl.java
  29. 1 1
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/component/TaiShanCrawlerRequestComponent.java
  30. 2 0
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/constant/enums/RequestUrl.java
  31. 4 2
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanCrawlerLoginRequest.java
  32. 6 6
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanCrawlerSmsCodeRequest.java
  33. 3 2
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanCrawlerVerifyRequest.java
  34. 30 0
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanExternalSendCodeRequest.java
  35. 2 0
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/response/TaiShanCrawlerSmsCodeResponse.java
  36. 43 0
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/response/TaiShanExternalSendCodeResponse.java
  37. 20 0
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/properties/ExteriorCaptchaProperties.java
  38. 9 0
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/TaiShanCrawlerQuoteProcessService.java
  39. 2 1
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/TaiShanCrawlerRequest.java
  40. 157 34
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerQuoteProcessServiceImpl.java
  41. 8 1
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerRequestImpl.java
  42. 13 3
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/service/Impl/ZhongAnCrawlerRequestImpl.java
  43. 7 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/service/Impl/ZhongMeiCrawlerRequestImpl.java
  44. 63 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteRequestBuild.java
  45. 74 19
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteResultsVoBuild.java
  46. 115 37
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerSaveQuoteInfoRequestBuild.java
  47. 2 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerCacheComponent.java
  48. 19 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerRequestComponent.java
  49. 7 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQueryOrderStatusRequest.java
  50. 1 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQuotationRequest.java
  51. 54 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerUploadImageInfoListRequest.java
  52. 37 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/response/ZiJinCrawlerImageUploadInfoListResponse.java
  53. 3 2
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/enums/RequestUrl.java
  54. 2 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/ZiJinCrawlerOrderService.java
  55. 11 12
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerOrderServiceImpl.java
  56. 43 126
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerRequestImpl.java
  57. 7 0
      tenant/organization/src/main/java/com/jzg/organization/controller/AgreementRulesController.java
  58. 2 2
      tenant/organization/src/main/java/com/jzg/organization/controller/SchemeController.java
  59. 8 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/PtlAgreementUndwrtRulesMapper.java
  60. 9 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/jyxSettingMapper.java
  61. 8 0
      tenant/organization/src/main/java/com/jzg/organization/service/PtlAgreementUndwrtRulesService.java
  62. 1 1
      tenant/organization/src/main/java/com/jzg/organization/service/PtlSchemeService.java
  63. 199 23
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementUndwrtRulesServiceImpl.java
  64. 29 1
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java
  65. 1 0
      tenant/organization/src/main/resources/application.yml
  66. 12 1
      tenant/organization/src/main/resources/mapper/PtlAgreementUndwrtRulesMapper.xml
  67. 347 0
      协议承保规则接口对接文档.md

+ 3 - 5
commons/src/main/java/com/jzg/commons/entity/dto/AgreementRulesAddParam.java

@@ -2,13 +2,9 @@ package com.jzg.commons.entity.dto;
 
 import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttrLink;
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
 import lombok.Data;
 
-import java.time.LocalDateTime;
-import java.util.Date;
 import java.util.List;
 
 @Schema(description = "承保规则新增dto")
@@ -26,6 +22,8 @@ public class AgreementRulesAddParam {
     private String endTime;
 
     @Schema(description = "规则属性")
-    @NotEmpty(message = "规则属性不能为空")
     private List<PtlAgreementUndwrtRulesAttrLink> rulesAttrList;
+
+    @Schema(description = "规则属性分组(多条规则)")
+    private List<RulesGroupParam> rulesGroups;
 }

+ 8 - 5
commons/src/main/java/com/jzg/commons/entity/dto/AgreementRulesEditParam.java

@@ -2,7 +2,6 @@ package com.jzg.commons.entity.dto;
 
 import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttrLink;
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
@@ -12,10 +11,12 @@ import java.util.List;
 @Data
 public class AgreementRulesEditParam {
 
-    @NotNull(message = "承保规则id不能为空")
-    @Schema(description = "承保规则id")
+    @Schema(description = "承保规则id(单条模式)")
     private String id;
 
+    @Schema(description = "父规则ID(批量模式)")
+    private String parentId;
+
     @Schema(description = "协议id")
     @NotNull(message = "协议id不能为空")
     private String agreementId;
@@ -26,7 +27,9 @@ public class AgreementRulesEditParam {
     @Schema(description = "生效截止时间")
     private String endTime;
 
-    @Schema(description = "规则属性")
-    @NotEmpty(message = "规则属性不能为空")
+    @Schema(description = "规则属性(单条模式)")
     private List<PtlAgreementUndwrtRulesAttrLink> rulesAttrList;
+
+    @Schema(description = "规则属性分组(批量模式)")
+    private List<RulesGroupParam> rulesGroups;
 }

+ 22 - 0
commons/src/main/java/com/jzg/commons/entity/dto/RulesGroupParam.java

@@ -0,0 +1,22 @@
+package com.jzg.commons.entity.dto;
+
+import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttr;
+import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttrLink;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "规则属性分组")
+@Data
+public class RulesGroupParam {
+
+    @Schema(description = "并且规则属性")
+    @NotEmpty(message = "规则属性不能为空")
+    private List<PtlAgreementUndwrtRulesAttrLink> rulesAttrList;
+
+    @Schema(description = "费用属性")
+    private List<PtlAgreementUndwrtRulesAttr>  costsAttrLinks;
+
+}

+ 4 - 0
commons/src/main/java/com/jzg/commons/entity/po/PtlAgreementUndwrtRules.java

@@ -33,6 +33,10 @@ public class PtlAgreementUndwrtRules extends BaseModel {
     @Schema(description = "规则描述")
     private String ruleDescription;
 
+    /** 父规则ID */
+    @Schema(description = "父规则ID")
+    private String parentId;
+
     /** 显示顺序 */
     @Schema(description = "显示顺序")
     private Integer orderNum;

+ 4 - 0
commons/src/main/java/com/jzg/commons/entity/po/jyxSetting.java

@@ -27,5 +27,9 @@ public class jyxSetting extends BaseModel {
     private BigDecimal premium;
 
     private String systemCode;
+    /**
+     * 产品编码
+     */
+    private String productCode;
 
 }

+ 8 - 1
commons/src/main/java/com/jzg/commons/entity/quote/vo/base/LoginBase.java

@@ -13,7 +13,14 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 @Data
 public class LoginBase {
-
+    /**
+     * 请求类型  1 api 2 python
+     */
+    private  String apiType;
+    /**
+     * 承保机构编码
+     */
+    private String companyCode;
     /**
      * 用户名
      */

+ 8 - 0
commons/src/main/java/com/jzg/commons/entity/vo/AgreementRulesVo.java

@@ -1,6 +1,7 @@
 package com.jzg.commons.entity.vo;
 
 import com.jzg.commons.core.base.BaseModel;
+import com.jzg.commons.entity.dto.RulesGroupParam;
 import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttr;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
@@ -32,6 +33,10 @@ public class AgreementRulesVo extends BaseModel {
     @Schema(description = "规则描述")
     private String ruleDescription;
 
+    /** 父规则ID */
+    @Schema(description = "父规则ID")
+    private String parentId;
+
     /** 显示顺序 */
     @Schema(description = "显示顺序")
     private Integer orderNum;
@@ -42,4 +47,7 @@ public class AgreementRulesVo extends BaseModel {
     @Schema(description = "费用列表")
     private List<CostListVo> costVoList;
 
+    @Schema(description = "规则属性分组(多条规则)")
+    private List<RulesGroupParam> rulesGroups;
+
 }

+ 7 - 0
tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/service/impl/AnShengCrawlerRequestImpl.java

@@ -24,6 +24,8 @@ import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.component.DistributedLockComponent;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.utils.TimeProcessing;
 import lombok.RequiredArgsConstructor;
@@ -58,6 +60,11 @@ public class AnShengCrawlerRequestImpl implements AnShengCrawlerRequest {
         anShengCrawlerLoginService.login(loginBase.getUsername(), loginBase.getPassword());
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();

+ 7 - 0
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerRequestImpl.java

@@ -29,6 +29,8 @@ import com.jzg.quotation.bohai.crawler.util.PythonExecutor;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.bohai.crawler.build.BoHaiCrawlerQuoteResultsVoBuild;
 import com.jzg.quotation.bohai.crawler.component.BoHaiCrawlerRequestComponent;
@@ -99,6 +101,11 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         boHaiCrawlerQuoteProcessService.login(loginBase.getUsername(), loginBase.getPassword());
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
   public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         return boHaiCrawlerQuoteProcessService.detectLogin(detectLoginRequest);

+ 7 - 0
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/crawler/service/impl/ChengTaiCrawlerRequestImpl.java

@@ -26,6 +26,8 @@ import com.jzg.quotation.chengtai.crawler.utils.ZipImageExample;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.service.ExteriorUtilsRequest;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.commons.utils.TimeProcessing;
@@ -59,6 +61,11 @@ public class ChengTaiCrawlerRequestImpl implements ChengTaiCrawlerRequest {
         }
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public QuoteResultsVo quote(QuoteVo quoteVo) throws Exception {
 

+ 9 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/entity/GetCaptchaRequest.java

@@ -19,6 +19,15 @@ public class GetCaptchaRequest implements Serializable {
 
     @Serial
     private static final long serialVersionUID = 327592537421379864L;
+
+    /**
+     * 请求类型  1 api 2 python
+     */
+    private  String apiType;
+    /**
+     * 承保机构编码
+     */
+    private String companyCode;
     /**
      * 用户名
      */

+ 3 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/service/QuotationCrawlerBaseService.java

@@ -3,6 +3,8 @@ package com.jzg.quotation.commons.service;
 
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 
 
 /**
@@ -19,4 +21,5 @@ public interface QuotationCrawlerBaseService extends QuotationBaseService {
      */
     void login(LoginBase loginBase);
 
+    GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest);
 }

+ 7 - 0
tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/crawler/service/impl/DaJiaCrawlerRequestImpl.java

@@ -11,6 +11,8 @@ import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.commons.utils.TimeProcessing;
@@ -101,6 +103,11 @@ public class DaJiaCrawlerRequestImpl implements DaJiaCrawlerRequest {
         daJiaCrawlerQuoteProcessService.login(loginBase.getUsername(), loginBase.getPassword());
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         return daJiaCrawlerQuoteProcessService.detectLogin(detectLoginRequest);

+ 8 - 0
tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/build/GuoRenCrawlerQuoteResultsVoBuild.java

@@ -40,14 +40,22 @@ public final class GuoRenCrawlerQuoteResultsVoBuild {
                 .map(String::valueOf)
                 .orElse("0");
 
+        String bcPremium = Optional.ofNullable(calculationPremium.getBc())
+                .map(GuoRenCrawlerCalculationPremiumData.BcDTO::getPrpTmain)
+                .map(GuoRenCrawlerCalculationPremiumData.BcDTO.PrpTMainDTO::getNoCarPremium)
+                .map(String::valueOf)
+                .orElse("0");
+
         String vvTax = Optional.ofNullable(calculationPremium.getCi())
                 .map(GuoRenCrawlerCalculationPremiumData.CiDTO::getPrpTcarshipTax)
                 .map(GuoRenCrawlerCalculationPremiumData.CiDTO.PrpTcarshipTaxDTO::getSumPayTax)
                 .map(String::valueOf)
                 .orElse("0");
 
+
         quoteResultsVo.getCosts().setCiPremium(ciPremium);
         quoteResultsVo.getCosts().setBiPremium(biPremium); // 注意这里CI和BI保费相同
+        quoteResultsVo.getCosts().setNiPremium(bcPremium);
         quoteResultsVo.getCosts().setVvTax(vvTax);
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
 

+ 0 - 1
tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/request/GuoRenCrawlerProposalNoSaveRequest.java

@@ -31,7 +31,6 @@ public class GuoRenCrawlerProposalNoSaveRequest implements Serializable {
 
     public GuoRenCrawlerProposalNoSaveRequest(QuoteVo quoteVo, GuoRenCrawlerCalculationPremiumData guoRenCrawlerCalculationPremiumData, GuoRenCrawlerCalculationPremiumRequest calculationPremiumRequest) {
         this.bc = calculationPremiumRequest.getBc();
-        this.bc.setPrpTmain(guoRenCrawlerCalculationPremiumData.getBc().getPrpTmain());
         this.bc.getPrpTmain().setCaptcha("");
         this.bc.getPrpTmain().setEProposalFlag("1");
         this.basePartVo = calculationPremiumRequest.getBasePartVo();

+ 623 - 1
tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/response/GuoRenCrawlerCalculationPremiumData.java

@@ -5,8 +5,8 @@ import com.jzg.quotation.guoren.crawler.entity.dto.CiInsureDemandDTO;
 import com.jzg.quotation.guoren.crawler.entity.dto.PrptengageListDTO;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import com.jzg.quotation.guoren.crawler.entity.dto.PrpTMainDTO;
 
+import java.io.Serial;
 import java.util.List;
 
 /**
@@ -3574,6 +3574,628 @@ public class GuoRenCrawlerCalculationPremiumData extends GuoRenCrawlerBaseRespon
         @JsonProperty("prpTengiNeerList")
         private List<?> prpTengiNeerList;
 
+
+
+        @NoArgsConstructor
+        @Data
+        public class PrpTMainDTO {
+
+            @Serial
+            private static final long serialVersionUID = -1506154526496095056L;
+
+
+            @JsonProperty("agreementNo")
+            private String agreementNo;
+
+            @JsonProperty("project")
+            private String project;
+
+            @JsonProperty("cooprOutlets")
+            private String cooprOutlets;
+
+            @JsonProperty("commissionerNo")
+            private String commissionerNo;
+
+            @JsonProperty("comName")
+            private String comName;
+
+            @JsonProperty("handler1Name")
+            private String handler1Name;
+
+            @JsonProperty("agentName")
+            private String agentName;
+
+            @JsonProperty("unitMaintenanceName")
+            private String unitMaintenanceName;
+
+            @JsonProperty("unitMaintenanceType1Name")
+            private String unitMaintenanceType1Name;
+
+            @JsonProperty("channeltypeoneName")
+            private String channeltypeoneName;
+
+            @JsonProperty("unitMaintenanceType2Name")
+            private String unitMaintenanceType2Name;
+
+            @JsonProperty("channeltypetwoName")
+            private String channeltypetwoName;
+
+            /**
+             * 1 诉讼 2 裁决
+             */
+            @JsonProperty("argueSolution")
+            private String argueSolution;
+
+            @JsonProperty("arbitboardName")
+            private String arbitboardName;
+
+            @JsonProperty("isExpressProtectionFlag")
+            private String isExpressProtectionFlag;
+
+            /**
+             * 电子投保单标识 1 电子投保单  0 传统投保单
+             */
+            @JsonProperty("eProposalFlag")
+            private String eProposalFlag;
+
+            @JsonProperty("appliFactorFlag")
+            private String appliFactorFlag;
+
+            @JsonProperty("insuredFactorFlag")
+            private String insuredFactorFlag;
+
+            @JsonProperty("handler1Code")
+            private String handler1Code;
+
+            @JsonProperty("channeltypeone")
+            private String channeltypeone;
+
+            @JsonProperty("channeltypetwo")
+            private String channeltypetwo;
+
+            @JsonProperty("classIdentifier")
+            private String classIdentifier;
+
+            @JsonProperty("unitMaintenanceCode")
+            private String unitMaintenanceCode;
+
+            @JsonProperty("unitmainTenanceType1")
+            private String unitmainTenanceType1;
+
+            @JsonProperty("unitmainTenanceType2")
+            private String unitmainTenanceType2;
+
+            @JsonProperty("isStandard")
+            private String isStandard;
+
+            @JsonProperty("uwELRrel1")
+            private String uwELRrel1;
+
+            @JsonProperty("uwELRrel2")
+            private String uwELRrel2;
+
+            @JsonProperty("templateName")
+            private String templateName;
+
+            @JsonProperty("templateNo")
+            private String templateNo;
+
+            @JsonProperty("deGentType")
+            private String deGentType;
+
+            @JsonProperty("saleProfessionalNum")
+            private String saleProfessionalNum;
+
+            @JsonProperty("lifeAgentName")
+            private String lifeAgentName;
+
+            @JsonProperty("lifeAgentCode")
+            private String lifeAgentCode;
+
+            @JsonProperty("internetFlag")
+            private String internetFlag;
+
+            @JsonProperty("internetPlatform")
+            private String internetPlatform;
+
+            @JsonProperty("internetSource")
+            private String internetSource;
+
+            @JsonProperty("platformCategory")
+            private String platformCategory;
+
+            @JsonProperty("fcAgentCode")
+            private String fcAgentCode;
+
+            @JsonProperty("fcAgentName")
+            private String fcAgentName;
+
+            @JsonProperty("fcAgreementNo")
+            private String fcAgreementNo;
+
+            @JsonProperty("fcAgreementNoName")
+            private String fcAgreementNoName;
+
+            @JsonProperty("fcBusinessNature")
+            private String fcBusinessNature;
+
+            @JsonProperty("fcHandler1Code")
+            private String fcHandler1Code;
+
+            @JsonProperty("fcHandler1Name")
+            private String fcHandler1Name;
+
+            @JsonProperty("fcSaleProfessionalNum")
+            private String fcSaleProfessionalNum;
+
+            @JsonProperty("fclifeAgentName")
+            private String fclifeAgentName;
+
+            @JsonProperty("comCode")
+            private String comCode;
+
+            @JsonProperty("businessNature")
+            private String businessNature;
+
+            @JsonProperty("agentCode")
+            private String agentCode;
+
+            @JsonProperty("agentCanalCode")
+            private String agentCanalCode;
+
+            @JsonProperty("serviceStrategy")
+            private String serviceStrategy;
+
+            @JsonProperty("cooprOutletsNo")
+            private String cooprOutletsNo;
+
+            @JsonProperty("saleName")
+            private String saleName;
+
+            @JsonProperty("remark")
+            private String remark;
+
+            @JsonProperty("amlCode")
+            private String amlCode;
+
+            @JsonProperty("operateDate")
+            private String operateDate;
+
+            @JsonProperty("policySort")
+            private String policySort;
+
+            @JsonProperty("serviceLabelName")
+            private String serviceLabelName;
+
+            @JsonProperty("uniteBusinessFlag")
+            private Integer uniteBusinessFlag;
+
+            @JsonProperty("noCarFlag")
+            private Integer noCarFlag;
+
+            @JsonProperty("goodCodes")
+            private List<?> goodCodes;
+
+            @JsonProperty("noCarPremium")
+            private Integer noCarPremium;
+
+            @JsonProperty("certiNo")
+            private String certiNo;
+
+            @JsonProperty("certino1")
+            private String certino1;
+
+            @JsonProperty("business")
+            private Object business;
+
+            @JsonProperty("operatorCode")
+            private String operatorCode;
+
+            @JsonProperty("signDate")
+            private String signDate;
+
+            @JsonProperty("loginComCode")
+            private String loginComCode;
+
+            @JsonProperty("noCarCodes")
+            private String noCarCodes;
+
+            @JsonProperty("cooprOutletsName")
+            private String cooprOutletsName;
+
+            @JsonProperty("proposalNo")
+            private String proposalNo;
+
+            @JsonProperty("renewalFlag")
+            private String renewalFlag;
+
+            @JsonProperty("classCode")
+            private String classCode;
+
+            @JsonProperty("riskCode")
+            private String riskCode;
+
+            @JsonProperty("contractNo")
+            private String contractNo;
+
+            @JsonProperty("printNo")
+            private String printNo;
+
+            @JsonProperty("language")
+            private String language;
+
+            @JsonProperty("policyType")
+            private String policyType;
+
+            @JsonProperty("appliCode")
+            private String appliCode;
+
+            @JsonProperty("appliName")
+            private String appliName;
+
+            @JsonProperty("appliAddress")
+            private String appliAddress;
+
+            @JsonProperty("insuredCode")
+            private String insuredCode;
+
+            @JsonProperty("insuredName")
+            private String insuredName;
+
+            @JsonProperty("insuredAddress")
+            private String insuredAddress;
+
+
+            @JsonProperty("startDate")
+            private String startDate;
+
+            @JsonProperty("startHour")
+            private Integer startHour;
+
+            @JsonProperty("startMinute")
+            private Integer startMinute;
+
+            @JsonProperty("endMinute")
+            private Integer endMinute;
+
+            @JsonProperty("endDate")
+            private String endDate;
+
+            @JsonProperty("endHour")
+            private Integer endHour;
+
+            @JsonProperty("pureRate")
+            private Integer pureRate;
+
+            @JsonProperty("disRate")
+            private Integer disRate;
+
+            @JsonProperty("disCount")
+            private Double disCount;
+
+            @JsonProperty("currency")
+            private String currency;
+
+            @JsonProperty("sumAmount")
+            private Integer sumAmount;
+
+            @JsonProperty("sumPremium")
+            private Double sumPremium;
+
+            @JsonProperty("sumSubprem")
+            private Integer sumSubprem;
+
+            @JsonProperty("sumQuantity")
+            private Integer sumQuantity;
+
+            @JsonProperty("judicalCode")
+            private String judicalCode;
+
+            @JsonProperty("judicalScope")
+            private String judicalScope;
+
+            @JsonProperty("autoTransRenewFlag")
+            private String autoTransRenewFlag;
+
+
+            @JsonProperty("makeCom")
+            private String makeCom;
+
+            @JsonProperty("operateSite")
+            private String operateSite;
+
+
+            @JsonProperty("handlerCode")
+            private String handlerCode;
+
+
+            @JsonProperty("approverCode")
+            private String approverCode;
+
+            @JsonProperty("underWriteCode")
+            private String underWriteCode;
+
+            @JsonProperty("underWriteName")
+            private String underWriteName;
+
+
+            @JsonProperty("inputDate")
+            private String inputDate;
+
+            @JsonProperty("inputHour")
+            private Integer inputHour;
+
+            @JsonProperty("statiSticSym")
+            private String statiSticSym;
+
+
+            @JsonProperty("coinsFlag")
+            private String coinsFlag;
+
+            @JsonProperty("reinsFlag")
+            private String reinsFlag;
+
+            @JsonProperty("allinsFlag")
+            private String allinsFlag;
+
+            @JsonProperty("underwriteFlag")
+            private String underwriteFlag;
+
+            @JsonProperty("othFlag")
+            private String othFlag;
+
+            @JsonProperty("disRate1")
+            private Integer disRate1;
+
+            @JsonProperty("businessFlag")
+            private String businessFlag;
+
+            @JsonProperty("updaterCode")
+            private String updaterCode;
+
+            @JsonProperty("updateDate")
+            private String updateDate;
+
+            @JsonProperty("upDateHour")
+            private String upDateHour;
+
+            @JsonProperty("shareHolderFlag")
+            private String shareHolderFlag;
+
+            @JsonProperty("inquiryNo")
+            private String inquiryNo;
+
+            @JsonProperty("payMode")
+            private String payMode;
+
+            @JsonProperty("policyNo")
+            private String policyNo;
+
+            @JsonProperty("visaCode")
+            private String visaCode;
+
+            @JsonProperty("manualType")
+            private String manualType;
+
+            @JsonProperty("businessKind")
+            private String businessKind;
+
+            @JsonProperty("businessClass")
+            private String businessClass;
+
+            @JsonProperty("manualFlag")
+            private String manualFlag;
+
+            @JsonProperty("businessRemark1")
+            private String businessRemark1;
+
+            @JsonProperty("businessRemark2")
+            private String businessRemark2;
+
+            @JsonProperty("domesticFlag")
+            private String domesticFlag;
+
+            @JsonProperty("ventureFlag")
+            private String ventureFlag;
+
+            @JsonProperty("bidFlag")
+            private String bidFlag;
+
+            @JsonProperty("agriFlag")
+            private String agriFlag;
+
+            @JsonProperty("agriNature")
+            private String agriNature;
+
+            @JsonProperty("groupPurchaseFlag")
+            private String groupPurchaseFlag;
+
+            @JsonProperty("productCode")
+            private String productCode;
+
+            @JsonProperty("payMethod")
+            private String payMethod;
+
+            @JsonProperty("immeValiFlag")
+            private String immeValiFlag;
+
+            @JsonProperty("lifeManageComCode")
+            private String lifeManageComCode;
+
+            @JsonProperty("lifeChannelType")
+            private String lifeChannelType;
+
+            @JsonProperty("lifeSalecomCode")
+            private String lifeSalecomCode;
+
+            @JsonProperty("lifeAppcontNo")
+            private String lifeAppcontNo;
+
+            @JsonProperty("saleMobile")
+            private String saleMobile;
+
+            @JsonProperty("isPersonal")
+            private String isPersonal;
+
+            @JsonProperty("subRiskCode")
+            private String subRiskCode;
+
+            @JsonProperty("ePolicySort")
+            private String ePolicySort;
+
+            @JsonProperty("policyUrl")
+            private String policyUrl;
+
+            @JsonProperty("captcha")
+            private String captcha;
+
+            @JsonProperty("eFlag")
+            private String eFlag;
+
+            @JsonProperty("uploadTime")
+            private String uploadTime;
+
+            @JsonProperty("businessNatureNew")
+            private String businessNatureNew;
+
+            @JsonProperty("groupBuySize")
+            private Integer groupBuySize;
+
+            @JsonProperty("businessMark")
+            private String businessMark;
+
+            @JsonProperty("mainBankName")
+            private String mainBankName;
+
+            @JsonProperty("otherBankName")
+            private String otherBankName;
+
+            @JsonProperty("sumnoTaxPremium")
+            private Double sumnoTaxPremium;
+
+            @JsonProperty("sumTaxFee")
+            private Double sumTaxFee;
+
+            @JsonProperty("linkerName")
+            private String linkerName;
+
+            @JsonProperty("linkerMobile")
+            private String linkerMobile;
+
+            @JsonProperty("linkerAddress")
+            private String linkerAddress;
+
+            @JsonProperty("dataSourceCode")
+            private String dataSourceCode;
+
+            @JsonProperty("policySequenceNo")
+            private String policySequenceNo;
+
+            @JsonProperty("underwritSequenceNo")
+            private String underwritSequenceNo;
+
+            @JsonProperty("infoManagerFlag")
+            private String infoManagerFlag;
+
+            @JsonProperty("teamCode")
+            private String teamCode;
+
+            @JsonProperty("teamName")
+            private String teamName;
+
+            @JsonProperty("teamTypeId")
+            private String teamTypeId;
+
+            @JsonProperty("teamTypeIdName")
+            private String teamTypeIdName;
+
+            @JsonProperty("teamTypeTwo")
+            private String teamTypeTwo;
+
+            @JsonProperty("teamTypeTwoName")
+            private String teamTypeTwoName;
+
+            @JsonProperty("teamTypeThree")
+            private String teamTypeThree;
+
+            @JsonProperty("teamTypeThreeName")
+            private String teamTypeThreeName;
+
+            @JsonProperty("customerGroupName")
+            private String customerGroupName;
+
+            @JsonProperty("businessNatureOne")
+            private String businessNatureOne;
+
+            @JsonProperty("businessNatureOneName")
+            private String businessNatureOneName;
+
+            @JsonProperty("businessNatureThree")
+            private String businessNatureThree;
+
+            @JsonProperty("businessNatureTwo")
+            private String businessNatureTwo;
+
+            @JsonProperty("businessNatureTwoName")
+            private String businessNatureTwoName;
+
+            @JsonProperty("businessNaturethreeName")
+            private String businessNaturethreeName;
+
+            @JsonProperty("feeandDiscountFlag")
+            private Integer feeandDiscountFlag;
+
+            @JsonProperty("saleChange")
+            private Double saleChange;
+
+            @JsonProperty("oaFlowNumber")
+            private String oaFlowNumber;
+
+            @JsonProperty("upDateTime")
+            private String upDateTime;
+
+            @JsonProperty("underWriteendTime")
+            private String underWriteendTime;
+
+            @JsonProperty("answer")
+            private String answer;
+
+            @JsonProperty("orderNo")
+            private String orderNo;
+
+            @JsonProperty("simpleOrderFlag")
+            private String simpleOrderFlag;
+
+            @JsonProperty("hisOrderNo")
+            private String hisOrderNo;
+
+            @JsonProperty("startDateFlag")
+            private String startDateFlag;
+
+            @JsonProperty("saleGentType")
+            private String saleGentType;
+
+            @JsonProperty("demandNo")
+            private String demandNo;
+
+            @JsonProperty("correction_applicant")
+            private String correctionApplicant;
+
+
+            @JsonProperty("firstProposalDate")
+            private String firstProposalDate;
+
+            @JsonProperty("isbatchProposalNo")
+            private String isbatchProposalNo;
+
+            @JsonProperty("carsonlyid")
+            private String carsonlyid;
+
+            @JsonProperty("flag")
+            private String flag;
+
+        }
+
         @NoArgsConstructor
         @Data
         public static class PrpTitemCarDTO {

+ 7 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/service/Impl/GuoshouCrawlerRequestImpl.java

@@ -16,6 +16,8 @@ import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.client.OrgClient;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.guoshou.crawler.component.GsCrawlerLoginComponent;
 import com.jzg.quotation.guoshou.crawler.component.GsCrawlerRequestComponent;
@@ -71,6 +73,11 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
 
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();

+ 7 - 0
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/service/Impl/HengBangCrawlerRequestImpl.java

@@ -25,6 +25,8 @@ import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.commons.utils.DateTimeUtil;
@@ -83,6 +85,11 @@ public class HengBangCrawlerRequestImpl implements HengBangCrawlerRequest {
         hbCrawlerRequestComponent.authenticate(loginBase.getUsername(), loginBase.getPassword(), RequestConstant.REQUEST_NUMBER);
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();

+ 8 - 2
tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/build/HuaNongCrawlerQuoteResultsVoBuild.java

@@ -64,7 +64,7 @@ public final class HuaNongCrawlerQuoteResultsVoBuild {
                 // 商业险
                 buildKindInfo(quoteVo.getKindInfoVo(), contractDTO.getCoverage());
                 buildRiskInfoVo(quoteVo.getBiRiskInfoVo(), contractDTO.getContractMain(), contractDTO.getPlatFormMessage(), false);
-                quoteResultsVo.getCosts().setBiPremium(String.valueOf(contractDTO.getContractMain().getBiTotalpremium()));
+                quoteResultsVo.getCosts().setBiPremium(String.valueOf(contractDTO.getContractMain().getTotalPremium()));
                 quoteResultsVo.setBiPolicyNumber(contractDTO1.getContractMain().getContractNo());
             }
         });
@@ -72,7 +72,13 @@ public final class HuaNongCrawlerQuoteResultsVoBuild {
         quoteResultsVo.setScoreVo(buildScoreVo(huaNongCrawlerQuotedPriceResponse));
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
         quoteResultsVo.setCiRiskInfoVo(quoteVo.getCiRiskInfoVo());
-        quoteResultsVo.setBiRiskInfoVo(quoteVo.getBiRiskInfoVo());
+        RiskInfoVo biRiskInfo = quoteVo.getBiRiskInfoVo();
+        if(biRiskInfo != null && quoteVo.getCiRiskInfoVo() != null){
+            biRiskInfo.setStartDate(quoteVo.getCiRiskInfoVo().getStartDate());
+            biRiskInfo.setEndDate(quoteVo.getCiRiskInfoVo().getEndDate());
+        }
+
+        quoteResultsVo.setBiRiskInfoVo(biRiskInfo);
         return quoteResultsVo;
     }
 

+ 120 - 131
tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/service/impl/HuaNongCrawlerRequestImpl.java

@@ -13,6 +13,8 @@ import com.jzg.commons.entity.quote.vo.identify.ReinsuranceCaptchaVo;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.service.ExteriorUtilsRequest;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
@@ -63,6 +65,11 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
         huaNongCrawlerQuoteProcessService.login(loginBase.getUsername(), loginBase.getPassword(), null, true);
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();
@@ -316,7 +323,8 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
             boolean isCiDuplicate = StringUtils.hasText(ciReinsureMsg) &&
                     (ciReinsureMsg.contains("重复投保") || ciReinsureMsg.contains("终保日期"));
             boolean isBiDuplicate = StringUtils.hasText(biReinsureMsg) &&
-                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期"));
+                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期")
+                            || biReinsureMsg.contains("保期:["));
 
             if (isCiDuplicate || isBiDuplicate) {
                 hasDuplicateInsurance = true;
@@ -344,25 +352,45 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
             HuaNongCrawlerQuotedPriceResponse response,
             HttpHeaders httpHeaders) {
 
+        // 收集所有contract中的重复投保信息(与Python一致:遍历所有contract汇总)
+        String ciReinsureEndDate = null;
+        String ciReinsureMessage = null;
+        String biReinsureEndDate = null;
+        String biReinsureMessage = null;
+
         for (HuaNongCrawlerQuotedPriceResponse.BusinessDataDTO.ContractDTO contract : response.getBusinessData().getContract()) {
             if (contract.getPlatFormMessage() == null) {
                 continue;
             }
-
-            String riskCode = contract.getContractMain().getRiskCode();
-            String ciReinsureMsg = contract.getPlatFormMessage().getCiReinsureMessage();
-            String biReinsureMsg = contract.getPlatFormMessage().getBiReinsureMessage();
-
-            boolean needAdjustCi = "0507".equals(riskCode) &&
-                    StringUtils.hasText(ciReinsureMsg) &&
-                    (ciReinsureMsg.contains("重复投保") || ciReinsureMsg.contains("终保日期"));
-
-            boolean needAdjustBi = ("0510".equals(riskCode) || "0515".equals(riskCode)) &&
-                    StringUtils.hasText(biReinsureMsg) &&
-                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期"));
-
-            if (needAdjustCi || needAdjustBi) {
-                adjustPolicyDate(request, riskCode, contract);
+            String ciEnd = contract.getPlatFormMessage().getCiReinsureEndDate();
+            String ciMsg = contract.getPlatFormMessage().getCiReinsureMessage();
+            String biEnd = contract.getPlatFormMessage().getBiReinsureEndDate();
+            String biMsg = contract.getPlatFormMessage().getBiReinsureMessage();
+
+            if (StringUtils.hasText(ciEnd)) ciReinsureEndDate = ciEnd;
+            if (StringUtils.hasText(ciMsg)) ciReinsureMessage = ciMsg;
+            if (StringUtils.hasText(biEnd)) biReinsureEndDate = biEnd;
+            if (StringUtils.hasText(biMsg)) biReinsureMessage = biMsg;
+        }
+
+        // 与Python一致:三个触发条件
+        boolean ciTrigger = StringUtils.hasText(ciReinsureEndDate)
+                && StringUtils.hasText(ciReinsureMessage)
+                && ciReinsureMessage.contains("终保日期");
+        boolean biTrigger1 = StringUtils.hasText(biReinsureEndDate)
+                && StringUtils.hasText(biReinsureMessage)
+                && biReinsureMessage.contains("终保日期");
+        boolean biTrigger2 = StringUtils.hasText(biReinsureEndDate)
+                && StringUtils.hasText(biReinsureMessage)
+                && biReinsureMessage.contains("保期:[");
+
+        if (ciTrigger || biTrigger1 || biTrigger2) {
+            // 与Python一致:交强险和商业险的起保日期同时更新
+            if (StringUtils.hasText(ciReinsureEndDate)) {
+                adjustPolicyDate(request, "0507", ciReinsureEndDate);
+            }
+            if (StringUtils.hasText(biReinsureEndDate)) {
+                adjustPolicyDate(request, "0510", biReinsureEndDate);
             }
         }
 
@@ -386,7 +414,8 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
             boolean isCiDuplicate = StringUtils.hasText(ciReinsureMsg) &&
                     (ciReinsureMsg.contains("重复投保") || ciReinsureMsg.contains("终保日期"));
             boolean isBiDuplicate = StringUtils.hasText(biReinsureMsg) &&
-                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期"));
+                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期")
+                            || biReinsureMsg.contains("保期:["));
 
             if (isCiDuplicate || isBiDuplicate) {
                 return true;
@@ -401,63 +430,89 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
             HuaNongCrawlerQuotedPriceResponse response,
             HttpHeaders httpHeaders) {
 
+        // 收集所有contract中的重复投保信息
+        String ciReinsureEndDate = null;
+        String ciReinsureMessage = null;
+        String biReinsureEndDate = null;
+        String biReinsureMessage = null;
+
         for (HuaNongCrawlerQuotedPriceResponse.BusinessDataDTO.ContractDTO contract : response.getBusinessData().getContract()) {
             if (contract.getPlatFormMessage() == null) {
                 continue;
             }
-
-            String riskCode = contract.getContractMain().getRiskCode();
-            String ciReinsureMsg = contract.getPlatFormMessage().getCiReinsureMessage();
-            String biReinsureMsg = contract.getPlatFormMessage().getBiReinsureMessage();
-
-            boolean needAdjustCi = "0507".equals(riskCode) &&
-                    StringUtils.hasText(ciReinsureMsg) &&
-                    (ciReinsureMsg.contains("重复投保") || ciReinsureMsg.contains("终保日期"));
-
-            boolean needAdjustBi = ("0510".equals(riskCode) || "0515".equals(riskCode)) &&
-                    StringUtils.hasText(biReinsureMsg) &&
-                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期"));
-
-            if (needAdjustCi || needAdjustBi) {
-                adjustPolicyDateWithOneMoreDay(request, riskCode, contract);
+            String ciEnd = contract.getPlatFormMessage().getCiReinsureEndDate();
+            String ciMsg = contract.getPlatFormMessage().getCiReinsureMessage();
+            String biEnd = contract.getPlatFormMessage().getBiReinsureEndDate();
+            String biMsg = contract.getPlatFormMessage().getBiReinsureMessage();
+
+            if (StringUtils.hasText(ciEnd)) ciReinsureEndDate = ciEnd;
+            if (StringUtils.hasText(ciMsg)) ciReinsureMessage = ciMsg;
+            if (StringUtils.hasText(biEnd)) biReinsureEndDate = biEnd;
+            if (StringUtils.hasText(biMsg)) biReinsureMessage = biMsg;
+        }
+
+        // 与Python一致:三个触发条件
+        boolean ciTrigger = StringUtils.hasText(ciReinsureEndDate)
+                && StringUtils.hasText(ciReinsureMessage)
+                && ciReinsureMessage.contains("终保日期");
+        boolean biTrigger1 = StringUtils.hasText(biReinsureEndDate)
+                && StringUtils.hasText(biReinsureMessage)
+                && biReinsureMessage.contains("终保日期");
+        boolean biTrigger2 = StringUtils.hasText(biReinsureEndDate)
+                && StringUtils.hasText(biReinsureMessage)
+                && biReinsureMessage.contains("保期:[");
+
+        if (ciTrigger || biTrigger1 || biTrigger2) {
+            // 与Python一致:交强险和商业险的起保日期同时更新,日期+1天
+            if (StringUtils.hasText(ciReinsureEndDate)) {
+                adjustPolicyDateWithPlusOne(request, "0507", ciReinsureEndDate);
+            }
+            if (StringUtils.hasText(biReinsureEndDate)) {
+                adjustPolicyDateWithPlusOne(request, "0510", biReinsureEndDate);
             }
         }
 
         return huaNongCrawlerRequestComponent.quotedPrice(request, httpHeaders);
     }
 
-    private void adjustPolicyDateWithOneMoreDay(HuaNongCrawlerQuotedPriceRequestRequest request,
-                                                 String riskCode, HuaNongCrawlerQuotedPriceResponse.BusinessDataDTO.ContractDTO contract) {
-
-        String lastExpireDate = "";
-
-        if ("0507".equals(riskCode)) {
-            lastExpireDate = contract.getPlatFormMessage().getCiReinsureEndDate();
-        } else if ("0510".equals(riskCode) || "0515".equals(riskCode)) {
-            String biReinsureEndDate = contract.getPlatFormMessage().getBiReinsureEndDate();
-            String lastPolicyExpireDate = contract.getPlatFormMessage().getLastPolicyExpireDate();
-
-            if (StringUtils.hasText(biReinsureEndDate)) {
-                lastExpireDate = biReinsureEndDate;
-            } else if (StringUtils.hasText(lastPolicyExpireDate)) {
-                lastExpireDate = lastPolicyExpireDate;
-            }
-        }
-
-        if (StringUtils.hasText(lastExpireDate)) {
-            lastExpireDate = ensureDateTimeFormat(lastExpireDate);
-            lastExpireDate = plusOneDayDateTime(lastExpireDate);
+    /**
+     * 调整保单日期(与Python get_contract 一致:更新contractMain + 全部coverage的validDate和expiryDate)
+     */
+    private void adjustPolicyDate(HuaNongCrawlerQuotedPriceRequestRequest request,
+                                  String riskCode, String lastExpireDate) {
+        lastExpireDate = ensureDateTimeFormat(lastExpireDate);
+        applyDateToContract(request, riskCode, lastExpireDate);
+    }
 
-            String finalLastExpireDate = lastExpireDate;
-            request.getBusinessData().getContract().stream()
-                    .filter(dto -> riskCode.equals(dto.getContractMain().getRiskCode()))
-                    .findFirst()
-                    .ifPresent(dto -> {
-                        dto.getContractMain().setValidDate(finalLastExpireDate);
-                        dto.getContractMain().setExpiryDate(TimeProcessing.minusOneSecondAfterYear(finalLastExpireDate));
-                        dto.getCoverage().get(0).setValidDate(finalLastExpireDate);
-                    });
-        }
+    /**
+     * 调整保单日期并+1天(第二次重试用)
+     */
+    private void adjustPolicyDateWithPlusOne(HuaNongCrawlerQuotedPriceRequestRequest request,
+                                             String riskCode, String lastExpireDate) {
+        lastExpireDate = ensureDateTimeFormat(lastExpireDate);
+        lastExpireDate = plusOneDayDateTime(lastExpireDate);
+        applyDateToContract(request, riskCode, lastExpireDate);
+    }
+    /**
+     * 将日期应用到请求中的contract:更新contractMain和全部coverage的validDate、expiryDate
+     */
+    private void applyDateToContract(HuaNongCrawlerQuotedPriceRequestRequest request,
+                                     String riskCode, String finalLastExpireDate) {
+        String expiryDate = TimeProcessing.minusOneSecondAfterYear(finalLastExpireDate);
+        request.getBusinessData().getContract().stream()
+                .filter(dto -> riskCode.equals(dto.getContractMain().getRiskCode()))
+                .findFirst()
+                .ifPresent(dto -> {
+                    dto.getContractMain().setValidDate(finalLastExpireDate);
+                    dto.getContractMain().setExpiryDate(expiryDate);
+                    // 与Python get_contract 一致:所有coverage都更新validDate和expiryDate
+                    if (dto.getCoverage() != null) {
+                        dto.getCoverage().forEach(cov -> {
+                            cov.setValidDate(finalLastExpireDate);
+                            cov.setExpiryDate(expiryDate);
+                        });
+                    }
+                });
     }
 
     private String plusOneDayDateTime(String dateTime) {
@@ -465,42 +520,6 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
         return localDateTime.plusDays(1).format(TimeProcessing.DATE_TIME_FORMATTER);
     }
 
-    private void adjustPolicyDate(HuaNongCrawlerQuotedPriceRequestRequest request,
-                                  String riskCode, HuaNongCrawlerQuotedPriceResponse.BusinessDataDTO.ContractDTO contract) {
-
-        String lastExpireDate = "";
-
-        if ("0507".equals(riskCode)) {
-            // 交强险:优先使用 ciReinsureEndDate
-            lastExpireDate = contract.getPlatFormMessage().getCiReinsureEndDate();
-        } else if ("0510".equals(riskCode) || "0515".equals(riskCode)) {
-            // 商业险:优先使用 biReinsureEndDate,其次使用 lastPolicyExpireDate
-            String biReinsureEndDate = contract.getPlatFormMessage().getBiReinsureEndDate();
-            String lastPolicyExpireDate = contract.getPlatFormMessage().getLastPolicyExpireDate();
-
-            if (StringUtils.hasText(biReinsureEndDate)) {
-                lastExpireDate = biReinsureEndDate;
-            } else if (StringUtils.hasText(lastPolicyExpireDate)) {
-                lastExpireDate = lastPolicyExpireDate;
-            }
-        }
-
-        if (StringUtils.hasText(lastExpireDate)) {
-            // 统一日期格式
-            lastExpireDate = ensureDateTimeFormat(lastExpireDate);
-
-            String finalLastExpireDate = lastExpireDate;
-            request.getBusinessData().getContract().stream()
-                    .filter(dto -> riskCode.equals(dto.getContractMain().getRiskCode()))
-                    .findFirst()
-                    .ifPresent(dto -> {
-                        dto.getContractMain().setValidDate(finalLastExpireDate);
-                        dto.getContractMain().setExpiryDate(TimeProcessing.minusOneSecondAfterYear(finalLastExpireDate));
-                        dto.getCoverage().get(0).setValidDate(finalLastExpireDate);
-                    });
-        }
-    }
-
     private HuaNongCrawlerQuotedPriceResponse checkAndHandleRemainingDuplicate(HuaNongCrawlerQuotedPriceResponse response, boolean throwException) {
         if (response == null || response.getBusinessData() == null ||
                 response.getBusinessData().getContract() == null) {
@@ -520,7 +539,8 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
             boolean stillCiDuplicate = StringUtils.hasText(ciReinsureMsg) &&
                     (ciReinsureMsg.contains("重复投保") || ciReinsureMsg.contains("终保日期"));
             boolean stillBiDuplicate = StringUtils.hasText(biReinsureMsg) &&
-                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期"));
+                    (biReinsureMsg.contains("重复投保") || biReinsureMsg.contains("终保日期")
+                            || biReinsureMsg.contains("保期:["));
 
             if (stillCiDuplicate) {
                 if (errorMsg.length() > 0) {
@@ -579,37 +599,6 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
     }
 
 
-    // 处理重复投保
-    private HuaNongCrawlerQuotedPriceResponse repeatQuote(HuaNongCrawlerQuotedPriceRequestRequest huaNongCrawlerQuotedPriceRequest, HuaNongCrawlerQuotedPriceResponse.BusinessDataDTO.ContractDTO contract, HttpHeaders httpHeaders) {
-        String riskCode = contract.getContractMain().getRiskCode();
-        if ("0510".equals(riskCode) || "0515".equals(riskCode)) {
-            String lastExpireDate = contract.getPlatFormMessage().getLastPolicyExpireDate();
-            if (lastExpireDate != null && !lastExpireDate.trim().isEmpty()) {
-                final String finalRiskCode = riskCode;
-                huaNongCrawlerQuotedPriceRequest.getBusinessData().getContract().stream()
-                        .filter(dto -> finalRiskCode.equals(dto.getContractMain().getRiskCode()))
-                        .findFirst()
-                        .ifPresent(dto -> {
-                            dto.getContractMain().setValidDate(lastExpireDate);
-                            dto.getContractMain().setExpiryDate(TimeProcessing.minusOneSecondAfterYear(lastExpireDate));
-                        });
-            }
-        } else if ("0507".equals(riskCode)) {
-            String lastExpireDate = ensureDateTimeFormat(contract.getPlatFormMessage().getCiReinsureEndDate());
-            ;
-            if (lastExpireDate != null && !lastExpireDate.trim().isEmpty()) {
-                huaNongCrawlerQuotedPriceRequest.getBusinessData().getContract().stream()
-                        .filter(dto -> "0507".equals(dto.getContractMain().getRiskCode()))
-                        .findFirst()
-                        .ifPresent(dto -> {
-                            dto.getContractMain().setValidDate(lastExpireDate);
-                            dto.getContractMain().setExpiryDate(TimeProcessing.minusOneSecondAfterYear(lastExpireDate));
-                        });
-            }
-        }
-        return huaNongCrawlerRequestComponent.quotedPrice(huaNongCrawlerQuotedPriceRequest, httpHeaders);
-    }
-
     public String ensureDateTimeFormat(String dateStr) {
         if (dateStr == null || dateStr.trim().isEmpty()) {
             return "";

+ 7 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java

@@ -17,6 +17,8 @@ import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.entity.quote.vo.base.OrderBase;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.commons.utils.HtEncryptDecryptUtils;
@@ -122,6 +124,11 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
 
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
   public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();

+ 7 - 0
tenant/insurance/quotation-renbao/src/main/java/com/jzg/quotation/renbao/crawler/service/impl/RenBaoCrawlerRequestImpl.java

@@ -8,6 +8,8 @@ import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.renbao.crawler.component.RenBaoCrawlerRequestComponent;
 import com.jzg.quotation.renbao.crawler.constant.enums.ClauseTypeEnum;
 import com.jzg.quotation.renbao.crawler.entity.dto.PrpCinsuredsDTO;
@@ -38,6 +40,11 @@ public class RenBaoCrawlerRequestImpl implements RenBaoCrawlerRequest {
 
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
   public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();

+ 7 - 0
tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestImpl.java

@@ -10,6 +10,8 @@ import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.renbaonew.crawler.component.RenBaoNewCrawlerCacheComponent;
 import com.jzg.quotation.renbaonew.crawler.component.RenBaoNewCrawlerRequestComponent;
@@ -66,6 +68,11 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
         getTokenService.getToken(loginBase.getUsername(), loginBase.getPassword());
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         return getTokenService.detectLogin(detectLoginRequest);

+ 7 - 0
tenant/insurance/quotation-shenneng/src/main/java/com/jzg/quotation/shenneng/crawler/service/impl/ShenNengCrawlerRequestImpl.java

@@ -6,6 +6,8 @@ import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.shenneng.crawler.service.ShenNengCrawlerLoginService;
 import com.jzg.quotation.shenneng.crawler.service.ShenNengCrawlerRequest;
 import lombok.RequiredArgsConstructor;
@@ -22,6 +24,11 @@ public class ShenNengCrawlerRequestImpl implements ShenNengCrawlerRequest {
         shenNengCrawlerLoginService.login(loginBase.getUsername(), loginBase.getPassword());
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         return shenNengCrawlerLoginService.detectLogin(detectLoginRequest);

+ 10 - 2
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/UnifyOrderManager.java

@@ -40,6 +40,7 @@ import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
 import com.jzg.quotation.commons.entity.GetCaptchaRequest;
 import com.jzg.quotation.commons.service.QuotationBaseService;
+import com.jzg.quotation.commons.service.QuotationCrawlerBaseService;
 import com.jzg.quotation.commons.utils.SnowFlakeUtil;
 import com.jzg.quotation.guoren.crawler.service.GuoRenCrawlerRequest;
 import com.jzg.quotation.summary.aop.AuditVerification;
@@ -1001,14 +1002,21 @@ public class UnifyOrderManager {
     @PostMapping("guoRenlogin")
     @Operation(summary = "国任登录")
     public HttpResult guoRenlogin(@RequestBody LoginBase loginBase) {
-        guoRenCrawlerRequest.login(loginBase);
+//        guoRenCrawlerRequest.login(loginBase);
+//        return HttpResult.ok();
+
+        QuotationCrawlerBaseService loginService = companyFactory.getLoginService(loginBase);
+
+        loginService.login(loginBase);
         return HttpResult.ok();
     }
 
     @PostMapping("getGuoRenCaptcha")
     @Operation(summary = "国任登录验证码")
     public HttpResult getGuoRenCaptcha(@RequestBody GetCaptchaRequest sendCaptchaRequest) {
-        return HttpResult.ok(guoRenCrawlerRequest.getCaptcha(sendCaptchaRequest));
+        QuotationCrawlerBaseService captchaService = companyFactory.getCaptchaService(sendCaptchaRequest);
+        //return HttpResult.ok(guoRenCrawlerRequest.getCaptcha(sendCaptchaRequest));
+        return HttpResult.ok(captchaService.getCaptcha(sendCaptchaRequest));
     }
 
     @PostMapping("/detectLogin")

+ 34 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/factory/CompanyFactory.java

@@ -10,12 +10,14 @@ import com.jzg.commons.entity.orders.po.*;
 import com.jzg.commons.entity.po.EsmInsCompany;
 import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
+import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.exception.SystemException;
 import com.jzg.commons.util.AssertionUtils;
 import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.commons.constants.quote.enums.base.ApiType;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
 import com.jzg.quotation.commons.service.QuotationApiBaseService;
 import com.jzg.quotation.commons.service.QuotationBaseService;
 import com.jzg.quotation.commons.service.QuotationCrawlerBaseService;
@@ -115,6 +117,38 @@ public class CompanyFactory {
         return service;
     }
 
+
+    public QuotationCrawlerBaseService getCaptchaService(GetCaptchaRequest sendCaptchaRequest) {
+        // 获取service
+        QuotationCrawlerBaseService service = getQuotationBaseInfo(Integer.parseInt(sendCaptchaRequest.getApiType()), sendCaptchaRequest.getCompanyCode());
+
+        return service;
+    }
+
+    public QuotationCrawlerBaseService getLoginService(LoginBase loginBase) {
+        // 获取service
+        QuotationCrawlerBaseService service = getQuotationBaseInfo(Integer.parseInt(loginBase.getApiType()), loginBase.getCompanyCode());
+
+        return service;
+    }
+
+
+    private QuotationCrawlerBaseService getQuotationBaseInfo(int apiType, String insuranceCode) {
+        log.info("quotationCrawlerBaseServiceMap参数的值:{}", com.alibaba.fastjson.JSON.toJSONString(quotationCrawlerBaseServiceMap));
+
+        String s = extractEnglishChars(insuranceCode);
+        QuotationCrawlerBaseService quotationApiBaseService = null;
+        String s1 = s + apiType;
+        if (ApiType.API_2.getCode() == apiType) {
+            quotationApiBaseService = quotationCrawlerBaseServiceMap.get(s1);
+        }
+        if (!ObjectUtils.isEmpty(quotationApiBaseService)) {
+            return quotationApiBaseService;
+        }
+        log.error("报价类型出错,请联系管理员:apiType=[{}],insuranceCode=[{}]", apiType, insuranceCode);
+        throw new SystemException("报价类型出错,请联系管理员处理。");
+    }
+
     /**
      * 获取保司实体
      *

+ 7 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/impl/TKQuotationBaseServiceImpl.java

@@ -16,6 +16,8 @@ import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.taikang.crawler.ConvertUtil;
 import com.jzg.quotation.taikang.crawler.cache.RedisCacheUtil;
 import com.jzg.quotation.taikang.crawler.client.AESDecryptor;
@@ -112,6 +114,11 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
 
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public QuoteResultsVo quote(QuoteVo commonQuoteVo) {
         CarInfoVo commonCarInfoVo = commonQuoteVo.getCarInfoVo();

+ 7 - 0
tenant/insurance/quotation-taipingyang/src/main/java/com/jzg/quotation/taipingyang/crawler/service/impl/TaiPingYangCrawlerRequestImpl.java

@@ -7,6 +7,8 @@ import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.CookiesRequest;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.taipingyang.crawler.component.TaiPingYangCrawlerRequestComponent;
 import com.jzg.quotation.taipingyang.crawler.entity.request.TaiPingYangCrawlerCarInfoRequest;
@@ -34,6 +36,11 @@ public class TaiPingYangCrawlerRequestImpl implements TaiPingYangCrawlerRequest
 
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         return taiPingYangCrawlerQuoteProcessService.detectLogin(detectLoginRequest);

+ 1 - 1
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/component/TaiShanCrawlerRequestComponent.java

@@ -157,7 +157,7 @@ public class TaiShanCrawlerRequestComponent {
      * @return
      */
     public TaiShanCrawlerLoginResponse login(TaiShanCrawlerLoginRequest request, HttpHeaders headers) {
-        TaiShanCrawlerLoginResponse response = post(RequestUrl.CONFIRM, request, TaiShanCrawlerLoginResponse.class, headers);
+        TaiShanCrawlerLoginResponse response = post(RequestUrl.AUTHENTICATE, request, TaiShanCrawlerLoginResponse.class, headers);
         return response;
     }
 

+ 2 - 0
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/constant/enums/RequestUrl.java

@@ -10,6 +10,8 @@ public enum RequestUrl {
     HUAKUAI("/api_prod/auth/api/base/base_anji/get", "获取滑块验证码"),
     CHECK("/api_prod/auth/api/base/base_anji/check", "滑块校验"),
 
+    // 登录认证
+    AUTHENTICATE("/api_prod/auth/api/authenticate", "登录认证"),
 
     // 车辆相关
     CAR("/api_prod/ins/api/search/vehicle", "车型查询"),

+ 4 - 2
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanCrawlerLoginRequest.java

@@ -37,9 +37,11 @@ public class TaiShanCrawlerLoginRequest implements Serializable {
         StringBuffer aesSb = new StringBuffer();
         aesSb.append(token + "---");
         aesSb.append(aesRes);
-        String captchaVerification = TaiShanCrawlerUtils.aesEncrypt(aesSb.toString(), secretKey);
+        //String captchaVerification = TaiShanCrawlerUtils.aesEncrypt(aesSb.toString(), secretKey);
+        String captchaVerification = "";
         this.username = loginBase.getUsername();
-        this.password = TaiShanCrawlerUtils.desEncrypt(loginBase.getPassword(),"chdAdmin");
+        //this.password = TaiShanCrawlerUtils.desEncrypt(loginBase.getPassword(),"chdAdmin");
+        this.password = loginBase.getPassword();
         this.rememberMe = true;
         this.smsCode = loginBase.getCaptcha();
         this.code = captchaVerification;

+ 6 - 6
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanCrawlerSmsCodeRequest.java

@@ -1,6 +1,5 @@
 package com.jzg.quotation.taishan.crawler.entity.request;
 
-import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.jzg.quotation.taishan.crawler.entity.response.TaiShanCrawlerVerifyResponse;
 import com.jzg.quotation.taishan.crawler.util.TaiShanCrawlerUtils;
@@ -30,11 +29,12 @@ public class TaiShanCrawlerSmsCodeRequest implements Serializable {
     public TaiShanCrawlerSmsCodeRequest(TaiShanCrawlerVerifyResponse verifyResponse, List<Integer> integers, List<Integer> sizeList, String password, String username){
         int x = integers.get(0);
         int width = sizeList.get(0);
-        int t = 310 * x / width;
-        JSONObject pointJson = new JSONObject();
-        pointJson.put("x", x);
-        pointJson.put("y", 5);
-        String encryptedPointJson = TaiShanCrawlerUtils.aesEncrypt(pointJson.toJSONString(), verifyResponse.getRepData().getSecretKey());
+        // 参考Python实现:t = 310 * t / setSize_imgWidth (浮点除法)
+        double t = 310.0 * x / width;
+        // 参考Python实现:point_json = '{"x":'+str(t)+',"y":5}'
+        // 手动拼接字符串,确保与Python格式完全一致,避免JSONObject序列化差异
+        String pointJsonStr = "{\"x\":" + t + ",\"y\":5}";
+        String encryptedPointJson = TaiShanCrawlerUtils.aesEncrypt(pointJsonStr, verifyResponse.getRepData().getSecretKey());
         String crtm = TaiShanCrawlerUtils.desEncrypt(password,"chdAdmin");
         this.captchaVO = new CaptchaVODTO(encryptedPointJson, verifyResponse.getRepData().getToken());
         this.userId = username;

+ 3 - 2
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanCrawlerVerifyRequest.java

@@ -19,11 +19,12 @@ public class TaiShanCrawlerVerifyRequest implements Serializable {
     @JsonProperty("clientUid")
     private String clientUid;
     @JsonProperty("ts")
-    private double ts;
+    private long ts;
 
     public TaiShanCrawlerVerifyRequest(String clientUid) {
         this.captchaType = "blockPuzzle";
         this.clientUid = clientUid;
-        this.ts = System.currentTimeMillis() / 1000.0;
+        // 参考Python实现:int(time.time() * 1000) 毫秒级整数时间戳
+        this.ts = System.currentTimeMillis();
     }
 }

+ 30 - 0
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/request/TaiShanExternalSendCodeRequest.java

@@ -0,0 +1,30 @@
+package com.jzg.quotation.taishan.crawler.entity.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 外部发送验证码请求
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+public class TaiShanExternalSendCodeRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @JsonProperty("check")
+    private String check;
+
+    @JsonProperty("username")
+    private String username;
+
+    @JsonProperty("pwd")
+    private String pwd;
+}

+ 2 - 0
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/response/TaiShanCrawlerSmsCodeResponse.java

@@ -14,6 +14,8 @@ public class TaiShanCrawlerSmsCodeResponse implements Serializable, TaiShanCrawl
     @Serial
     private static final long serialVersionUID = 0157577267035300221620L;
 
+    @JsonProperty("code")
+    private String code;
 
     @JsonProperty("repCode")
     private String repCode;

+ 43 - 0
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/entity/response/TaiShanExternalSendCodeResponse.java

@@ -0,0 +1,43 @@
+package com.jzg.quotation.taishan.crawler.entity.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 外部发送验证码响应
+ */
+@NoArgsConstructor
+@Data
+public class TaiShanExternalSendCodeResponse implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @JsonProperty("message")
+    private String message;
+
+    @JsonProperty("code")
+    private Integer code;
+
+    @JsonProperty("data")
+    private DataDTO data;
+
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @Data
+    public static class DataDTO {
+        @JsonProperty("token")
+        private String token;
+
+        @JsonProperty("secretKey")
+        private String secretKey;
+
+        @JsonProperty("pointJson")
+        private String pointJson;
+    }
+}

+ 20 - 0
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/properties/ExteriorCaptchaProperties.java

@@ -0,0 +1,20 @@
+package com.jzg.quotation.taishan.crawler.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 外部验证码接口配置属性
+ * 从 Nacos 配置中读取
+ */
+@Component
+@ConfigurationProperties(prefix = "exterior.api.sendcode")
+@Data
+public class ExteriorCaptchaProperties {
+
+    /**
+     * 验证码服务
+     */
+    private String url;
+}

+ 9 - 0
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/TaiShanCrawlerQuoteProcessService.java

@@ -2,6 +2,8 @@ package com.jzg.quotation.taishan.crawler.service;
 
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import org.springframework.http.HttpHeaders;
 
 /**
@@ -10,6 +12,13 @@ import org.springframework.http.HttpHeaders;
  * @date: 2025年9月17日16:28:40
  **/
 public interface TaiShanCrawlerQuoteProcessService {
+    /**
+     * 获取验证码
+     *
+     * @param sendCaptchaRequest 获取验证码请求
+     * @return 验证码响应
+     */
+    GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest);
 
     /**
      * 登录

+ 2 - 1
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/TaiShanCrawlerRequest.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.taishan.crawler.service;
 
+import com.jzg.quotation.commons.service.GetCaptchaBaseService;
 import com.jzg.quotation.commons.service.QuotationCrawlerBaseService;
 
 /**
@@ -7,6 +8,6 @@ import com.jzg.quotation.commons.service.QuotationCrawlerBaseService;
  * @author:
  * @date:
  **/
-public interface TaiShanCrawlerRequest extends QuotationCrawlerBaseService {
+public interface TaiShanCrawlerRequest extends QuotationCrawlerBaseService, GetCaptchaBaseService {
 
 }

+ 157 - 34
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerQuoteProcessServiceImpl.java

@@ -4,21 +4,30 @@ import com.alibaba.fastjson.JSON;
 import com.jzg.commons.constants.quote.enums.base.ExpenseRequestUrl;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.entity.quote.vo.identify.SliderCaptchaVo;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.service.ExteriorUtilsRequest;
 import com.jzg.quotation.taishan.crawler.component.TaiShanCrawlerCacheComponent;
 import com.jzg.quotation.taishan.crawler.component.TaiShanCrawlerRequestComponent;
+import com.jzg.quotation.commons.component.RequestComponent;
 import com.jzg.quotation.taishan.crawler.entity.request.TaiShanCrawlerLoginRequest;
 import com.jzg.quotation.taishan.crawler.entity.request.TaiShanCrawlerSmsCodeRequest;
 import com.jzg.quotation.taishan.crawler.entity.request.TaiShanCrawlerVerifyRequest;
+import com.jzg.quotation.taishan.crawler.entity.request.TaiShanExternalSendCodeRequest;
 import com.jzg.quotation.taishan.crawler.entity.response.TaiShanCrawlerLoginResponse;
 import com.jzg.quotation.taishan.crawler.entity.response.TaiShanCrawlerSmsCodeResponse;
 import com.jzg.quotation.taishan.crawler.entity.response.TaiShanCrawlerVerifyResponse;
+import com.jzg.quotation.taishan.crawler.entity.response.TaiShanExternalSendCodeResponse;
+import com.jzg.quotation.taishan.crawler.properties.ExteriorCaptchaProperties;
 import com.jzg.quotation.taishan.crawler.service.TaiShanCrawlerQuoteProcessService;
 import com.jzg.quotation.taishan.crawler.util.TaiShanCrawlerUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.util.TextUtils;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
 import java.nio.charset.StandardCharsets;
@@ -45,31 +54,117 @@ public class TaiShanCrawlerQuoteProcessServiceImpl implements TaiShanCrawlerQuot
 
     private final ExteriorUtilsRequest exteriorUtilsRequest;
 
+    private final RequestComponent requestComponent;
+
+    private final ExteriorCaptchaProperties exteriorCaptchaProperties;
+
     // 登陆次数
     public static final int LOGINS_NUMBER = 3;
 
+//    @Override
+//    public void sendCode(String username, String password) {
+//        HttpHeaders httpHeaders = new HttpHeaders();
+//        getVerifyHeader(httpHeaders);
+//        // 获取滑块验证码
+//        Map<String, String> map = uuid();
+//        TaiShanCrawlerVerifyRequest verifyRequest = new TaiShanCrawlerVerifyRequest(map.get("slider"));
+//        log.info("verifyRequest参数的值:{}", JSON.toJSONString(verifyRequest));
+//
+//        TaiShanCrawlerVerifyResponse verifyResponse = taiShanCrawlerRequestComponent.crawlerVerify(verifyRequest, httpHeaders);
+//        log.info("verifyResponse参数的值:{}", JSON.toJSONString(verifyResponse));
+//        // 滑块验证码识别
+//        TaiShanCrawlerVerifyResponse.RepDataDTO repData = verifyResponse.getRepData();
+//        List<Integer> integers = exteriorUtilsRequest.sliderCaptchaIdentify(ExpenseRequestUrl.SLIDER_IDENTIFY, new SliderCaptchaVo(repData.getOriginalImageBase64(), repData.getJigsawImageBase64()));
+//        // 获取图片的宽高
+//        List<Integer> sizeList = TaiShanCrawlerUtils.getImageSizeFromBase64(repData.getOriginalImageBase64());
+//        // 获取验证码
+//        TaiShanCrawlerSmsCodeRequest smsCodeRequest = new TaiShanCrawlerSmsCodeRequest(verifyResponse, integers, sizeList, password, username);
+//        log.info("smsCodeRequest参数的值:{}", JSON.toJSONString(smsCodeRequest));
+//        TaiShanCrawlerSmsCodeResponse smsCodeResponse = taiShanCrawlerRequestComponent.crawlerCheck(smsCodeRequest, httpHeaders);
+//        log.info("smsCodeResponse参数的值:{}", JSON.toJSONString(smsCodeResponse));
+//
+//        // 缓存登录信息
+//        Map<String, Object> tokenMap = new HashMap<>();
+//        tokenMap.put("token", smsCodeResponse.getRepData().getToken());
+//        tokenMap.put("secretKey", verifyResponse.getRepData().getSecretKey());
+//        tokenMap.put("pointJson", smsCodeResponse.getRepData().getPointJson());
+//        log.info("TaiShan-tokenMap参数的值:{}", JSON.toJSONString(tokenMap));
+//        taiShanCrawlerCacheComponent.cacheToken(username, tokenMap);
+//    }
+
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        log.info("开始获取泰山账号验证码");
+
+        GetCaptchaResponse getCaptchaResponse = new GetCaptchaResponse();
+        if(sendCaptchaRequest != null){
+            String username = sendCaptchaRequest.getUsername();
+            String password = sendCaptchaRequest.getPassword();
+
+            if(StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)){
+                // 调用外部发送验证码接口(URL从Nacos配置读取)
+                TaiShanExternalSendCodeRequest externalRequest = new TaiShanExternalSendCodeRequest("", username, password);
+                log.info("externalSendCodeRequest参数的值:{}", JSON.toJSONString(externalRequest));
+
+                String sendCodeUrl = exteriorCaptchaProperties.getUrl();
+                log.info("外部发送验证码接口URL:{}", sendCodeUrl);
+
+                // 使用代码中已有的 requestComponent.post 方法
+                HttpHeaders externalHeaders = new HttpHeaders();
+                ResponseEntity<String> externalResponseEntity = requestComponent.post(sendCodeUrl, JSON.toJSONString(externalRequest), String.class, externalHeaders);
+                String externalResponseBody = externalResponseEntity.getBody();
+                log.info("外部发送验证码接口响应内容:{}", externalResponseBody);
+                TaiShanExternalSendCodeResponse externalResponse = JSON.parseObject(externalResponseBody, TaiShanExternalSendCodeResponse.class);
+                log.info("externalSendCodeResponse参数的值:{}", JSON.toJSONString(externalResponse));
+
+                // 从外部响应中获取数据并缓存
+                TaiShanExternalSendCodeResponse.DataDTO externalData = externalResponse.getData();
+                Map<String, Object> tokenMap = new HashMap<>();
+                tokenMap.put("token", externalData.getToken());
+                tokenMap.put("secretKey", externalData.getSecretKey());
+                tokenMap.put("pointJson", externalData.getPointJson());
+                log.info("TaiShan-tokenMap参数的值(从外部接口获取):{}", JSON.toJSONString(tokenMap));
+                taiShanCrawlerCacheComponent.cacheToken(username, tokenMap);
+
+                getCaptchaResponse.setIdentifyId(externalData.getToken());
+            }
+        }
+
+        return getCaptchaResponse;
+    }
+
+
+
     @Override
     public void sendCode(String username, String password) {
-        HttpHeaders httpHeaders = new HttpHeaders();
-        getVerifyHeader(httpHeaders);
-        // 获取滑块验证码
-        Map<String, String> map = uuid();
-        TaiShanCrawlerVerifyRequest verifyRequest = new TaiShanCrawlerVerifyRequest(map.get("slider"));
-        TaiShanCrawlerVerifyResponse verifyResponse = taiShanCrawlerRequestComponent.crawlerVerify(verifyRequest, httpHeaders);
-        // 滑块验证码识别
-        TaiShanCrawlerVerifyResponse.RepDataDTO repData = verifyResponse.getRepData();
-        List<Integer> integers = exteriorUtilsRequest.sliderCaptchaIdentify(ExpenseRequestUrl.SLIDER_IDENTIFY, new SliderCaptchaVo(repData.getOriginalImageBase64(), repData.getJigsawImageBase64()));
-        // 获取图片的宽高
-        List<Integer> sizeList = TaiShanCrawlerUtils.getImageSizeFromBase64(repData.getOriginalImageBase64());
-        // 获取验证码
-        TaiShanCrawlerSmsCodeRequest smsCodeRequest = new TaiShanCrawlerSmsCodeRequest(verifyResponse, integers, sizeList, password, username);
-        TaiShanCrawlerSmsCodeResponse smsCodeResponse = taiShanCrawlerRequestComponent.crawlerCheck(smsCodeRequest, httpHeaders);
-
-        // 缓存登录信息
+        // 调用外部发送验证码接口(URL从Nacos配置读取)
+        TaiShanExternalSendCodeRequest externalRequest = new TaiShanExternalSendCodeRequest("", username, password);
+        log.info("externalSendCodeRequest参数的值:{}", JSON.toJSONString(externalRequest));
+
+        String sendCodeUrl = exteriorCaptchaProperties.getUrl();
+        log.info("外部发送验证码接口URL:{}", sendCodeUrl);
+        
+        // 使用代码中已有的 requestComponent.post 方法
+        HttpHeaders externalHeaders = new HttpHeaders();
+        ResponseEntity<String> externalResponseEntity = requestComponent.post(sendCodeUrl, JSON.toJSONString(externalRequest), String.class, externalHeaders);
+        String externalResponseBody = externalResponseEntity.getBody();
+        log.info("外部发送验证码接口响应内容:{}", externalResponseBody);
+        TaiShanExternalSendCodeResponse externalResponse = JSON.parseObject(externalResponseBody, TaiShanExternalSendCodeResponse.class);
+        log.info("externalSendCodeResponse参数的值:{}", JSON.toJSONString(externalResponse));
+
+//        if (externalResponse == null || externalResponse.getCode() != 200) {
+//            String message = externalResponse != null ? externalResponse.getMessage() : "未知错误";
+//            log.warn("外部发送验证码接口调用失败,错误信息:{}", message);
+//            throw new RuntimeException("外部发送验证码失败:" + message);
+//        }
+
+        // 从外部响应中获取数据并缓存
+        TaiShanExternalSendCodeResponse.DataDTO externalData = externalResponse.getData();
         Map<String, Object> tokenMap = new HashMap<>();
-        tokenMap.put("token", smsCodeResponse.getRepData().getToken());
-        tokenMap.put("secretKey", verifyResponse.getRepData().getSecretKey());
-        tokenMap.put("pointJson", smsCodeResponse.getRepData().getPointJson());
+        tokenMap.put("token", externalData.getToken());
+        tokenMap.put("secretKey", externalData.getSecretKey());
+        tokenMap.put("pointJson", externalData.getPointJson());
+        log.info("TaiShan-tokenMap参数的值(从外部接口获取):{}", JSON.toJSONString(tokenMap));
         taiShanCrawlerCacheComponent.cacheToken(username, tokenMap);
     }
 
@@ -79,40 +174,66 @@ public class TaiShanCrawlerQuoteProcessServiceImpl implements TaiShanCrawlerQuot
      */
     @Override
     public void login(LoginBase loginBase) {
+        log.info("泰山-login");
         HttpHeaders httpHeaders = new HttpHeaders();
         getVerifyHeader(httpHeaders);
 
         Map<String, Object> tokenMap = taiShanCrawlerCacheComponent.getToken(loginBase.getUsername());
+        log.info("泰山-tokenMap参数的值:{}", JSON.toJSONString(tokenMap));
+
         TaiShanCrawlerLoginRequest loginRequest = new TaiShanCrawlerLoginRequest(loginBase,tokenMap);
+        log.info("TaiShan-loginRequest参数的值:{}", JSON.toJSONString(loginRequest));
         TaiShanCrawlerLoginResponse loginResponse = taiShanCrawlerRequestComponent.login(loginRequest, httpHeaders);
         log.info("TaiShan-loginResponse参数的值:{}", JSON.toJSONString(loginResponse));
         if(loginResponse.getCode().equals("200")){
             String authorization = loginResponse.getResult().getIdToken();
+            log.info("TaiShan-Username参数的值:{}", JSON.toJSONString(loginBase.getUsername()));
+            log.info("TaiShan-authorization参数的值:{}", JSON.toJSONString(authorization));
             taiShanCrawlerCacheComponent.cacheAuthorization(loginBase.getUsername(), authorization);
         }
     }
 
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
+        log.info("泰山-detectLogin");
         String username = detectLoginRequest.getUsername();
-        String password = detectLoginRequest.getPassword();
-        LoginBase loginBase = new LoginBase();
-        loginBase.setUsername(username);
-        loginBase.setPassword(password);
-
-        HttpHeaders httpHeaders = new HttpHeaders();
-        getVerifyHeader(httpHeaders);
-
+        String token = null;
         Map<String, Object> tokenMap = taiShanCrawlerCacheComponent.getToken(username);
-        TaiShanCrawlerLoginRequest loginRequest = new TaiShanCrawlerLoginRequest(loginBase,tokenMap);
-        TaiShanCrawlerLoginResponse loginResponse = taiShanCrawlerRequestComponent.login(loginRequest, httpHeaders);
-        if(loginResponse.getCode().equals("200")){
-            String authorization = loginResponse.getResult().getIdToken();
-            taiShanCrawlerCacheComponent.cacheAuthorization(loginBase.getUsername(), authorization);
+        if(tokenMap !=null && !tokenMap.isEmpty()){
+            token = (String) tokenMap.get("token");
         }
-        return true;
+        return StringUtils.hasText(token);
+
+
+//        log.info("TaiShan-detectLoginRequest参数的值:{}", JSON.toJSONString(detectLoginRequest));
+//        String username = detectLoginRequest.getUsername();
+//        String password = detectLoginRequest.getPassword();
+//        LoginBase loginBase = new LoginBase();
+//        loginBase.setUsername(username);
+//        loginBase.setPassword(password);
+//        log.info("TaiShan-loginBase参数的值:{}", JSON.toJSONString(loginBase));
+//
+//        HttpHeaders httpHeaders = new HttpHeaders();
+//        getVerifyHeader(httpHeaders);
+//
+//        sendCode(username, password);
+//
+//        Map<String, Object> tokenMap = taiShanCrawlerCacheComponent.getToken(username);
+//        log.info("TaiShan-tokenMap参数的值:{}", JSON.toJSONString(tokenMap));
+
+
+//        TaiShanCrawlerLoginRequest loginRequest = new TaiShanCrawlerLoginRequest(loginBase,tokenMap);
+//        TaiShanCrawlerLoginResponse loginResponse = taiShanCrawlerRequestComponent.login(loginRequest, httpHeaders);
+//        log.info("TaiShan-loginResponse参数的值:{}", JSON.toJSONString(loginResponse));
+//        if(loginResponse.getCode().equals("200")){
+//            String authorization = loginResponse.getResult().getIdToken();
+//            //缓存登录的信息
+//            taiShanCrawlerCacheComponent.cacheAuthorization(loginBase.getUsername(), authorization);
+//        }
+//        return true;
     }
 
+
     private void getVerifyHeader(HttpHeaders httpHeaders) {
         httpHeaders.set(HttpHeaders.ACCEPT, "application/json, text/plain, */*");
         httpHeaders.set(HttpHeaders.ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9");
@@ -174,7 +295,9 @@ public class TaiShanCrawlerQuoteProcessServiceImpl implements TaiShanCrawlerQuot
      */
     @Override
     public HttpHeaders getHeaders(String username, String comCode) {
-        String authorization = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI1ODI0MjEiLCJhdXRoIjoiUk9MRV9CVVNJTkVTUyIsInBhc3N3b3JkX2V4cGlyZSI6MTUsImV4cCI6MTc4MTY4NzIzMn0.ldWz9TMY4AJ75VE0Bk1mkzAXPC9jJNMIWL82n0kGHrBwASgGvBxO3fe7orHbCIowt0athoRn1zA9m5ZNnO7olg";
+        //String authorization = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI1ODI0MjEiLCJhdXRoIjoiUk9MRV9CVVNJTkVTUyIsInBhc3N3b3JkX2V4cGlyZSI6MTUsImV4cCI6MTc4MTY4NzIzMn0.ldWz9TMY4AJ75VE0Bk1mkzAXPC9jJNMIWL82n0kGHrBwASgGvBxO3fe7orHbCIowt0athoRn1zA9m5ZNnO7olg";
+
+        String authorization = "Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiI1ODI0MjEiLCJhdXRoIjoiUk9MRV9CVVNJTkVTUyIsInBhc3N3b3JkX2V4cGlyZSI6MTIsImV4cCI6MTc4MTk0MDMyMX0.rsR8yMmSsB5iOstJSToswargqTCFB5He37UydrlK_lKFsHVqtBL-EOAgls4YL4nKWvRtbSxxY6HZRczHFG0iRw";
         HttpHeaders httpHeaders = new HttpHeaders();
         
         httpHeaders.set("Accept", "application/json, text/plain, */*");

+ 8 - 1
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerRequestImpl.java

@@ -12,6 +12,8 @@ import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.taishan.crawler.build.TaiShanCrawlerQuoteRequestVoBuild;
 import com.jzg.quotation.taishan.crawler.build.TaiShanCrawlerQuoteResultsVoBuild;
@@ -61,7 +63,10 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
 
     public static final int CIRCULATE_NUMBER = 3;
 
-
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return taiShanCrawlerQuoteProcessService.getCaptcha(sendCaptchaRequest);
+    }
     /**
      * 登录
      *
@@ -558,4 +563,6 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
         }
         return downloadPolicyResultVo;
     }
+
+
 }

+ 13 - 3
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/service/Impl/ZhongAnCrawlerRequestImpl.java

@@ -13,6 +13,7 @@ import com.jzg.commons.entity.quote.vo.CarInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.ObjectUtil;
 import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.client.PlatformClient;
@@ -21,6 +22,8 @@ import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.entity.quote.vo.base.OrderBase;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.zhongan.crawler.build.ZhongAnCrawlerQuoteResultsVoBuild;
@@ -36,6 +39,7 @@ import com.jzg.quotation.zhongan.crawler.service.ZhongAnCrawlerOrderService;
 import com.jzg.quotation.zhongan.crawler.service.ZhongAnCrawlerRequest;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -46,6 +50,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -202,20 +207,20 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
             return quoteResultsVo;
         }
         // 处理重复投保
-        if (quoteResponse.getAdditionalInfo() != null) {
+        if (ObjectUtils.isNotEmpty(quoteResponse.getAdditionalInfo())) {
             if (quoteResponse.getAdditionalInfo().getInsureMessageF() != null && quoteResponse.getAdditionalInfo().getInsureMessageF().contains("重复投保")) {
                 String jqExtractDate = jqExtractDate(quoteResponse);
                 if (jqExtractDate != null) {
                     quoteRequest.setCompelInsEffectiveDate(jqExtractDate);
                 }
                 quoteResponse = zhongAnCrawlerRequestComponent.quote(quoteRequest, headers);
-                if (quoteResponse.getAdditionalInfo() != null && quoteResponse.getAdditionalInfo().getInsureMessage().contains("重复投保")) {
+                if (ObjectUtils.isNotEmpty(quoteResponse.getAdditionalInfo()) && quoteResponse.getAdditionalInfo().getInsureMessage() != null && quoteResponse.getAdditionalInfo().getInsureMessage().contains("重复投保")) {
                     String syExtractDate = syExtractDate(quoteResponse);
                     if (syExtractDate != null) {
                         quoteRequest.setEffectiveDate(syExtractDate);
                     }
+                    quoteResponse = zhongAnCrawlerRequestComponent.quote(quoteRequest, headers);
                 }
-                quoteResponse = zhongAnCrawlerRequestComponent.quote(quoteRequest, headers);
             }
         }
 
@@ -642,4 +647,9 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
     public void login(LoginBase loginBase) {
 
     }
+
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
 }

+ 7 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/service/Impl/ZhongMeiCrawlerRequestImpl.java

@@ -13,6 +13,8 @@ import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.CacheConstant;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.zhongmei.api.constant.TransCode;
@@ -66,6 +68,11 @@ public class ZhongMeiCrawlerRequestImpl implements ZhongMeiCrawlerRequest {
         zmCrawlerRequestComponent.authenticate(loginBase.getUsername(), loginBase.getPassword(), ZmCrawlerRequestComponent.REQUEST_NUMBER);
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         String username = detectLoginRequest.getUsername();

+ 63 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteRequestBuild.java

@@ -0,0 +1,63 @@
+package com.jzg.quotation.zijin.crawler.build;
+
+import com.jzg.commons.util.StringUtils;
+import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerQuotationRequest;
+import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerRecognizeCodesRequest;
+import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
+import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerRecognizeCodesResponse;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @description: 紫金财险爬虫报价“转保标志”再次报价构建器
+ * @author: wangrq
+ * @date: 2026/6/6 16:05
+ **/
+@Slf4j
+public class ZiJinCrawlerQuoteRequestBuild {
+
+    /**
+     * 构建识别码请求
+     *
+     * @param ziJinCrawlerQuotationResponse
+     * @return
+     */
+    public static ArrayList<ZiJinCrawlerRecognizeCodesRequest> buildRecognizeCodesRequests(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+        ArrayList<ZiJinCrawlerRecognizeCodesRequest> ziJinCrawlerRecognizeCodesRequests = new ArrayList<>();
+        if (StringUtils.isNotEmpty(ziJinCrawlerQuotationResponse.getBasePart().getQuestion())) {
+            ZiJinCrawlerRecognizeCodesRequest ziJinCrawlerRecognizeCodesRequest = new ZiJinCrawlerRecognizeCodesRequest();
+            ziJinCrawlerRecognizeCodesRequest.setBase64(ziJinCrawlerQuotationResponse.getBasePart().getQuestion());
+            ziJinCrawlerRecognizeCodesRequest.setSerialNo("question");
+            ziJinCrawlerRecognizeCodesRequests.add(ziJinCrawlerRecognizeCodesRequest);
+        }
+        if (StringUtils.isNotEmpty(ziJinCrawlerQuotationResponse.getBasePart().getQuestionCI())) {
+            ZiJinCrawlerRecognizeCodesRequest ziJinCrawlerRecognizeCodesRequest = new ZiJinCrawlerRecognizeCodesRequest();
+            ziJinCrawlerRecognizeCodesRequest.setBase64(ziJinCrawlerQuotationResponse.getBasePart().getQuestionCI());
+            ziJinCrawlerRecognizeCodesRequest.setSerialNo("questionCI");
+            ziJinCrawlerRecognizeCodesRequests.add(ziJinCrawlerRecognizeCodesRequest);
+        }
+        return ziJinCrawlerRecognizeCodesRequests;
+    }
+
+    /**
+     * 重新报价
+     * @param ziJinCrawlerRecognizeCodesResponse
+     * @param ziJinCrawlerQuotationRequest
+     */
+    public static void buildReQuote(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse, ZiJinCrawlerRecognizeCodesResponse ziJinCrawlerRecognizeCodesResponse, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+        List<ZiJinCrawlerRecognizeCodesResponse.Results> results = ziJinCrawlerRecognizeCodesResponse.getResults();
+        for (ZiJinCrawlerRecognizeCodesResponse.Results result : results) {
+            if ("question".equals(result.getSerialNo())) {
+                ziJinCrawlerQuotationRequest.getBaseInfo().setAnswer(result.getResult());
+                ziJinCrawlerQuotationRequest.getBaseInfo().setDemandNo(ziJinCrawlerQuotationResponse.getBasePart().getDemandNo());
+            }
+            if ("questionCI".equals(result.getSerialNo())) {
+                ziJinCrawlerQuotationRequest.getBaseInfo().setAnswerCI(result.getResult());
+                ziJinCrawlerQuotationRequest.getBaseInfo().setDemandNoCI(ziJinCrawlerQuotationResponse.getBasePart().getDemandNoCI());
+            }
+        }
+    }
+
+}

+ 74 - 19
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteResultsVoBuild.java

@@ -259,20 +259,68 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
             return scoreVo;
         }
         ZiJinCrawlerQuotationResponse.PriceInfoList priceInfo = priceInfoList.get(0);
-        JSONArray scoreArray = new JSONArray();
+        ZiJinCrawlerQuotationResponse.CiProfitDetailData ciProfitDetailData = ziJinCrawlerQuotationResponse.getCiProfitDetailData();
 
         scoreVo.setJqLossRation(priceInfo.getLrRecomAdjust());
         scoreVo.setSyLossRation(priceInfo.getLrRecom());
 
+        JSONArray scoreArray = new JSONArray();
+        // 商业险定价信息
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "自主定价系数")
+                .fluentPut("scoreKey", "uwRel")
+                .fluentPut("score", priceInfo.getUwRel()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "交通违法系数")
+                .fluentPut("scoreKey", "chanRel")
+                .fluentPut("score", priceInfo.getChanRel()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "无赔款优惠系数")
+                .fluentPut("scoreKey", "nonclaimAdjuct")
+                .fluentPut("score", ciProfitDetailData != null ? ciProfitDetailData.getNonclaimAdjuct() : ""));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "无赔款优待等级")
+                .fluentPut("scoreKey", "claimAdjustLevel")
+                .fluentPut("score", ciProfitDetailData != null ? ciProfitDetailData.getClaimAdjustLevel() : ""));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "连续承保年数")
+                .fluentPut("scoreKey", "insureYears")
+                .fluentPut("score", ciProfitDetailData != null ? ciProfitDetailData.getInsureYears() : null));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "连续承保期间出险次数")
+                .fluentPut("scoreKey", "claimTimes")
+                .fluentPut("score", ciProfitDetailData  != null ? ciProfitDetailData.getClaimTimes() : null));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "总折扣")
+                .fluentPut("scoreKey", "initialELR")
+                .fluentPut("score", priceInfo.getInitialELR()));
+        scoreVo.setScoreJson(scoreArray);
+
         // 定价评分
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "标费含NCD预期赔付率")
+                .fluentPut("scoreKey", "ncdBpremELR")
+                .fluentPut("score", priceInfo.getNcdBpremELR()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "商业险赔付率")
+                .fluentPut("scoreKey", "lrRecom")
+                .fluentPut("score", priceInfo.getLrRecom()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "交强险赔付率")
+                .fluentPut("scoreKey", "lrRecomAdjust")
+                .fluentPut("score", priceInfo.getLrRecomAdjust()));
         scoreArray.add(new JSONObject()
                 .fluentPut("scoreName", "交强险预测评分")
                 .fluentPut("scoreKey", "revPredScoreAdjust")
                 .fluentPut("score", priceInfo.getRevPredScoreAdjust()));
         scoreArray.add(new JSONObject()
-                .fluentPut("scoreName", "商业险预测评分")
+                .fluentPut("scoreName", "交强险预测评分")
+                .fluentPut("scoreKey", "revPredScoreAdjust")
+                .fluentPut("score", priceInfo.getRevPredScoreAdjust()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "交强险不浮动原因")
                 .fluentPut("scoreKey", "revPredScore")
-                .fluentPut("score", priceInfo.getRevPredScore()));
+                .fluentPut("score", null));
         scoreArray.add(new JSONObject()
                 .fluentPut("scoreName", "车辆核保分")
                 .fluentPut("scoreKey", "underwrite01")
@@ -281,22 +329,6 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 .fluentPut("scoreName", "律商新能源评分")
                 .fluentPut("scoreKey", "evScore")
                 .fluentPut("score", priceInfo.getEvScore()));
-        scoreArray.add(new JSONObject()
-                .fluentPut("scoreName", "标费含NCD预期赔付率")
-                .fluentPut("scoreKey", "ncdBpremELR")
-                .fluentPut("score", priceInfo.getNcdBpremELR()));
-        scoreArray.add(new JSONObject()
-                .fluentPut("scoreName", "交强险赔付率")
-                .fluentPut("scoreKey", "lrRecomAdjust")
-                .fluentPut("score", priceInfo.getLrRecomAdjust()));
-        scoreArray.add(new JSONObject()
-                .fluentPut("scoreName", "商业险赔付率")
-                .fluentPut("scoreKey", "lrRecom")
-                .fluentPut("score", priceInfo.getLrRecom()));
-        scoreArray.add(new JSONObject()
-                .fluentPut("scoreName", "商业险手续费")
-                .fluentPut("scoreKey", "handFeeBi")
-                .fluentPut("score", priceInfo.getUwRel()));
         scoreVo.setScoreJson(scoreArray);
 
         // 车慧达定价信息
@@ -325,6 +357,29 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 .fluentPut("scoreKey", "carLoadTranche")
                 .fluentPut("score", priceInfo.getCarLoadTranche()));
         scoreVo.setScoreJson(scoreArray);
+
+        // 影响因子
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "NCD")// 升费因子名称
+                .fluentPut("scoreKey", "effectValueUPOne")
+                .fluentPut("score", priceInfo.getEffectValueUPOne()));// 因子比例
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "性别年龄")
+                .fluentPut("scoreKey", "effectValueUPTwo")
+                .fluentPut("score", priceInfo.getEffectValueUPTwo()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "车牌")
+                .fluentPut("scoreKey", "effectValueUPThree")
+                .fluentPut("score", priceInfo.getEffectValueUPThree()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "是否投保医保外用药")
+                .fluentPut("scoreKey", "effectValueDownFour")
+                .fluentPut("score", priceInfo.getEffectValueDownFour()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "平台分")
+                .fluentPut("scoreKey", "effectValueDownFive")
+                .fluentPut("score", priceInfo.getEffectValueDownFive()));
+        scoreVo.setScoreJson(scoreArray);
         return scoreVo;
     }
 }

+ 115 - 37
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerSaveQuoteInfoRequestBuild.java

@@ -2,15 +2,15 @@ package com.jzg.quotation.zijin.crawler.build;
 
 import com.jzg.commons.entity.quote.vo.CustomerInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
-import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.zijin.api.constant.enums.RiskCodeEnum;
+import com.jzg.quotation.zijin.crawler.component.ZiJinCrawlerCacheComponent;
 import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerQuotationRequest;
-import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerRecognizeCodesRequest;
 import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerSaveQuoteInfoRequest;
 import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
 import com.jzg.quotation.zijin.crawler.util.ConvertUtil;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.jetbrains.annotations.NotNull;
+import org.springframework.stereotype.Component;
 import org.springframework.util.ObjectUtils;
 
 import java.util.*;
@@ -20,9 +20,113 @@ import java.util.*;
  * @author:
  * @date:
  **/
+@Component
+@RequiredArgsConstructor
 @Slf4j
 public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
 
+    private final ZiJinCrawlerCacheComponent ziJinCrawlerCacheComponent;
+
+    /**
+     * 构建保存报价信息请求对象
+     *
+     * @return 构建完成的保存报价信息请求对象
+     */
+    public ZiJinCrawlerSaveQuoteInfoRequest buildSaveQuoteInfoRequest(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+        ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = new ZiJinCrawlerSaveQuoteInfoRequest();
+
+        // 设置代理人代码
+        ziJinCrawlerSaveQuoteInfoRequest.setAgentCode(ziJinCrawlerQuotationRequest.getBaseInfo().getAgentCode());
+
+        // 设置订单ID
+        ziJinCrawlerSaveQuoteInfoRequest.setOrderId(ziJinCrawlerQuotationResponse.getOrderId());
+
+        // 设置订单号
+        ziJinCrawlerSaveQuoteInfoRequest.setOrderNo(ziJinCrawlerQuotationResponse.getOrderNo());
+
+        // 设置基础信息
+        ziJinCrawlerSaveQuoteInfoRequest.setBaseInfo(buildSaveBaseInfo(quoteVo, ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
+
+        // 设置车主信息
+        ziJinCrawlerSaveQuoteInfoRequest.setCarOwnerInfo(buildSaveCarOwnerInfo(quoteVo, ziJinCrawlerQuotationRequest));
+
+        // 设置车险附加险信息列表
+        ziJinCrawlerSaveQuoteInfoRequest.setCarPolicySubInfoList(buildSaveCarPolicySubInfo(ziJinCrawlerQuotationRequest));
+
+        // 设置附加险列表
+        ziJinCrawlerSaveQuoteInfoRequest.setAttachRiskList(new ArrayList<>());
+
+        // 设置 投保人/被保人 列表
+        ziJinCrawlerSaveQuoteInfoRequest.setInsuredList(buildSaveInsuredList(quoteVo, ziJinCrawlerQuotationRequest));
+
+        // 设置险别明细列表
+        ziJinCrawlerSaveQuoteInfoRequest.setItemKindList(buildSaveItemKindList(ziJinCrawlerQuotationResponse));
+
+        // 设置收费信息列表
+        ziJinCrawlerSaveQuoteInfoRequest.setChargingInfoList(new ArrayList<>());
+
+        // 设置订单来源
+        ziJinCrawlerSaveQuoteInfoRequest.setOrderOrigin("KSCD_PROD");
+
+        // 设置产品代码
+        ziJinCrawlerSaveQuoteInfoRequest.setProductCode("CAR20190517");
+
+        // 设置产品名称
+        ziJinCrawlerSaveQuoteInfoRequest.setProductName("机动车保险");
+
+        // 设置提交信息
+        ziJinCrawlerSaveQuoteInfoRequest.setSubmitInfo(new HashMap<>());
+
+        // 设置车船税减免信息
+        ziJinCrawlerSaveQuoteInfoRequest.setTaxRelifInfo(buildSaveTaxRelifInfo(ziJinCrawlerQuotationResponse));
+
+        // 设置终端ID
+        ziJinCrawlerSaveQuoteInfoRequest.setTerminalId("KSCD");
+
+        // 设置终端类型
+        ziJinCrawlerSaveQuoteInfoRequest.setTerminalIdType("Vue-PC");
+
+        // 设置投保标识
+        ziJinCrawlerSaveQuoteInfoRequest.setInsuranceSign("0");
+
+        // 设置车辆信息
+        ziJinCrawlerSaveQuoteInfoRequest.setVehicleInfo(buildVehicleInfo(ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
+
+        // 设置车辆设备保费列表
+        ziJinCrawlerSaveQuoteInfoRequest.setCarDevicePremiumDtoList(new ArrayList<>());
+
+        // 设置约定列表
+        ziJinCrawlerSaveQuoteInfoRequest.setEngageList(new ArrayList<>());
+
+        // 设置附件文件列表
+        ziJinCrawlerSaveQuoteInfoRequest.setItemFileDataList(buildSaveFileDataList(ziJinCrawlerQuotationResponse));
+
+        // 设置订单附加信息
+        ziJinCrawlerSaveQuoteInfoRequest.setOrderAttachInfo(buildSaveOrderAttachInfo(quoteVo, ziJinCrawlerQuotationRequest));
+
+        // 设置是否包含子机构
+        ziJinCrawlerSaveQuoteInfoRequest.setIsIncludeSubCom(1);
+
+        return ziJinCrawlerSaveQuoteInfoRequest;
+    }
+
+    /**
+     * 构建保存报价信息请求的附件文件列表
+     *
+     * @param ziJinCrawlerQuotationResponse
+     * @return
+     */
+    private List<ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData> buildSaveFileDataList(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+        // 获取图片上传信息
+        List<ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.FileInfo> imagesInfoList = ziJinCrawlerCacheComponent.getImagesInfo(ziJinCrawlerQuotationResponse.getOrderNo());
+        return Optional.ofNullable(ziJinCrawlerQuotationResponse.getItemKindList()).orElseGet(Collections::emptyList).stream().map(itemKindListDTO ->
+                ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.builder()
+                        .riskCode(itemKindListDTO.getRiskCode())
+                        .fileList(imagesInfoList)
+                        .build()
+        ).toList();
+    }
+
     /**
      * 构建保存报价信息的订单附加信息
      *
@@ -30,7 +134,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationRequest
      * @return
      */
-    public static ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo buildSaveOrderAttachInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+    private ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo buildSaveOrderAttachInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
         return ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo.builder()
                 .carAppliRelation("1")
                 .carInsuredRelation("1")
@@ -53,7 +157,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationResponse 报价结果
      * @return 保存报价信息的车辆信息
      */
-    public static ZiJinCrawlerSaveQuoteInfoRequest.VehicleInfo buildVehicleInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+    private ZiJinCrawlerSaveQuoteInfoRequest.VehicleInfo buildVehicleInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
         ZiJinCrawlerQuotationRequest.VehicleInfo carInfo = ziJinCrawlerQuotationRequest.getVehicleInfo();
         // 计算使用年限
         int useYears = 0;
@@ -129,7 +233,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationResponse
      * @return
      */
-    public static ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo buildSaveTaxRelifInfo(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+    private ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo buildSaveTaxRelifInfo(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
         if (ziJinCrawlerQuotationResponse.getCarShipTax() == null) {
             return null;
         }
@@ -192,8 +296,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationResponse
      * @return
      */
-    @NotNull
-    public static List<ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo> buildSaveItemKindList(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+    private List<ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo> buildSaveItemKindList(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
         List<ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo> itemKindList = new ArrayList<>();
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(ziJinCrawlerQuotationResponse.getItemKindList())) {
             for (ZiJinCrawlerQuotationResponse.ItemKindList kind : ziJinCrawlerQuotationResponse.getItemKindList()) {
@@ -222,8 +325,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationRequest
      * @return
      */
-    @NotNull
-    public static List<ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo> buildSaveInsuredList(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+    private List<ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo> buildSaveInsuredList(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
         // 投保人
         CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
         String addr = policyHolderInfo.getAddr();
@@ -289,8 +391,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationRequest
      * @return
      */
-    @NotNull
-    public static List<ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo> buildSaveCarPolicySubInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+    private List<ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo> buildSaveCarPolicySubInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
         List<ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo> carPolicySubInfoList = new ArrayList<>();
         if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(ziJinCrawlerQuotationRequest.getCarPolicySubInfoList())) {
             for (ZiJinCrawlerQuotationRequest.CarPolicySubInfoList subInfo : ziJinCrawlerQuotationRequest.getCarPolicySubInfoList()) {
@@ -319,7 +420,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationRequest
      * @return
      */
-    public static ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo buildSaveCarOwnerInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+    private ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo buildSaveCarOwnerInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
         return ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo.builder()
                 .customerAmlPropReqDtoList(new ArrayList<>())
                 .carOwner(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getCarOwner())
@@ -337,7 +438,7 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
      * @param ziJinCrawlerQuotationRequest  报价参数
      * @param ziJinCrawlerQuotationResponse 报价返回对象
      */
-    public static ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo buildSaveBaseInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+    private ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo buildSaveBaseInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
         Double sumPremium = 0.0;
         Double sumPremiumCI = ziJinCrawlerQuotationResponse.getPlanList().stream().filter(plan -> RiskCodeEnum.TRAFFIC_CODE.equals(plan.getRiskCode())).mapToDouble(ZiJinCrawlerQuotationResponse.PlanList::getPlanFee).findFirst().orElse(0.0);
         return ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.builder()
@@ -410,27 +511,4 @@ public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
                 .build();
     }
 
-    /**
-     * 构建识别码请求
-     *
-     * @param ziJinCrawlerQuotationResponse
-     * @return
-     */
-    public static ArrayList<ZiJinCrawlerRecognizeCodesRequest> buildRecognizeCodesRequests(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        ArrayList<ZiJinCrawlerRecognizeCodesRequest> ziJinCrawlerRecognizeCodesRequests = new ArrayList<>();
-        if (StringUtils.isNotEmpty(ziJinCrawlerQuotationResponse.getBasePart().getQuestion())) {
-            ZiJinCrawlerRecognizeCodesRequest ziJinCrawlerRecognizeCodesRequest = new ZiJinCrawlerRecognizeCodesRequest();
-            ziJinCrawlerRecognizeCodesRequest.setBase64(ziJinCrawlerQuotationResponse.getBasePart().getQuestion());
-            ziJinCrawlerRecognizeCodesRequest.setSerialNo("question");
-            ziJinCrawlerRecognizeCodesRequests.add(ziJinCrawlerRecognizeCodesRequest);
-        }
-        if (StringUtils.isNotEmpty(ziJinCrawlerQuotationResponse.getBasePart().getQuestionCI())) {
-            ZiJinCrawlerRecognizeCodesRequest ziJinCrawlerRecognizeCodesRequest = new ZiJinCrawlerRecognizeCodesRequest();
-            ziJinCrawlerRecognizeCodesRequest.setBase64(ziJinCrawlerQuotationResponse.getBasePart().getQuestionCI());
-            ziJinCrawlerRecognizeCodesRequest.setSerialNo("questionCI");
-            ziJinCrawlerRecognizeCodesRequests.add(ziJinCrawlerRecognizeCodesRequest);
-        }
-        return ziJinCrawlerRecognizeCodesRequests;
-    }
-
 }

+ 2 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerCacheComponent.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerSaveQuoteInfoRequest;
+import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerUploadImageInfoListRequest;
 import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerSaveResponse;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -116,7 +117,7 @@ public class ZiJinCrawlerCacheComponent {
      * @param orderNo 订单号
      * @param dataDTOS 图片信息
      */
-    public void cacheImagesInfo(String orderNo, List<ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.FileInfo> dataDTOS) {
+    public void cacheImagesInfo(String orderNo, List<ZiJinCrawlerUploadImageInfoListRequest.ItemFileDataListDTO> dataDTOS) {
         String responseStr = JSONObject.toJSONString(dataDTOS);
         redissonClient.getBucket(IMAGES_INFO + orderNo).set(responseStr, Duration.ofDays(IMAGES_INFO_TIME));
     }

+ 19 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerRequestComponent.java

@@ -341,6 +341,23 @@ public class ZiJinCrawlerRequestComponent {
         return responseEntity.getBody();
     }
 
+    /**
+     * 上传影像件列表
+     *
+     * @param headers
+     * @return ZiJinCrawlerImageUploadResponse
+     */
+    public ZiJinCrawlerImageUploadInfoListResponse uploadImageInfoList(ZiJinCrawlerUploadImageInfoListRequest ziJinCrawlerUploadImageInfoListRequest, HttpHeaders headers) throws Exception {
+        //设置headers
+        HttpHeaders httpHeaders = setHttpHeaders();
+
+        String jsonString = JSON.toJSONString(ziJinCrawlerUploadImageInfoListRequest);
+        log.info("ziJinCrawlerUploadImageInfoListRequest请求参数的值:{}", jsonString);
+        ResponseEntity<ZiJinCrawlerImageUploadInfoListResponse> responseEntity = requestComponent.post(RequestUrl.UPLOAD_IMAGE_INFO_LIST.getRequestUrl(ziJinCrawlerProperties.getBaseUrl()), jsonString, ZiJinCrawlerImageUploadInfoListResponse.class, httpHeaders);
+        return responseEntity.getBody();
+    }
+
+
 
     /**
      * 获取支付链接
@@ -368,7 +385,7 @@ public class ZiJinCrawlerRequestComponent {
      */
     public ZiJinCrawlerQueryOrderStatusResponse queryOrderStatus(ZiJinCrawlerQueryOrderStatusRequest ziJinCrawlerQueryOrderStatusRequest, HttpHeaders headers) throws IOException {
         //设置headers
-        HttpHeaders httpHeaders = setHttpHeaders1();
+        HttpHeaders httpHeaders = setHttpHeaders();
 
         String jsonString = JSON.toJSONString(ziJinCrawlerQueryOrderStatusRequest);
         log.info("ziJinCrawlerQueryOrderStatusRequest请求参数的值:{}", jsonString);
@@ -512,6 +529,7 @@ public class ZiJinCrawlerRequestComponent {
         headers.set("sec-ch-ua-mobile", "?0");
         headers.set("sec-ch-ua-platform", "\"Windows\"");
         headers.set("x-csrf-token", "CrwLEmSfUevAb8PcN7kXff-I");
+        headers.set("content-type", "application/json");
         return headers;
     }
 

+ 7 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQueryOrderStatusRequest.java

@@ -77,4 +77,11 @@ public class ZiJinCrawlerQueryOrderStatusRequest implements Serializable {
     @JsonProperty("orderOrigin")
     @JSONField(ordinal = 8)
     private String orderOrigin;
+
+    /**
+     * 许可证号:传车牌号
+     */
+    @JsonProperty("licenseNo")
+    @JSONField(ordinal = 9)
+    private String licenseNo;
 }

+ 1 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQuotationRequest.java

@@ -353,7 +353,7 @@ public class ZiJinCrawlerQuotationRequest implements Serializable {
         private String renewalFlag;
 
         /**
-         *
+         * 续保标志
          */
         @JsonProperty("renewalFlagCI")
         private String renewalFlagCI;

+ 54 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerUploadImageInfoListRequest.java

@@ -0,0 +1,54 @@
+package com.jzg.quotation.zijin.crawler.entity.request;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.jzg.quotation.zijin.api.entity.request.UploadFileRequest;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @description:
+ * @author:
+ * @date:
+ **/
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class ZiJinCrawlerUploadImageInfoListRequest implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 5189448987075578164L;
+
+    @JsonProperty("itemFileDataList")
+    private List<ItemFileDataListDTO> itemFileDataList;
+
+    @JsonProperty("orderId")
+    private String orderId;
+
+
+    @NoArgsConstructor
+    @Data
+    @Builder
+    public static class ItemFileDataListDTO implements Serializable {
+
+        @Serial
+        private static final long serialVersionUID = -8088228995799949015L;
+
+        @JsonProperty("fileId")
+        private String fileId;
+
+        @JsonProperty("fileType")
+        private String fileType;
+
+        public ItemFileDataListDTO(String fileId, String fileType) {
+            this.fileId = fileId;
+            this.fileType = fileType;
+        }
+    }
+}

+ 37 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/response/ZiJinCrawlerImageUploadInfoListResponse.java

@@ -0,0 +1,37 @@
+package com.jzg.quotation.zijin.crawler.entity.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @description: 紫金财险爬虫影像上传列表响应实体类
+ * @author:
+ * @date:
+ **/
+@Data
+public class ZiJinCrawlerImageUploadInfoListResponse implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -7410523311993599009L;
+
+    /**
+     * 响应状态码
+     */
+    @JsonProperty("rtnCode")
+    private String rtnCode;
+
+    /**
+     * 响应状态描述
+     */
+    @JsonProperty("rtnMsg")
+    private String rtnMsg;
+
+    /**
+     * 影像ID
+     */
+    @JsonProperty("recoFailedImageIdList")
+    private String recoFailedImageIdList;
+}

+ 3 - 2
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/enums/RequestUrl.java

@@ -23,8 +23,8 @@ public enum RequestUrl implements CrawlerRequestUrlStandard {
     GET_ACTUAL_VALUE("/api/v1/insurance/public/vehicle-proposal/vehicleModel/getActualValue", "获取车辆实际价值"),
     PRICE("/api/v1/vehicle/proposal-process/premium-calculation", "计算保费"),
     SAVE_QUOTE_INFORMATION("/dpgateway/insurance-order/order/save", "保存报价信息"),
-    // 报价提示转保标志,紫金系统调用该接口自动输入验证码跳过转保标志继续报价(二维码是报价接口失败返回:basePart.question)
-    SKIP_SING("/egg/controller/common/recognizeCodes", "跳过转保标志"),
+    // 报价提示转保标志,紫金系统调用该接口自动输入验证码跳过转保标志继续报价
+    SKIP_SING("/egg/controller/common/recognizeCodes", "转保标志"),
     SAVE_PROPOSAL_ORDER("/kscd-frontend/order/saveProposal", "保存投保单"),
     // 税务登记证号
     GET_TAX_REGISTRY_NUMBER("/temp/api/v1/insurance/public/taxInfo/getTaxRegistryNumber", "获取税务登记证号"),
@@ -32,6 +32,7 @@ public enum RequestUrl implements CrawlerRequestUrlStandard {
     UNDERWRITING("/kscd-frontend/carAutoUnderwriting", "核保"),
     //上传影像
     UPLOAD_IMAGE("/dpgateway/insurance-order/carInsurance/uploadFile", "上传影像"),
+    UPLOAD_IMAGE_INFO_LIST("/dpgateway/insurance-order/carInsurance/uploadImageInfoList", "上传影像列表"),
     // 支付链接
     QRCODE("/api/v1/insurance/public/paymentApplication/pushMessage", "支付二维码"),
     // 查询订单状态

+ 2 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/ZiJinCrawlerOrderService.java

@@ -3,6 +3,7 @@ package com.jzg.quotation.zijin.crawler.service;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.quotation.zijin.crawler.entity.po.ZiJinCrawlerOrder;
 import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
+import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerSaveProposalResponse;
 
 /**
  * @description: 紫金财险爬虫订单服务
@@ -17,7 +18,7 @@ public interface ZiJinCrawlerOrderService {
      * @param ziJinCrawlerQuotationResponse
      * @param success
      */
-    void save(QuoteVo quoteVo, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse, boolean success);
+    void save(QuoteVo quoteVo, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse, ZiJinCrawlerSaveProposalResponse ziJinCrawlerSaveProposalResponse, String orderId, boolean success);
 
     /**
      * 根据系统内部订单号查询紫金财险爬虫订单

+ 11 - 12
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerOrderServiceImpl.java

@@ -3,6 +3,7 @@ package com.jzg.quotation.zijin.crawler.service.impl;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.quotation.zijin.crawler.entity.po.ZiJinCrawlerOrder;
 import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
+import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerSaveProposalResponse;
 import com.jzg.quotation.zijin.crawler.repository.ZiJinCrawlerOrderRepository;
 import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerOrderService;
 import lombok.RequiredArgsConstructor;
@@ -23,29 +24,27 @@ public class ZiJinCrawlerOrderServiceImpl implements ZiJinCrawlerOrderService {
 
     /**
      * 保存紫金财险爬虫订单
+     *
      * @param quoteVo
      * @param ziJinCrawlerQuotationResponse
      * @param success
      */
     @Override
-    public void save(QuoteVo quoteVo, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse, boolean success) {
+    public void save(QuoteVo quoteVo, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse, ZiJinCrawlerSaveProposalResponse ziJinCrawlerSaveProposalResponse, String orderId, boolean success) {
         ZiJinCrawlerOrder order = new ZiJinCrawlerOrder();
         order.setOrdersNo(quoteVo.getOrder().getOrdersNo());
         order.setOrderNo(ziJinCrawlerQuotationResponse.getOrderNo());
-        /*order.setOrderNo(ziJinCrawlerQuotationResponse.getData().getBusUniqueId());
-        order.setBusUniqueId(ziJinCrawlerQuotationResponse.getData().getBusUniqueId());
+        order.setBusUniqueId(orderId);
         order.setQuoteSuccess(success);
-
-        if (ziJinCrawlerQuotationResponse.getData().getTrafficPolicy() != null) {
-            order.setCiApplyNo(ziJinCrawlerQuotationResponse.getData().getTrafficPolicy().getApplicationNo());
-            order.setCiPremium(ziJinCrawlerQuotationResponse.getData().getTrafficPolicy().getPremium());
+        if (success && ziJinCrawlerSaveProposalResponse != null) {
+            order.setCiApplyNo(ziJinCrawlerSaveProposalResponse.getData().getProposalNoCI());
+            order.setCiPolicyNo(ziJinCrawlerSaveProposalResponse.getData().getPolicyNoCI());
+            // order.setCiPremium(ziJinCrawlerQuotationResponse.getData().getTrafficPolicy().getPremium());
+            order.setSyApplyNo(ziJinCrawlerSaveProposalResponse.getData().getProposalNo());
+            order.setBiPolicyNo(ziJinCrawlerSaveProposalResponse.getData().getPolicyNo());
+            // order.setBiPremium(ziJinCrawlerQuotationResponse.getData().getBusinessPolicy().getPremium());
         }
 
-        if (ziJinCrawlerQuotationResponse.getData().getBusinessPolicy() != null) {
-            order.setSyApplyNo(ziJinCrawlerQuotationResponse.getData().getBusinessPolicy().getApplicationNo());
-            order.setBiPremium(ziJinCrawlerQuotationResponse.getData().getBusinessPolicy().getPremium());
-        }*/
-
         order.setCreateTime(LocalDateTime.now());
         order.setUpdateTime(LocalDateTime.now());
         if (!success) {

+ 43 - 126
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerRequestImpl.java

@@ -13,12 +13,16 @@ import com.jzg.commons.entity.quote.vo.base.OrderBase;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
 import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
-import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaRequest;
+import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
+import com.jzg.quotation.commons.utils.DateTimeUtil;
 import com.jzg.quotation.zijin.api.constant.enums.MotorVehicleInsuranceEnum;
 import com.jzg.quotation.zijin.api.constant.enums.RiskCodeEnum;
+import com.jzg.quotation.zijin.api.entity.request.UploadImageInfoListRequest;
+import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerQuoteRequestBuild;
 import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerQuoteResultsVoBuild;
 import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerSaveQuoteInfoRequestBuild;
 import com.jzg.quotation.zijin.crawler.component.ZiJinBuildingAttributionInformation;
@@ -33,7 +37,6 @@ import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerOrderService;
 import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerQuoteProcessService;
 import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerRequest;
 import com.jzg.quotation.zijin.crawler.util.Base64ImageExtractor;
-import com.jzg.quotation.zijin.crawler.util.RS6Item;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
@@ -72,7 +75,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
 
     private final ZiJinCrawlerQuoteProcessService ziJinCrawlerQuoteProcessService;
 
-    private final PlatformClient platformClient;
+    private final ZiJinCrawlerSaveQuoteInfoRequestBuild ziJinCrawlerSaveQuoteInfoRequestBuild;
 
 
     /**
@@ -85,6 +88,11 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         ziJinCrawlerQuoteProcessService.login(loginBase.getUsername(), loginBase.getPassword());
     }
 
+    @Override
+    public GetCaptchaResponse getCaptcha(GetCaptchaRequest sendCaptchaRequest) {
+        return null;
+    }
+
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         return ziJinCrawlerQuoteProcessService.detectLogin(detectLoginRequest);
@@ -206,32 +214,23 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             // 转保标志
             if (ResponseCode.R_0001.getCode().equals(ziJinCrawlerQuotationResponse.getRtnCode())) {
                 if (ziJinCrawlerQuotationResponse.getBasePart() != null) {
-                    ZiJinCrawlerRecognizeCodesResponse ziJinCrawlerRecognizeCodesResponse = ziJinCrawlerRequestComponent.recognizeCodes(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildRecognizeCodesRequests(ziJinCrawlerQuotationResponse), headers);
+                    ZiJinCrawlerRecognizeCodesResponse ziJinCrawlerRecognizeCodesResponse = ziJinCrawlerRequestComponent.recognizeCodes(ZiJinCrawlerQuoteRequestBuild.buildRecognizeCodesRequests(ziJinCrawlerQuotationResponse), headers);
                     log.info("ziJinCrawlerRecognizeCodesResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerRecognizeCodesResponse));
-                    // 再次调用报价接口
+                    // 验证码通过后再次调用报价接口
                     if (ResponseCode.R_0000.getCode().equals(ziJinCrawlerRecognizeCodesResponse.getRtnCode())) {
-                        List<ZiJinCrawlerRecognizeCodesResponse.Results> results = ziJinCrawlerRecognizeCodesResponse.getResults();
-                        for (ZiJinCrawlerRecognizeCodesResponse.Results result : results) {
-                            if ("question".equals(result.getSerialNo())) {
-                                ziJinCrawlerQuotationRequest.getBaseInfo().setAnswer(result.getResult());
-                            }
-                            if ("questionCI".equals(result.getSerialNo())) {
-                                ziJinCrawlerQuotationRequest.getBaseInfo().setAnswerCI(result.getResult());
-                            }
-                            ziJinCrawlerQuotationRequest.getBaseInfo().setRenewalFlagCI("1");
-                        }
+                        ZiJinCrawlerQuoteRequestBuild.buildReQuote(ziJinCrawlerQuotationResponse, ziJinCrawlerRecognizeCodesResponse, ziJinCrawlerQuotationRequest);
                         ziJinCrawlerQuotationResponse = ziJinCrawlerRequestComponent.quotation(ziJinCrawlerQuotationRequest, headers);
                     }
                 }
             }
             // 4.0 处理报价失败
             if (!ResponseCode.R_0000.getCode().equals(ziJinCrawlerQuotationResponse.getRtnCode())) {
-                ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, false);
+                ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, null, ziJinCrawlerQuotationRequest.getOrderId(), false);
                 return ZiJinCrawlerQuoteResultsVoBuild.buildQuoteFailResultsVo(ziJinCrawlerQuotationResponse);
             } else {
                 // 报价成功
                 // 保存报价信息
-                ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = buildSaveQuoteInfoRequest(quoteVo, ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse);
+                ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = ziJinCrawlerSaveQuoteInfoRequestBuild.buildSaveQuoteInfoRequest(quoteVo, ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse);
                 log.info("ziJinCrawlerSaveQuoteInfoRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveQuoteInfoRequest));
                 ZiJinCrawlerSaveQuoteInfoResponse ziJinCrawlerSaveQuoteInfoResponse = ziJinCrawlerRequestComponent.saveQuoteInformation(ziJinCrawlerSaveQuoteInfoRequest, headers);
                 log.info("ziJinCrawlerSaveQuoteInfoResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveQuoteInfoResponse));
@@ -244,7 +243,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 ZiJinCrawlerSaveProposalResponse ziJinCrawlerSaveProposalResponse = ziJinCrawlerRequestComponent.saveProposal(ziJinCrawlerSaveProposalRequest, headers);
                 log.info("ziJinCrawlerSaveProposalResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveProposalResponse));
 
-                ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, true);
+                ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, ziJinCrawlerSaveProposalResponse, ziJinCrawlerQuotationRequest.getOrderId(), true);
                 return ZiJinCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo.getOrder().getOrdersNo(), quoteVo, ziJinCrawlerQuotationResponse);
             }
         } catch (Exception e) {
@@ -269,7 +268,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
 
         ZiJinCrawlerUnderwritingResponse ziJinCrawlerUnderwritingResponse = null;
         try {
-            ZiJinCrawlerUnderwritingRequest ziJinCrawlerUnderwritingRequest = new ZiJinCrawlerUnderwritingRequest("KSCD_PROD", ziJinCrawlerOrder.getOrdersNo());
+            ZiJinCrawlerUnderwritingRequest ziJinCrawlerUnderwritingRequest = new ZiJinCrawlerUnderwritingRequest("KSCD_PROD", ziJinCrawlerOrder.getOrderNo());
             // 核保
             ziJinCrawlerUnderwritingResponse = ziJinCrawlerRequestComponent.underwriting(ziJinCrawlerUnderwritingRequest, headers);
             log.info("ziJinCrawlerUnderwritingResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerUnderwritingResponse));
@@ -381,7 +380,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             }
 
             // 单个上传影像
-            List<ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.FileInfo> dataDTOS = new ArrayList<>();
+            List<ZiJinCrawlerUploadImageInfoListRequest.ItemFileDataListDTO> dataDTOS = new ArrayList<>();
 
             for (InsuranceImageVo insuranceImageVo : insuranceUploadImageVo.getImageVoList()) {
                 if (insuranceImageVo == null) {
@@ -403,24 +402,21 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
 
                 // 构建上传影像文件请求参数
                 ZiJinCrawlerImageUploadRequest ziJinCrawlerImageUploadRequest = new ZiJinCrawlerImageUploadRequest();
-
                 // 根据图片格式动态设置MIME类型
                 String imageName = imageDTO.getImageName();
                 String mimeType = Base64ImageExtractor.getImageMimeType(imageName);
                 ziJinCrawlerImageUploadRequest.setFileBase64(mimeType + imageDTO.getImageBase64Str());
                 ziJinCrawlerImageUploadRequest.setFileName(imageName);
-
                 // 设置文件类型,转换为紫金对应的文件类型
                 String fileType = getFileTypeByImageCode(insuranceImageVo.getImageCode());
                 ziJinCrawlerImageUploadRequest.setFileType(fileType);
                 ziJinCrawlerImageUploadRequest.setOrderNo(ziJinCrawlerOrder.getOrderNo());
-
                 ZiJinCrawlerImageUploadResponse ziJinCrawlerImageUploadResponse = ziJinCrawlerRequestComponent.uploadImage(ziJinCrawlerImageUploadRequest, headers);
                 log.info("影像上传响应,订单号:{},响应:{}", ziJinCrawlerOrder.getOrderNo(), JSON.toJSONString(ziJinCrawlerImageUploadResponse));
 
                 if ("0000".equals(ziJinCrawlerImageUploadResponse.getRtnCode())) {
 
-                    ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.FileInfo fileInfo = ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.FileInfo.builder()
+                    ZiJinCrawlerUploadImageInfoListRequest.ItemFileDataListDTO fileInfo = ZiJinCrawlerUploadImageInfoListRequest.ItemFileDataListDTO.builder()
                             .fileId(ziJinCrawlerImageUploadResponse.getFileId())
                             .fileType(fileType)
                             .build();
@@ -429,7 +425,6 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
 
                     log.info("影像上传成功,订单号:{},影像编码:{},影像ID:{}", ziJinCrawlerOrder.getOrderNo(), insuranceImageVo.getImageCode(), ziJinCrawlerImageUploadResponse.getFileId());
                 } else {
-
                     String errorMsg = String.format("影像上传失败,订单号:%s,影像编码:%s,错误码:%s,错误信息:%s", ziJinCrawlerOrder.getOrderNo(), insuranceImageVo.getImageCode(), ziJinCrawlerImageUploadResponse.getRtnCode(), ziJinCrawlerImageUploadResponse.getRtnMsg());
                     log.error(errorMsg);
                     throw new RuntimeException(errorMsg);
@@ -440,6 +435,10 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 return;
             }
 
+            ZiJinCrawlerUploadImageInfoListRequest ziJinCrawlerUploadImageInfoListRequest = new ZiJinCrawlerUploadImageInfoListRequest(dataDTOS, ziJinCrawlerOrder.getBusUniqueId());
+            // 保存影像信息
+            ziJinCrawlerRequestComponent.uploadImageInfoList(ziJinCrawlerUploadImageInfoListRequest, headers);
+
             // 缓存影像信息
             ziJinCrawlerCacheComponent.cacheImagesInfo(ziJinCrawlerOrder.getOrderNo(), dataDTOS);
 
@@ -456,19 +455,19 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
      * @return 文件类型
      */
     private String getFileTypeByImageCode(String imageCode) {
-        if (!StringUtils.hasLength(imageCode)) {
-            return "9";
-        }
         switch (imageCode) {
             case "C01":
-                return "9";
             case "D01":
                 return "56";
             case "C02":
             case "D02":
+            case "C03":
+            case "D03":
+            case "C04":
+            case "D04":
                 return "53";
             default:
-                return "9";
+                return "";
         }
     }
 
@@ -495,12 +494,13 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             // 设置请求参数
             ziJinCrawlerQueryOrderStatusRequest.setOrderStatus(new String[]{});
             ziJinCrawlerQueryOrderStatusRequest.setOrderNo(ziJinCrawlerOrder.getOrderNo());
-            ziJinCrawlerQueryOrderStatusRequest.setUpdateTimeBegin("");
-            ziJinCrawlerQueryOrderStatusRequest.setUpdateTimeEnd("");
+            ziJinCrawlerQueryOrderStatusRequest.setLicenseNo(orderStatusVo.getCarInfo().getLicenseNo());
+            ziJinCrawlerQueryOrderStatusRequest.setUpdateTimeBegin(DateTimeUtil.getLocalDateStr());
+            ziJinCrawlerQueryOrderStatusRequest.setUpdateTimeEnd(DateTimeUtil.getLocalDateStr());
             ziJinCrawlerQueryOrderStatusRequest.setPageNum(1);
             ziJinCrawlerQueryOrderStatusRequest.setPageSize(10);
             ziJinCrawlerQueryOrderStatusRequest.setProductCodeList(new String[]{});
-            ziJinCrawlerQueryOrderStatusRequest.setOrderOrigin("KSCD_PROD,FH_PROD,DP_WXMP,DP_ZYB,RENEWAL_PROD,DP_ZNCD,SHHTB_B");
+            ziJinCrawlerQueryOrderStatusRequest.setOrderOrigin("KSCD_PROD,FH_PROD,DP_WXMP,DP_ZYB,RENEWAL_PROD,DP_ZNCD,SHHTB_B,QYYGTB");
 
             ZiJinCrawlerQueryOrderStatusResponse ziJinCrawlerQueryOrderStatusResponse = ziJinCrawlerRequestComponent.queryOrderStatus(ziJinCrawlerQueryOrderStatusRequest, headers);
             log.info("ziJinCrawlerQueryOrderStatusResponse对象的值:{}", JSON.toJSONString(ziJinCrawlerQueryOrderStatusResponse));
@@ -513,6 +513,10 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 orderStatusEnum = InsOrderStatusEnum.valueOf("ORDER_CLOSE");
                 orderStatus = orderStatusEnum.getCode();
             }
+            if ("9".equals(orderStatus)) {
+                orderStatusEnum = InsOrderStatusEnum.valueOf("AUDIT_FAIL");
+                orderStatus = orderStatusEnum.getCode();
+            }
             OrderStatusResultVo orderStatusResultVo = new OrderStatusResultVo();
             // 将订单状态转换为枚举类型
             orderStatusResultVo.setOrderStatus(orderStatusEnum);
@@ -802,11 +806,15 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         baseInfo.setHanderCode("214003263");
         baseInfo.setHanderName("程涛");
         baseInfo.setDemandNo("01ZKIC140026051910017933666448");
-        baseInfo.setDemandNoCI("01ZKIC140026051910017933666448");// 这个先放开看行不
+        if (quoteVo.getBiRiskInfoVo() != null) {
+            baseInfo.setDemandNoCI("01ZKIC140026051910017933666448");// 这个先放开看行不
+        }
         // 经测试:燃油: 单交设为2,交三设为0
         baseInfo.setCalculateFlag(quoteVo.getBiRiskInfoVo() == null ? "2" : "0");
-        // 经测试:燃油:单交设为"",交三设为1
+        // 经测试:燃油:单交设为"",交三设为1?。 这个是续保标志,延顺日期的时候设置为1(完了测试一下)
         baseInfo.setRenewalFlag(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
+        // 经测试:燃油:单交设为"",交三设为1?。 这个是续保标志,延顺日期的时候设置为1(完了测试一下)
+        baseInfo.setRenewalFlagCI(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
         return baseInfo;
     }
 
@@ -1122,7 +1130,6 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 item.setUnitAmount(kindItem.getUnitAmount());
                 item.setServiceTimes(kindItem.getServiceTimes());
                 item.setQuantity(ObjectUtils.isEmpty(kindItem.getQuantity()) ? null : Integer.parseInt(kindItem.getQuantity()));
-                item.setDeductibleRate(ObjectUtils.isEmpty(kindItem.getDeductibleRate()) ? null : Integer.parseInt(kindItem.getDeductibleRate()));
                 itemKindList.add(item);
             }
         }
@@ -1731,97 +1738,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         return profitDataList;
     }
 
-    /**
-     * 构建保存报价信息请求对象
-     *
-     * @return 构建完成的保存报价信息请求对象
-     */
-    private ZiJinCrawlerSaveQuoteInfoRequest buildSaveQuoteInfoRequest(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = new ZiJinCrawlerSaveQuoteInfoRequest();
-
-        // 设置代理人代码
-        ziJinCrawlerSaveQuoteInfoRequest.setAgentCode(ziJinCrawlerQuotationRequest.getBaseInfo().getAgentCode());
-
-        // 设置订单ID
-        ziJinCrawlerSaveQuoteInfoRequest.setOrderId(ziJinCrawlerQuotationResponse.getOrderId());
-
-        // 设置订单号
-        ziJinCrawlerSaveQuoteInfoRequest.setOrderNo(ziJinCrawlerQuotationResponse.getOrderNo());
-
-        // 设置基础信息
-        ziJinCrawlerSaveQuoteInfoRequest.setBaseInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveBaseInfo(quoteVo, ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
-
-        // 设置车主信息
-        ziJinCrawlerSaveQuoteInfoRequest.setCarOwnerInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveCarOwnerInfo(quoteVo, ziJinCrawlerQuotationRequest));
 
-        // 设置车险附加险信息列表
-        ziJinCrawlerSaveQuoteInfoRequest.setCarPolicySubInfoList(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveCarPolicySubInfo(ziJinCrawlerQuotationRequest));
 
-        // 设置附加险列表
-        ziJinCrawlerSaveQuoteInfoRequest.setAttachRiskList(new ArrayList<>());
 
-        // 设置 投保人/被保人 列表
-        ziJinCrawlerSaveQuoteInfoRequest.setInsuredList(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveInsuredList(quoteVo, ziJinCrawlerQuotationRequest));
-
-        // 设置险别明细列表
-        ziJinCrawlerSaveQuoteInfoRequest.setItemKindList(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveItemKindList(ziJinCrawlerQuotationResponse));
-
-        // 设置收费信息列表
-        ziJinCrawlerSaveQuoteInfoRequest.setChargingInfoList(new ArrayList<>());
-
-        // 设置订单来源
-        ziJinCrawlerSaveQuoteInfoRequest.setOrderOrigin("KSCD_PROD");
-
-        // 设置产品代码
-        ziJinCrawlerSaveQuoteInfoRequest.setProductCode("CAR20190517");
-
-        // 设置产品名称
-        ziJinCrawlerSaveQuoteInfoRequest.setProductName("机动车保险");
-
-        // 设置提交信息
-        ziJinCrawlerSaveQuoteInfoRequest.setSubmitInfo(new HashMap<>());
-
-        // 设置车船税减免信息
-        ziJinCrawlerSaveQuoteInfoRequest.setTaxRelifInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveTaxRelifInfo(ziJinCrawlerQuotationResponse));
-
-        // 设置终端ID
-        ziJinCrawlerSaveQuoteInfoRequest.setTerminalId("KSCD");
-
-        // 设置终端类型
-        ziJinCrawlerSaveQuoteInfoRequest.setTerminalIdType("Vue-PC");
-
-        // 设置投保标识
-        ziJinCrawlerSaveQuoteInfoRequest.setInsuranceSign("0");
-
-        // 设置车辆信息
-        ziJinCrawlerSaveQuoteInfoRequest.setVehicleInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildVehicleInfo(ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
-
-        // 设置车辆设备保费列表
-        ziJinCrawlerSaveQuoteInfoRequest.setCarDevicePremiumDtoList(new ArrayList<>());
-
-        // 设置约定列表
-        ziJinCrawlerSaveQuoteInfoRequest.setEngageList(new ArrayList<>());
-
-        // 设置附件文件列表
-        ziJinCrawlerSaveQuoteInfoRequest.setItemFileDataList(buildSaveFileDataList(ziJinCrawlerQuotationResponse));
-
-        // 设置订单附加信息
-        ziJinCrawlerSaveQuoteInfoRequest.setOrderAttachInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveOrderAttachInfo(quoteVo, ziJinCrawlerQuotationRequest));
-
-        // 设置是否包含子机构
-        ziJinCrawlerSaveQuoteInfoRequest.setIsIncludeSubCom(1);
-
-        return ziJinCrawlerSaveQuoteInfoRequest;
-    }
-
-    private List<ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData> buildSaveFileDataList(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        // 获取图片上传信息
-        List<ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.FileInfo> imagesInfoList = ziJinCrawlerCacheComponent.getImagesInfo(ziJinCrawlerQuotationResponse.getOrderNo());
-        return Optional.ofNullable(ziJinCrawlerQuotationResponse.getItemKindList()).orElseGet(Collections::emptyList).stream().map(itemKindListDTO ->
-                ZiJinCrawlerSaveQuoteInfoRequest.ItemFileData.builder()
-                        .riskCode(itemKindListDTO.getRiskCode())
-                        .fileList(imagesInfoList)
-                        .build()
-        ).toList();
-    }
 }

+ 7 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/AgreementRulesController.java

@@ -67,6 +67,13 @@ public class AgreementRulesController extends BaseController {
         return HttpResult.ok(agreementRulesService.deleteById(id)? "删除成功":"删除失败");
     }
 
+    @Operation(summary = "根据父ID查询规则列表")
+    @GetMapping("/rulesListByParentId")
+    public HttpResult<List<AgreementRulesVo>> rulesListByParentId(String parentId) {
+        List<AgreementRulesVo> rulesVos = agreementRulesService.queryListByParentId(parentId);
+        return HttpResult.ok(rulesVos);
+    }
+
     @Operation(summary = "获取承保规则明细")
     @GetMapping("getRuleInfo")
     public HttpResult getRuleInfo(String ruleId){

+ 2 - 2
tenant/organization/src/main/java/com/jzg/organization/controller/SchemeController.java

@@ -96,8 +96,8 @@ public class SchemeController {
 
     @Operation(summary = "获取方案结果")
     @GetMapping("/getSchemeResult")
-    public HttpResult getSchemeResult(String companyId,String productId){
-        SchemeResultVo schemeResultVo = ptlSchemeService.getSchemeResult(companyId,productId);
+    public HttpResult getSchemeResult(String companyId,String productId,String seatCount){
+         SchemeResultVo schemeResultVo = ptlSchemeService.getSchemeResult(companyId,productId,seatCount);
         return HttpResult.ok(schemeResultVo);
     }
 

+ 8 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/PtlAgreementUndwrtRulesMapper.java

@@ -22,6 +22,14 @@ public interface PtlAgreementUndwrtRulesMapper extends BaseMapper<PtlAgreementUn
      * @return List<AgreementRulesVo>
      */
     List<AgreementRulesVo> queryList(@Param("agreementId") String agreementId);
+
+    /**
+     * 根据父ID查询规则列表
+     *
+     * @param parentId 父规则ID
+     * @return List<AgreementRulesVo>
+     */
+    List<AgreementRulesVo> queryListByParentId(@Param("parentId") String parentId);
 }
 
 

+ 9 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/jyxSettingMapper.java

@@ -0,0 +1,9 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.commons.entity.po.jyxSetting;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface jyxSettingMapper extends BaseMapper<jyxSetting> {
+}

+ 8 - 0
tenant/organization/src/main/java/com/jzg/organization/service/PtlAgreementUndwrtRulesService.java

@@ -45,6 +45,14 @@ public interface PtlAgreementUndwrtRulesService extends IService<PtlAgreementUnd
      */
     AgreementRulesVo rulesGet(String ruleId);
 
+    /**
+     * 根据父ID查询规则列表
+     *
+     * @param parentId 父规则ID
+     * @return List<AgreementRulesVo> 协议规则列表
+     */
+    List<AgreementRulesVo> queryListByParentId(String parentId);
+
     /**
      * 删除承保规则
      * @param id

+ 1 - 1
tenant/organization/src/main/java/com/jzg/organization/service/PtlSchemeService.java

@@ -80,7 +80,7 @@ public interface PtlSchemeService extends IService<PtlScheme> {
      * @param productId
      * @return
      */
-    public SchemeResultVo getSchemeResult(String companyId,String productId);
+    public SchemeResultVo getSchemeResult(String companyId,String productId,String seatCount);
 
     List<InsBusinessInsuranceVo> getBusinessInsuranceListByKindType(String kindCode);
 

+ 199 - 23
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementUndwrtRulesServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.jzg.commons.entity.dto.AgreementRulesAddParam;
 import com.jzg.commons.entity.dto.AgreementRulesEditParam;
 import com.jzg.commons.entity.dto.CostAgreementParam;
+import com.jzg.commons.entity.dto.RulesGroupParam;
 import com.jzg.commons.entity.po.PtlAgreementUndwrtRules;
 import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttr;
 import com.jzg.commons.entity.po.PtlAgreementUndwrtRulesAttrLink;
@@ -31,6 +32,8 @@ import org.springframework.transaction.annotation.Transactional;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -93,12 +96,49 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
                     rulesVo.setCostVoList(costVos);
                 }
             }
+            // 相同parentId的规则合并为一条,ruleDescription以","拼接
+            rulesVos = mergeByParentId(rulesVos);
         }
         return rulesVos;
     }
 
     /**
-     * 承保规则新增
+     * 将相同parentId的规则合并为一条,ruleDescription以","拼接
+     */
+    private List<AgreementRulesVo> mergeByParentId(List<AgreementRulesVo> rulesVos) {
+        List<AgreementRulesVo> result = new ArrayList<>();
+        Map<String, List<AgreementRulesVo>> groupMap = new LinkedHashMap<>();
+
+        for (AgreementRulesVo vo : rulesVos) {
+            String parentId = vo.getParentId();
+            if (parentId != null && !parentId.isEmpty()) {
+                groupMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(vo);
+            } else {
+                result.add(vo);
+            }
+        }
+
+        for (List<AgreementRulesVo> group : groupMap.values()) {
+            if (group.size() == 1) {
+                result.add(group.get(0));
+            } else {
+                AgreementRulesVo merged = group.get(0);
+                String joinedDesc = group.stream()
+                        .map(AgreementRulesVo::getRuleDescription)
+                        .filter(desc -> desc != null && !desc.isEmpty())
+                        .collect(Collectors.joining(","));
+                merged.setRuleDescription(joinedDesc);
+                result.add(merged);
+            }
+        }
+
+        result.sort(Comparator.comparing(AgreementRulesVo::getOrderNum,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        return result;
+    }
+
+    /**
+     * 承保规则新增(支持批量多条规则属性集合)
      *
      * @param param 要添加的承保规则
      * @return boolean 添加是否成功
@@ -107,29 +147,46 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
     @Transactional(rollbackFor = Exception.class)
     public boolean rulesAdd(AgreementRulesAddParam param) {
         log.info("添加承保规则:承保明细param=[{}]", JSONUtil.toJsonStr(param));
+
         // 根据协议id获取最大的序号
         LambdaQueryWrapper<PtlAgreementUndwrtRules> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(PtlAgreementUndwrtRules::getAgreementId, param.getAgreementId())
                 .eq(PtlAgreementUndwrtRules::getIsDelete, 0);
         queryWrapper.orderByDesc(PtlAgreementUndwrtRules::getOrderNum);
-        queryWrapper.last("LIMIT 1"); // 只取一个结果
+        queryWrapper.last("LIMIT 1");
         PtlAgreementUndwrtRules maxRules = baseMapper.selectOne(queryWrapper);
-        PtlAgreementUndwrtRules rules = new PtlAgreementUndwrtRules();
-        rules.setId(IdGenerate.nextId());
-        rules.setOrderNum(Objects.nonNull(maxRules) ? maxRules.getOrderNum() + 1 : 1);
-        rules.setStartTime(param.getStartTime());
-        rules.setEndTime(param.getEndTime());
-        rules.setAgreementId(param.getAgreementId());
+        int startOrderNum = Objects.nonNull(maxRules) ? maxRules.getOrderNum() + 1 : 1;
 
-        //遍历承保规则属性
         List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList = agreementUndwrtRulesAttrService.getUndwrtRulesAttrList();
+
+        // 批量模式:存在 rulesGroups 时
+        if (CollUtil.isNotEmpty(param.getRulesGroups())) {
+            String parentId = IdGenerate.nextId();
+            List<RulesGroupParam> groups = param.getRulesGroups();
+            for (int i = 0; i < groups.size(); i++) {
+                RulesGroupParam group = groups.get(i);
+                PtlAgreementUndwrtRules rules = buildRulesRecord(param, parentId, startOrderNum + i);
+
+                List<PtlAgreementUndwrtRulesAttrLink> andAttrLinks = processAndAttrs(group.getRulesAttrList(), undwrtRulesAttrList, rules.getId());
+
+                if (CollUtil.isNotEmpty(andAttrLinks)) {
+                    agreementUndwrtRulesAttrLinkMapper.insert(andAttrLinks);
+                }
+
+                rules.setRuleDescription(buildDesc(andAttrLinks, undwrtRulesAttrList));
+                baseMapper.insert(rules);
+            }
+            return true;
+        }
+
+        // 兼容旧的单条规则模式
+        PtlAgreementUndwrtRules rules = buildRulesRecord(param, null, startOrderNum);
         List<PtlAgreementUndwrtRulesAttrLink> rulesAttrList = param.getRulesAttrList();
         List<PtlAgreementUndwrtRulesAttrLink> costsAttrLink = new ArrayList<>();
         rulesAttrList.forEach(attr -> {
-
-            //判断空值
             if(Objects.isNull(attr.getMin()) && Objects.isNull(attr.getMax()) && Objects.isNull(attr.getMinArray())){
-                PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr = undwrtRulesAttrList.stream().filter(x -> x.getAttrCode().equals(attr.getAttrCode())).findFirst().orElse(null);
+                PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr = undwrtRulesAttrList.stream()
+                        .filter(x -> x.getAttrCode().equals(attr.getAttrCode())).findFirst().orElse(null);
                 throw new SystemException(ptlAgreementUndwrtRulesAttr.getAttrName() + "规则不能为空,请修改");
             }
             if (null != attr.getMin() ||  null != attr.getMax()) {
@@ -139,15 +196,98 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
             }
         });
         agreementUndwrtRulesAttrLinkMapper.insert(costsAttrLink);
-        //获取费用属性
         rules.setRuleDescription(buildDesc(costsAttrLink, undwrtRulesAttrList));
         baseMapper.insert(rules);
         baseMapper.updateById(rules);
         return true;
     }
 
+    /**
+     * 构建规则的公共字段
+     */
+    private PtlAgreementUndwrtRules buildRulesRecord(AgreementRulesAddParam param, String parentId, int orderNum) {
+        PtlAgreementUndwrtRules rules = new PtlAgreementUndwrtRules();
+        rules.setId(IdGenerate.nextId());
+        rules.setOrderNum(orderNum);
+        rules.setStartTime(param.getStartTime());
+        rules.setEndTime(param.getEndTime());
+        rules.setAgreementId(param.getAgreementId());
+        rules.setParentId(parentId);
+        return rules;
+    }
+
+    /**
+     * 处理并且规则属性
+     */
+    private List<PtlAgreementUndwrtRulesAttrLink> processAndAttrs(List<PtlAgreementUndwrtRulesAttrLink> attrs,
+                                                                    List<PtlAgreementUndwrtRulesAttr> attrMetaList,
+                                                                    String rulesId) {
+        List<PtlAgreementUndwrtRulesAttrLink> result = new ArrayList<>();
+        if (CollUtil.isEmpty(attrs)) {
+            return result;
+        }
+        attrs.forEach(attr -> {
+            if (Objects.isNull(attr.getMin()) && Objects.isNull(attr.getMax()) && Objects.isNull(attr.getMinArray())) {
+                PtlAgreementUndwrtRulesAttr meta = attrMetaList.stream()
+                        .filter(x -> x.getAttrCode().equals(attr.getAttrCode())).findFirst().orElse(null);
+                throw new SystemException(meta.getAttrName() + "规则不能为空,请修改");
+            }
+            if (null != attr.getMin() || null != attr.getMax()) {
+                attr.setRulesId(rulesId);
+                attr.setId(null);
+                result.add(attr);
+            }
+        });
+        return result;
+    }
+
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public boolean rulesEdit(AgreementRulesEditParam param) {
+        log.info("修改承保规则:承保明细param=[{}]", JSONUtil.toJsonStr(param));
+
+        List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList = agreementUndwrtRulesAttrService.getUndwrtRulesAttrList();
+
+        // 批量模式:存在 rulesGroups 时
+        if (CollUtil.isNotEmpty(param.getRulesGroups())) {
+            String parentId = param.getParentId();
+            if (parentId == null || parentId.isEmpty()) {
+                throw new SystemException("批量模式下父规则ID不能为空");
+            }
+
+            // 删除旧的所有子规则及其关联属性
+            List<AgreementRulesVo> oldRules = baseMapper.queryListByParentId(parentId);
+            if (CollUtil.isNotEmpty(oldRules)) {
+                for (AgreementRulesVo oldRule : oldRules) {
+                    agreementUndwrtRulesAttrLinkService.remove(new LambdaQueryWrapper<PtlAgreementUndwrtRulesAttrLink>()
+                            .eq(PtlAgreementUndwrtRulesAttrLink::getRulesId, oldRule.getId()));
+                    baseMapper.deleteById(oldRule.getId());
+                }
+            }
+
+            // 重新创建子规则
+            List<RulesGroupParam> groups = param.getRulesGroups();
+            for (int i = 0; i < groups.size(); i++) {
+                RulesGroupParam group = groups.get(i);
+                PtlAgreementUndwrtRules rules = new PtlAgreementUndwrtRules();
+                rules.setId(IdGenerate.nextId());
+                rules.setOrderNum(i + 1);
+                rules.setStartTime(param.getStartTime());
+                rules.setEndTime(param.getEndTime());
+                rules.setAgreementId(param.getAgreementId());
+                rules.setParentId(parentId);
+
+                List<PtlAgreementUndwrtRulesAttrLink> andAttrLinks = processAndAttrs(group.getRulesAttrList(), undwrtRulesAttrList, rules.getId());
+                if (CollUtil.isNotEmpty(andAttrLinks)) {
+                    agreementUndwrtRulesAttrLinkMapper.insert(andAttrLinks);
+                }
+                rules.setRuleDescription(buildDesc(andAttrLinks, undwrtRulesAttrList));
+                baseMapper.insert(rules);
+            }
+            return true;
+        }
+
+        // 兼容旧的单条规则模式
         PtlAgreementUndwrtRules rules = new PtlAgreementUndwrtRules();
         BeanUtils.copyProperties(param, rules);
 
@@ -155,7 +295,7 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
         agreementUndwrtRulesAttrLinkService.remove(new LambdaQueryWrapper<PtlAgreementUndwrtRulesAttrLink>()
                 .eq(PtlAgreementUndwrtRulesAttrLink::getRulesId, param.getId()));
 
-        List<PtlAgreementUndwrtRulesAttr> attrList = agreementUndwrtRulesAttrService.getUndwrtRulesAttrList();
+        List<PtlAgreementUndwrtRulesAttr> attrList = undwrtRulesAttrList;
         //再添加属性值
         List<PtlAgreementUndwrtRulesAttrLink> costsAttrLinks = param.getRulesAttrList();
         List<PtlAgreementUndwrtRulesAttrLink> costsAttrLink = new ArrayList<>();
@@ -194,16 +334,48 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
         PtlAgreementUndwrtRules rules = baseMapper.selectById(ruleId);
         AgreementRulesVo rulesVo = new AgreementRulesVo();
         BeanUtils.copyProperties(rules, rulesVo);
-        List<PtlAgreementUndwrtRulesAttrLink> linkList = agreementUndwrtRulesAttrLinkService.queryLinkList(ruleId);
-        // 获取费用因子属性
+
+        // 获取费用因子属性(公共逻辑,仅查询一次)
         List<PtlAgreementUndwrtRulesAttr> attrList = agreementUndwrtRulesAttrService.getUndwrtRulesAttrList();
         Map<String, PtlAgreementUndwrtRulesAttr> attrMap = attrList.stream()
                 .collect(Collectors.toMap(PtlAgreementUndwrtRulesAttr::getAttrCode, attr -> attr));
+
+        // 确定需要处理的规则ID列表
+        List<String> ruleIds;
+        if (rules.getParentId() != null && !rules.getParentId().isEmpty()) {
+            ruleIds = baseMapper.queryListByParentId(rules.getParentId()).stream()
+                    .map(AgreementRulesVo::getId).collect(Collectors.toList());
+        } else {
+            ruleIds = List.of(ruleId);
+        }
+
+        // 统一组装 groups
+        List<RulesGroupParam> groups = new ArrayList<>();
+        for (String id : ruleIds) {
+            List<PtlAgreementUndwrtRulesAttrLink> linkList = agreementUndwrtRulesAttrLinkService.queryLinkList(id);
+            List<PtlAgreementUndwrtRulesAttr> enrichedAttrs = enrichAttrLinks(linkList, attrMap);
+            RulesGroupParam group = new RulesGroupParam();
+            group.setRulesAttrList(linkList);
+            group.setCostsAttrLinks(enrichedAttrs);
+            groups.add(group);
+        }
+        rulesVo.setRulesGroups(groups);
+        // 单条模式向后兼容,同时设置 costsAttrLinks
+        if (ruleIds.size() == 1) {
+            rulesVo.setCostsAttrLinks(groups.get(0).getCostsAttrLinks());
+        }
+        return rulesVo;
+    }
+
+    /**
+     * 将属性链接丰富为完整的属性对象
+     */
+    private List<PtlAgreementUndwrtRulesAttr> enrichAttrLinks(List<PtlAgreementUndwrtRulesAttrLink> linkList,
+                                                               Map<String, PtlAgreementUndwrtRulesAttr> attrMap) {
         List<PtlAgreementUndwrtRulesAttr> newAttrList = new ArrayList<>();
         linkList.forEach(link -> {
-            if(attrMap.containsKey(link.getAttrCode())) {
-                PtlAgreementUndwrtRulesAttr attr= attrMap.get(link.getAttrCode());
-                //处理多选和下拉
+            if (attrMap.containsKey(link.getAttrCode())) {
+                PtlAgreementUndwrtRulesAttr attr = attrMap.get(link.getAttrCode());
                 if ("checkbox".equals(attr.getAttrType()) || "select".equals(attr.getAttrType()) || "inputTag".equals(attr.getAttrType())) {
                     if (null != link.getMin()) {
                         attr.setId(link.getId());
@@ -211,7 +383,7 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
                         attr.setMax(link.getMax());
                         attr.setOperator(link.getOperator());
                     }
-                }else{
+                } else {
                     attr.setId(link.getId());
                     attr.setMin(link.getMin());
                     attr.setMax(link.getMax());
@@ -219,10 +391,14 @@ public class PtlAgreementUndwrtRulesServiceImpl extends ServiceImpl<PtlAgreement
                 }
                 newAttrList.add(attr);
             }
-
         });
-        rulesVo.setCostsAttrLinks(newAttrList);
-        return rulesVo;
+        return newAttrList;
+    }
+
+    @Override
+    public List<AgreementRulesVo> queryListByParentId(String parentId) {
+        log.info("根据父ID查询协议承保规则列表。 parentId=[{}]", parentId);
+        return baseMapper.queryListByParentId(parentId);
     }
 
     @Override

+ 29 - 1
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java

@@ -20,6 +20,7 @@ import com.jzg.commons.entity.agreement.dispatch.vo.PtlAgreementDispatchVo;
 import com.jzg.commons.entity.agreement.dispatch.vo.ValidateDispatchRuleVo;
 import com.jzg.commons.entity.costs.vo.ValidateSchemeRuleVo;
 import com.jzg.commons.entity.po.*;
+import com.jzg.commons.entity.po.jyxSetting;
 import com.jzg.commons.entity.quote.vo.SalespersonInfoVo;
 import com.jzg.commons.entity.scheme.po.*;
 import com.jzg.commons.entity.scheme.vo.*;
@@ -92,6 +93,9 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
     @Autowired
     SysUserJzgInfoService sysUserJzgInfoService;
 
+    @Autowired
+    jyxSettingMapper jyxSettingMapper;
+
     /**
      * 添加方案
      * @param ptlSchemeSaveVo 车险报价的方案
@@ -487,10 +491,14 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
     }
 
     @Override
-    public SchemeResultVo getSchemeResult(String companyId, String productId) {
+    public SchemeResultVo getSchemeResult(String companyId, String productId,String seatCount) {
         log.info("根据保司Id和产品id查询协议信息。 companyId=[{}],productId=[{}]", companyId, productId);
         List<SchemeResultVo.SchemeVo> schemeInsuranceInfo = ptlSchemeMapper.getSchemeInsuranceInfo(companyId, productId);
         List<SchemeResultVo.SchemeVo> schemeDrivingInfo = ptlSchemeMapper.getSchemeDrivingInfo(companyId, productId);
+
+
+
+
         // 创建一个 Map,Key: info.id, Value: List<Driving>
         Map<String, List<SchemeResultVo.Driving>> drivingMap = new HashMap<>();
 
@@ -500,6 +508,26 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
                 drivingMap.put(info.getId(), info.getDrivings());
             }
         }
+        // 处理驾意险中的座位险逻辑,根据座位数匹配实际保险金额
+        if (StrUtil.isNotBlank(seatCount)) {
+            int seats = Integer.parseInt(seatCount);
+            drivingMap.forEach((infoId, drivings) -> {
+                drivings.forEach(driving -> {
+                    jyxSetting setting = jyxSettingMapper.selectOne(
+                            new LambdaQueryWrapper<jyxSetting>()
+                                    .eq(jyxSetting::getJyxConfigId, driving.getId())
+                                    .eq(jyxSetting::getSeats, seats)
+                                    .last("limit 1"));
+                    if (setting != null) {
+                        driving.setProductCode(setting.getProductCode());
+                        driving.setPremium(setting.getPremium() != null ? setting.getPremium().toString() : null);
+                        driving.setCoverage(setting.getCoverage() != null ? setting.getCoverage().toString() : null);
+                    }
+                });
+            });
+        }
+
+
 
         // 遍历 schemeInsuranceInfo,把 drivings 合并
         for (SchemeResultVo.SchemeVo insuranceScheme : schemeInsuranceInfo) {

+ 1 - 0
tenant/organization/src/main/resources/application.yml

@@ -68,6 +68,7 @@ tenant:
     - esm_ins_company
     - qr_barcode_config
     - jyx_config
+    - jyx_setting
     - sys_user_jzg_app
     - sys_dept
     - sys_user_jzg_info_salesman

+ 12 - 1
tenant/organization/src/main/resources/mapper/PtlAgreementUndwrtRulesMapper.xml

@@ -8,6 +8,7 @@
             <id property="id" column="id" jdbcType="VARCHAR"/>
             <result property="agreementId" column="agreement_id" jdbcType="VARCHAR"/>
             <result property="ruleDescription" column="rule_description" jdbcType="VARCHAR"/>
+            <result property="parentId" column="parent_id" jdbcType="VARCHAR"/>
             <result property="orderNum" column="order_num" jdbcType="INTEGER"/>
             <result property="createBy" column="create_by" jdbcType="VARCHAR"/>
             <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
@@ -17,7 +18,7 @@
     </resultMap>
 
     <sql id="Base_Column_List">
-        paur.id,paur.agreement_id,paur.rule_description,
+        paur.id,paur.agreement_id,paur.rule_description,paur.parent_id,
         paur.order_num,paur.create_by,paur.create_time,
         paur.update_by,paur.update_time,paur.is_delete
     </sql>
@@ -32,4 +33,14 @@
         </where>
         ORDER BY paur.order_num ASC
     </select>
+
+    <select id="queryListByParentId" resultType="com.jzg.commons.entity.vo.AgreementRulesVo">
+        SELECT <include refid="Base_Column_List"/>
+        FROM ptl_agreement_undwrt_rules paur
+        <where>
+            paur.is_delete = 0
+            AND paur.parent_id = #{parentId}
+        </where>
+        ORDER BY paur.order_num ASC
+    </select>
 </mapper>

+ 347 - 0
协议承保规则接口对接文档.md

@@ -0,0 +1,347 @@
+# 协议承保规则接口对接文档
+
+---
+
+## 一、新增承保规则
+
+**接口路径**:`POST /agreementRules/rulesAdd`
+
+### 请求参数
+
+| 字段名 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `agreementId` | String | 是 | 协议ID |
+| `startTime` | String | 否 | 生效开始时间 |
+| `endTime` | String | 否 | 生效截止时间 |
+| `rulesAttrList` | Array\<PtlAgreementUndwrtRulesAttrLink\> | 是 | 并且规则属性(AND 逻辑,单条规则模式) |
+| `rulesGroups` | Array\<RulesGroupParam\> | 否 | **【新增】** 规则属性分组(批量多条规则模式) |
+
+#### 两种模式说明
+
+- **单条规则模式**:使用 `rulesAttrList`,创建一条规则,`parentId` 为空
+- **批量规则模式**:使用 `rulesGroups`,一次创建多条规则,共享同一个 `parentId`,按分组顺序生成 `orderNum`
+- 两种模式互斥,优先使用 `rulesGroups` 批量模式
+
+### RulesGroupParam 结构
+
+| 字段名 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `rulesAttrList` | Array\<PtlAgreementUndwrtRulesAttrLink\> | 是 | 该组规则属性(AND 逻辑) |
+
+### PtlAgreementUndwrtRulesAttrLink 结构
+
+| 字段 | 类型 | 描述 |
+|---|---|---|
+| `attrId` | String | 协议属性ID |
+| `attrCode` | String | 协议属性编码 |
+| `min` | String | 左操作数(单选/输入值,数组时逗号分隔) |
+| `operator` | String | 运算符:1.范围 2.小于 3.小于等于 4.大于 5.大于等于 |
+| `max` | String | 右操作数(范围值上限) |
+| `minArray` | String[] | 左操作数数组(用于 checkbox/select/inputTag,非数据库字段) |
+
+### 请求体示例
+
+#### 单条规则模式
+
+```json
+{
+    "agreementId": "123456",
+    "startTime": "2026-01-01",
+    "endTime": "2026-12-31",
+    "rulesAttrList": [
+        {
+            "attrCode": "VehicleAge",
+            "min": "0",
+            "max": "5",
+            "operator": "1"
+        },
+        {
+            "attrCode": "LicenseArea",
+            "min": "BJ,SH",
+            "operator": "1"
+        }
+    ]
+}
+```
+
+#### 批量规则模式
+
+```json
+{
+    "agreementId": "123456",
+    "startTime": "2026-01-01",
+    "endTime": "2026-12-31",
+    "rulesGroups": [
+        {
+            "rulesAttrList": [
+                {
+                    "attrCode": "VehicleAge",
+                    "min": "0",
+                    "max": "5",
+                    "operator": "1"
+                }
+            ]
+        },
+        {
+            "rulesAttrList": [
+                {
+                    "attrCode": "LicenseArea",
+                    "min": "BJ,SH",
+                    "operator": "1"
+                },
+                {
+                    "attrCode": "Brand",
+                    "min": "AUDI,BMW",
+                    "operator": "1"
+                }
+            ]
+        }
+    ]
+}
+```
+
+### 响应
+
+```json
+{
+    "code": 200,
+    "msg": "添加承保规则成功"
+}
+```
+
+---
+
+## 二、修改承保规则
+
+**接口路径**:`POST /agreementRules/rulesEdit`
+
+### 请求参数
+
+| 字段名 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `id` | String | 是 | 承保规则ID |
+| `agreementId` | String | 是 | 协议ID |
+| `startTime` | String | 否 | 生效开始时间 |
+| `endTime` | String | 否 | 生效截止时间 |
+| `rulesAttrList` | Array\<PtlAgreementUndwrtRulesAttrLink\> | 是 | 并且规则属性(AND 逻辑) |
+
+### 请求体示例
+
+```json
+{
+    "id": "987654",
+    "agreementId": "123456",
+    "startTime": "2026-01-01",
+    "endTime": "2026-12-31",
+    "rulesAttrList": [
+        {
+            "attrCode": "VehicleAge",
+            "min": "0",
+            "max": "5",
+            "operator": "1"
+        }
+    ]
+}
+```
+
+> **修改逻辑**:先删除该规则下的所有旧属性关联数据,再重新插入新的规则属性。
+
+### 响应
+
+```json
+{
+    "code": 200,
+    "msg": "修改承保规则成功"
+}
+```
+
+---
+
+## 三、承保规则列表查询
+
+**接口路径**:`GET /agreementRules/rulesList`
+
+### 请求参数
+
+| 参数 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `agreementId` | String | 是 | 协议ID |
+
+### 响应字段
+
+| 字段 | 类型 | 描述 |
+|---|---|---|
+| `id` | String | 主键 |
+| `agreementId` | String | 协议ID |
+| `startTime` | String | 生效开始时间 |
+| `endTime` | String | 生效截止时间 |
+| `ruleDescription` | String | 规则描述文字 |
+| `parentId` | String | **【新增】** 父规则ID(批量模式时共用) |
+| `orderNum` | Integer | 显示顺序 |
+| `costsAttrLinks` | Array | 规则属性详情 |
+| `costVoList` | Array | 关联费用列表 |
+
+### 响应示例
+
+```json
+{
+    "code": 200,
+    "data": [
+        {
+            "id": "987654",
+            "agreementId": "123456",
+            "startTime": "2026-01-01",
+            "endTime": "2026-12-31",
+            "ruleDescription": "车龄范围值0到5,",
+            "parentId": "1792000000000000001",
+            "orderNum": 1,
+            "costsAttrLinks": [],
+            "costVoList": []
+        },
+        {
+            "id": "987655",
+            "agreementId": "123456",
+            "startTime": "2026-01-01",
+            "endTime": "2026-12-31",
+            "ruleDescription": "上牌城市为北京市,上海市,品牌为奥迪,宝马,",
+            "parentId": "1792000000000000001",
+            "orderNum": 2,
+            "costsAttrLinks": [],
+            "costVoList": []
+        }
+    ]
+}
+```
+
+---
+
+## 四、获取承保规则详情
+
+**接口路径**:`GET /agreementRules/rulesGet`
+
+### 请求参数
+
+| 参数 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `ruleId` | String | 是 | 承保规则ID |
+
+### 响应
+
+与列表接口返回结构一致,包含 `parentId` 字段。
+
+---
+
+## 五、根据父ID查询规则列表【新增】
+
+**接口路径**:`GET /agreementRules/rulesListByParentId`
+
+### 请求参数
+
+| 参数 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `parentId` | String | 是 | 父规则ID |
+
+### 功能说明
+
+当使用批量规则模式(`rulesGroups`)新增规则时,同批次的所有子规则共享同一个 `parentId`。调用此接口可根据 `parentId` 查询该批次下的所有子规则列表。
+
+### 响应字段
+
+与 `rulesList` 接口返回结构一致。
+
+### 响应示例
+
+```json
+{
+    "code": 200,
+    "data": [
+        {
+            "id": "987654",
+            "agreementId": "123456",
+            "startTime": "2026-01-01",
+            "endTime": "2026-12-31",
+            "ruleDescription": "车龄范围值0到5,",
+            "parentId": "1792000000000000001",
+            "orderNum": 1,
+            "costsAttrLinks": [],
+            "costVoList": []
+        },
+        {
+            "id": "987655",
+            "agreementId": "123456",
+            "startTime": "2026-01-01",
+            "endTime": "2026-12-31",
+            "ruleDescription": "上牌城市为北京市,上海市,",
+            "parentId": "1792000000000000001",
+            "orderNum": 2,
+            "costsAttrLinks": [],
+            "costVoList": []
+        }
+    ]
+}
+```
+
+---
+
+## 六、删除承保规则
+
+**接口路径**:`DELETE /agreementRules/rulesDelete`
+
+### 请求参数
+
+| 参数 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `id` | String | 是 | 承保规则ID |
+
+### 响应
+
+```json
+{
+    "code": 200,
+    "data": "删除成功"
+}
+```
+
+---
+
+## 七、获取承保规则明细
+
+**接口路径**:`GET /agreementRules/getRuleInfo`
+
+### 请求参数
+
+| 参数 | 类型 | 必填 | 描述 |
+|---|---|---|---|
+| `ruleId` | String | 是 | 承保规则ID |
+
+### 响应
+
+返回该规则下所有属性关联明细列表。
+
+---
+
+## 变更总结
+
+| 接口 | 变更点 | 变更内容 |
+|---|---|---|
+| `POST /rulesAdd` | 请求参数新增 | `rulesGroups`(批量规则分组),支持一次创建多条规则 |
+| `POST /rulesAdd` | 逻辑变更 | 批量模式下所有子规则共享同一 `parentId`,按分组顺序生成 `orderNum` |
+| `GET /rulesList` | 返回值新增 | `parentId`(父规则ID) |
+| `GET /rulesGet` | 返回值新增 | `parentId`(父规则ID) |
+| `GET /rulesListByParentId` | **新增接口** | 根据父ID查询子规则列表 |
+
+### 业务逻辑说明
+
+- **单条模式**:使用 `rulesAttrList` 创建一条规则,`parentId` 为 `null`
+- **批量模式**:使用 `rulesGroups` 一次创建多条规则,系统生成统一 `parentId` 关联同一批次的所有子规则
+- 批量模式与单条模式互斥,优先处理 `rulesGroups`
+- 通过 `rulesListByParentId` 接口可按 `parentId` 查询同批次的所有子规则
+- 修改接口仅支持对单条规则进行编辑
+
+### 数据库变更说明
+
+`ptl_agreement_undwrt_rules` 表需新增字段:
+
+```sql
+ALTER TABLE ptl_agreement_undwrt_rules ADD COLUMN parent_id VARCHAR(64) DEFAULT NULL COMMENT '父规则ID';
+```