Просмотр исходного кода

Merge branch 'master' into dev_jzg_lipf_v20260518

lipf 3 месяцев назад
Родитель
Сommit
32a8ecec81
25 измененных файлов с 808 добавлено и 587 удалено
  1. 2 2
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/api/service/impl/ChengTaiApiRequestImpl.java
  2. 2 2
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/filter/CarModelsFilterUtils.java
  3. 2 2
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/entity/request/HbCrawlerCalculationRequest.java
  4. 0 0
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/utils/HengBangAESUtil.java
  5. 1 1
      tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestBuilder.java
  6. 73 112
      tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestImpl.java
  7. 2 2
      tenant/insurance/quotation-summary/pom.xml
  8. 6 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/PreciseInitParam.java
  9. 4 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/PreciseInitResult.java
  10. 2 2
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/entity/TKDateInfo.java
  11. 14 5
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/entity/TKFlag.java
  12. 17 3
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/TKSimpleService.java
  13. 9 5
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/impl/TKQuotationBaseServiceImpl.java
  14. 107 17
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteResultsVoBuild.java
  15. 436 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerSaveQuoteInfoRequestBuild.java
  16. 5 3
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerRequestComponent.java
  17. 16 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQuotationRequest.java
  18. 2 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/response/ZiJinCrawlerRecognizeCodesResponse.java
  19. 19 15
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerQuoteProcessServiceImpl.java
  20. 25 412
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerRequestImpl.java
  21. 35 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/util/ConvertUtil.java
  22. 28 2
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/util/RS6Item.java
  23. 0 0
      tenant/insurance/quotation-zijin/src/main/resources/js/auto.js
  24. 1 1
      tenant/insurance/quotation-zijin/src/main/resources/js/content.js
  25. 0 0
      tenant/insurance/quotation-zijin/src/main/resources/js/tsssss.js

+ 2 - 2
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/api/service/impl/ChengTaiApiRequestImpl.java

@@ -265,10 +265,10 @@ public class ChengTaiApiRequestImpl implements ChengTaiApiRequest {
 
             }else{
                 // 转保车处理
-                ciQuestion = premiumCalculationResponse.getCompRisk() != null
+                ciQuestion = premiumCalculationResponse.getCompRisk().getBasePart() != null
                         ? premiumCalculationResponse.getCompRisk().getBasePart().getQuestion()
                         : null;
-                biQuestion = premiumCalculationResponse.getCommRisk() != null
+                biQuestion = premiumCalculationResponse.getCommRisk().getBasePart() != null
                         ? premiumCalculationResponse.getCommRisk().getBasePart().getQuestion()
                         : null;
                 // 订单号

+ 2 - 2
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/filter/CarModelsFilterUtils.java

@@ -16,7 +16,7 @@ import java.util.stream.Collectors;
 public final class CarModelsFilterUtils {
 
     public static <T extends CarModelsFilter> T to(List<T> carModelsFilterList, CarInfoVo carInfo) {
-        if (carModelsFilterList == null) {
+        if (carModelsFilterList == null || carModelsFilterList.isEmpty()) {
             throw new SystemException("核心查询车型失败 请联系业务人员处理");
         }
         List<T> stadarCarDTOS = new ArrayList<>();
@@ -35,7 +35,7 @@ public final class CarModelsFilterUtils {
 
         carModelsFilterList = carModelsFilterList.stream().filter(car -> carInfo.getPurchasePrice().equals(String.valueOf(car.getPurchasePrice()))).collect(Collectors.toList());
 
-        if (carModelsFilterList.isEmpty()) {
+        if (!stadarCarDTOS.isEmpty()) {
             return stadarCarDTOS.get(0);
         }
 

+ 2 - 2
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/entity/request/HbCrawlerCalculationRequest.java

@@ -141,8 +141,8 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
         dto.setProgramcode(vo.getProductCode());
         dto.setProgramname(vo.getProductName());
         if (biRiskInfoVo != null && StringUtils.isNotBlank(biRiskInfoVo.getStartDate()) && StringUtils.isNotBlank(biRiskInfoVo.getEndDate())) {
-            dto.setBegintime(DateUtil.toUtcDateTime(biRiskInfoVo.getStartDate()));
-            dto.setEndtime(DateUtil.toUtcDateTime(biRiskInfoVo.getEndDate()));
+            dto.setBegintime(DateUtil.toUtcDateTime(DateUtil.getCurrentDate(1) + " 00:00:00"));
+            dto.setEndtime(DateUtil.toUtcDateTime(DateUtil.getNextYearDateStrTranfer(DateUtil.getCurrentDate(1) + " 00:00:00")));
         }
         dto.setCompanycode("0107");
         dto.setRelationcarowner("a");

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/utils/HengBangAESUtil.java


+ 1 - 1
tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestBuilder.java

@@ -972,7 +972,7 @@ public class RenBaoNewCrawlerRequestBuilder {
     }
 
     /**
-     * 将险种信息列表转换为Map列表(使用反射,不依赖 KindInfoVo 的具体实现)
+     * 将险种信息列表转换为Map列表
      *
      * @param kindList 险种信息列表
      * @return Map列表,每个元素包含 kindCode, kindName, amount, serviceTimes, deductibleRate 等字段

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

@@ -631,50 +631,59 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
                 headers
         );
 
+        // ① 校验查询订单接口返回 —  :先检查message是否为Success
+        if (orderInfo == null || !"Success".equals(orderInfo.get("message"))) {
+            String statusText = orderInfo != null ? (String) orderInfo.get("statusText") : "查询订单响应为空";
+            throw new SystemException("查询订单异常: " + statusText);
+        }
+
+        // ② 获取result列表并校验长度 —  :只能为1或2条
+        Map<String, Object> data = (Map<String, Object>) orderInfo.get("data");
+        if (data == null || !data.containsKey("result")) {
+            throw new SystemException("查询订单异常: 未查询到订单");
+        }
+        List<Map<String, Object>> itemList = (List<Map<String, Object>>) data.get("result");
+        if (itemList == null || itemList.isEmpty()) {
+            throw new SystemException("查询订单异常: 未查询到订单");
+        }
+        if (itemList.size() > 2) {
+            throw new SystemException("查询订单异常");
+        }
+
+        // ③ 提取交强/商业单号,以及驾意险信息 —  
         String syProposalNo = "";
         String jqProposalNo = "";
-        List<String> documentnolist = new ArrayList<>();
         List<Map<String, String>> unitNoCarDataList = new ArrayList<>();
-
-        if (orderInfo != null && orderInfo.containsKey("data")) {
-            Map<String, Object> data = (Map<String, Object>) orderInfo.get("data");
-            if (data != null && data.containsKey("result")) {
-                List<Map<String, Object>> itemList = (List<Map<String, Object>>) data.get("result");
-                if (itemList != null && !itemList.isEmpty()) {
-                    for (Map<String, Object> item : itemList) {
-                         businessNo = (String) item.get("businessNo");
-                        if (businessNo != null) {
-                            if (businessNo.contains("DAA")) {
-                                syProposalNo = businessNo;
-                                documentnolist.add(businessNo);
-                            } else if (businessNo.contains("DZA")) {
-                                jqProposalNo = businessNo;
-                                documentnolist.add(businessNo);
-                            }
-                        }
-                    }
-
-                    Map<String, Object> firstItem = itemList.get(0);
-                    if (firstItem.containsKey("relationUPolicyInfolist")) {
-                        List<Map<String, Object>> relationList = (List<Map<String, Object>>) firstItem.get("relationUPolicyInfolist");
-                        if (relationList != null) {
-                            for (Map<String, Object> item : relationList) {
-                                String connectProposalNo = (String) item.get("connectProposalNo");
-                                if (connectProposalNo != null && !connectProposalNo.isEmpty()) {
-                                    documentnolist.add(connectProposalNo);
-                                    if (connectProposalNo.contains("EAD")) {
-                                        unitNoCarDataList.add(Map.of("uniteProposalNo", connectProposalNo, "riskCode", "EAD"));
-                                    } else if (connectProposalNo.contains("EBS")) {
-                                        unitNoCarDataList.add(Map.of("uniteProposalNo", connectProposalNo, "riskCode", "EBS"));
-                                    }
-                                }
-                            }
+        for (Map<String, Object> item : itemList) {
+            String bNo = (String) item.get("businessNo");
+            if (bNo == null) {
+                continue;
+            }
+            if (bNo.contains("DAA")) {
+                syProposalNo = bNo;
+            } else if (bNo.contains("DZA")) {
+                jqProposalNo = bNo;
+            }
+        }
+        // 提取驾意险关联单号(从relationUPolicyInfolist)
+        Map<String, Object> firstItem = itemList.get(0);
+        if (firstItem.containsKey("relationUPolicyInfolist")) {
+            List<Map<String, Object>> relationList = (List<Map<String, Object>>) firstItem.get("relationUPolicyInfolist");
+            if (relationList != null) {
+                for (Map<String, Object> relItem : relationList) {
+                    String connectProposalNo = (String) relItem.get("connectProposalNo");
+                    if (connectProposalNo != null && !connectProposalNo.isEmpty()) {
+                        if (connectProposalNo.contains("EAD")) {
+                            unitNoCarDataList.add(Map.of("uniteProposalNo", connectProposalNo, "riskCode", "EAD"));
+                        } else if (connectProposalNo.contains("EBS")) {
+                            unitNoCarDataList.add(Map.of("uniteProposalNo", connectProposalNo, "riskCode", "EBS"));
                         }
                     }
                 }
             }
         }
 
+        // ④ 提交核保
         RenBaoNewCrawlerUnderwritingRequest uwRequest = new RenBaoNewCrawlerUnderwritingRequest();
         uwRequest.setPrpbi(syProposalNo);
         uwRequest.setPrpci(jqProposalNo);
@@ -687,17 +696,22 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
         RenBaoNewCrawlerUnderwritingResponse uwResponse = requestComponent.submitUnderwriting(uwRequest, headers);
         log.info("Underwriting response: {}", JSONUtil.toJsonStr(uwResponse));
 
+        // ⑤ 校验核保返回 —  :检查message
         if (uwResponse == null || !"Success".equals(uwResponse.getMessage())) {
             String errorMsg = uwResponse != null ? uwResponse.getStatusText() : "核保响应为空";
             throw new SystemException("提交核保异常: " + errorMsg);
         }
 
+        // ⑥ 解析核保结果 —  :从undwrtForPassList和unitNoCarUnderWriteStateList中收集状态和错误信息
+        //    同时在这里构建documentnolist(支付接口用,必须在核保成功后才收集)
         String syState = "";
         String jqState = "";
         String eadState = "";
         String ebsState = "";
         String errorMessage = "";
         boolean errorFlag = false;
+        List<String> documentnolist = new ArrayList<>();
+        List<String> jyxBusinessNoList = new ArrayList<>();
 
         if (uwResponse.getData() != null && uwResponse.getData().getUndwrtForPassList() != null) {
             for (RenBaoNewCrawlerUnderwritingResponse.UndwrtForPassItem item : uwResponse.getData().getUndwrtForPassList()) {
@@ -707,9 +721,15 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
                     continue;
                 }
                 if (item.getProposalNo().contains("DAA")) {
+                    // 商业险
+                    syProposalNo = item.getProposalNo();
+                    documentnolist.add(syProposalNo);
                     syState = item.getUndwrtFlag() != null ? item.getUndwrtFlag() : item.getState();
                     errorMessage += "商业提核结果:" + item.getHandleText() + "; ";
                 } else if (item.getProposalNo().contains("DZA")) {
+                    // 交强险
+                    jqProposalNo = item.getProposalNo();
+                    documentnolist.add(jqProposalNo);
                     jqState = item.getUndwrtFlag() != null ? item.getUndwrtFlag() : item.getState();
                     errorMessage += "交强提核结果:" + item.getHandleText() + "; ";
                 }
@@ -724,43 +744,34 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
                     continue;
                 }
                 if (item.getBusinessNo().contains("EAD")) {
+                    // 驾意险EAD
+                    documentnolist.add(item.getBusinessNo());
+                    jyxBusinessNoList.add(item.getBusinessNo());
                     eadState = item.getState();
                     errorMessage += "驾意险EAD提核结果:" + item.getContent() + "; ";
                 } else if (item.getBusinessNo().contains("EBS")) {
+                    // 驾意险EBS
+                    documentnolist.add(item.getBusinessNo());
+                    jyxBusinessNoList.add(item.getBusinessNo());
                     ebsState = item.getState();
                     errorMessage += "驾意险EBS提核结果:" + item.getContent() + "; ";
                 }
             }
         }
 
+        // ⑦ errorFlag为true时直接抛异常 —  
         if (errorFlag) {
             throw new SystemException(errorMessage);
         }
 
-        if ("2".equals(jqState) || "2".equals(syState)) {
-            StringBuilder detailErrorMessage = new StringBuilder();
-            if (!jqProposalNo.isEmpty() && "2".equals(jqState)) {
-                Map<String, Object> jqUndwrtDetail = requestComponent.viewUndwrt(jqProposalNo, loginInfo.getUserCode(), headers);
-                String jqHandleText = parseViewUndwrtHandleText(jqUndwrtDetail);
-                detailErrorMessage.append("交强返回:").append(jqHandleText != null ? jqHandleText : errorMessage).append("; ");
-            }
-            if (!syProposalNo.isEmpty() && "2".equals(syState)) {
-                Map<String, Object> syUndwrtDetail = requestComponent.viewUndwrt(syProposalNo, loginInfo.getUserCode(), headers);
-                String syHandleText = parseViewUndwrtHandleText(syUndwrtDetail);
-                detailErrorMessage.append("商业返回:").append(syHandleText != null ? syHandleText : errorMessage);
-            }
-            if (detailErrorMessage.length() > 0) {
-                throw new SystemException(detailErrorMessage.toString());
-            }
-            throw new SystemException(errorMessage);
-        }
-
+        // ⑧ 交强险/商业险状态校验 —  :只允许 3/4/5/9
         if (!jqState.isEmpty() && !"3".equals(jqState) && !"4".equals(jqState) && !"5".equals(jqState) && !"9".equals(jqState)) {
             throw new SystemException(errorMessage);
         }
         if (!syState.isEmpty() && !"3".equals(syState) && !"4".equals(syState) && !"5".equals(syState) && !"9".equals(syState)) {
             throw new SystemException(errorMessage);
         }
+        // 驾意险状态校验 —  :只允许 3/4/5(驾意险没有9状态)
         if (!eadState.isEmpty() && !"3".equals(eadState) && !"4".equals(eadState) && !"5".equals(eadState)) {
             throw new SystemException(errorMessage);
         }
@@ -768,80 +779,30 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
             throw new SystemException(errorMessage);
         }
 
+        // 状态为9(待人工核保)—  :直接返回
         if ("9".equals(jqState) || "9".equals(syState)) {
-            String processInfo = "";
-            if (!jqProposalNo.isEmpty() && "9".equals(jqState)) {
-                Map<String, Object> jqProcessInfo = requestComponent.getUndwrtProcessInfo(jqProposalNo, headers);
-                String jqMsg = parseUndwrtProcessInfoMsg(jqProcessInfo);
-                if (jqMsg != null && !jqMsg.isEmpty()) {
-                    processInfo = jqMsg;
-                }
-            }
-            if (!syProposalNo.isEmpty() && "9".equals(syState)) {
-                Map<String, Object> syProcessInfo = requestComponent.getUndwrtProcessInfo(syProposalNo, headers);
-                String syMsg = parseUndwrtProcessInfoMsg(syProcessInfo);
-                if (syMsg != null && !syMsg.isEmpty()) {
-                    processInfo = processInfo.isEmpty() ? syMsg : (processInfo + "; " + syMsg);
-                }
-            }
-            String finalErrorMessage = processInfo.isEmpty() ? errorMessage : processInfo;
             UnderwritingResultsVo resultsVo = new UnderwritingResultsVo();
             resultsVo.setUnderwritingStatus(InsOrderStatusEnum.STAFF_PROCESS);
-            resultsVo.setUnderwritingResult(finalErrorMessage);
+            resultsVo.setUnderwritingResult(errorMessage);
+            resultsVo.setJqApplyNo(jqProposalNo);
+            resultsVo.setSyApplyNo(syProposalNo);
+            resultsVo.setJyApplyNo(jyxBusinessNoList.isEmpty() ? "" : String.join(",", jyxBusinessNoList));
             return resultsVo;
         }
 
+        // ⑩ 正常核保通过 — 获取支付链接(带重试,与Python的get_pay_url循环一致)
         String payUrl = getPaymentUrlWithRetry(documentnolist, loginInfo, headers);
 
         UnderwritingResultsVo resultsVo = new UnderwritingResultsVo();
         resultsVo.setPaymentLink(payUrl);
         resultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
         resultsVo.setUnderwritingResult("操作成功");
+        resultsVo.setJqPolicyno(jqProposalNo);
+        resultsVo.setSyPolicyno(syProposalNo);
+        resultsVo.setJyPolicyno(jyxBusinessNoList.isEmpty() ? "" : String.join(",", jyxBusinessNoList));
         return resultsVo;
     }
 
-    private String parseViewUndwrtHandleText(Map<String, Object> response) {
-        if (response == null) {
-            return null;
-        }
-        Object dataObj = response.get("data");
-        if (dataObj == null) {
-            return null;
-        }
-        if (dataObj instanceof List) {
-            @SuppressWarnings("unchecked")
-            List<Map<String, Object>> dataList = (List<Map<String, Object>>) dataObj;
-            if (!dataList.isEmpty()) {
-                Object handleText = dataList.get(0).get("handleText");
-                return handleText != null ? handleText.toString() : null;
-            }
-        }
-        return null;
-    }
-
-    private String parseUndwrtProcessInfoMsg(Map<String, Object> response) {
-        if (response == null) {
-            return null;
-        }
-        Object dataObj = response.get("data");
-        if (dataObj == null || !(dataObj instanceof Map)) {
-            return null;
-        }
-        @SuppressWarnings("unchecked")
-        Map<String, Object> data = (Map<String, Object>) dataObj;
-        Object underwritingInfosObj = data.get("underwritingInfos");
-        if (underwritingInfosObj == null || !(underwritingInfosObj instanceof List)) {
-            return null;
-        }
-        @SuppressWarnings("unchecked")
-        List<Map<String, Object>> underwritingInfos = (List<Map<String, Object>>) underwritingInfosObj;
-        if (!underwritingInfos.isEmpty()) {
-            Object msg = underwritingInfos.get(0).get("msg");
-            return msg != null ? msg.toString() : null;
-        }
-        return null;
-    }
-
     private String getPaymentUrlWithRetry(List<String> documentnolist, LoginInfoBO loginInfo, HttpHeaders headers) {
         RenBaoNewCrawlerPayRequest payRequest = new RenBaoNewCrawlerPayRequest();
         payRequest.setDocumentnolist(documentnolist);

+ 2 - 2
tenant/insurance/quotation-summary/pom.xml

@@ -106,12 +106,12 @@
             <version>1.0-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
-        <!--<dependency>
+        <dependency>
             <groupId>com.jzg</groupId>
             <artifactId>quotation-zijin</artifactId>
             <version>1.0-SNAPSHOT</version>
             <scope>compile</scope>
-        </dependency>-->
+        </dependency>
         <dependency>
             <groupId>com.jzg</groupId>
             <artifactId>quotation-hengbang</artifactId>

+ 6 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/PreciseInitParam.java

@@ -192,6 +192,11 @@ public class PreciseInitParam extends OrderRequest {
     @JsonProperty("carProduct")
     private TKCarProduct carProduct;
 
+    /**
+     * 泰乐途
+     */
+    private List<PreciseInitResult.NonCarProductListDTO> nonCarProductList;
+
 
 
     @Override
@@ -210,6 +215,7 @@ public class PreciseInitParam extends OrderRequest {
         addChildUnknownField("carTaxInfo", carTaxInfo);
         addChildUnknownField("insureInfo", insureInfo);
         addChildUnknownField("carProduct", carProduct);
+        addChildUnknownField("carProduct", carProduct);
     }
 }
 

+ 4 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/PreciseInitResult.java

@@ -183,6 +183,9 @@ public class PreciseInitResult extends UnknownFieldEntity {
 
     private List<?> expect;
 
+    /**
+     * 泰乐途
+     */
     private List<NonCarProductListDTO> nonCarProductList;
 
     @NoArgsConstructor
@@ -234,6 +237,7 @@ public class PreciseInitResult extends UnknownFieldEntity {
         addChildUnknownField("carTaxInfo", carTaxInfo);
         addChildUnknownField("chargingPost", chargingPost);
         addChildUnknownField("deviceList", deviceList);
+        addChildUnknownField("nonCarProductList", nonCarProductList);
     }
 
 }

+ 2 - 2
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/entity/TKDateInfo.java

@@ -21,11 +21,11 @@ public class TKDateInfo extends UnknownFieldEntity {
      */
     private String enrollDate;
     /**
-     * 交强险初始开始日期
+     * 商业险初始开始日期
      */
     private String initStartDateBZ;
     /**
-     * 商业险初始开始日期
+     * 交强险初始开始日期
      */
     private String initStartDateCI;
     /**

+ 14 - 5
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/entity/TKFlag.java

@@ -18,7 +18,7 @@ public class TKFlag extends UnknownFieldEntity {
      */
     private String bzFlag;
     /**
-     * 车辆服务API展示标志
+     * 车辆服务API展示标志, 1 = 页面展示泰乐途随车增值服务包(救援 + 驾乘),泰乐途展示开关
      */
     private String carServiceApiPresentShowFlag;
     /**
@@ -26,11 +26,11 @@ public class TKFlag extends UnknownFieldEntity {
      */
     private String ciFlag;
     /**
-     * 预期折扣标志
+     * 预期折扣标志:  2代表无法使用自主费率优惠、管控折扣
      */
     private String expectDiscountFlag;
     /**
-     * 预期显示标志
+     * 展示优惠弹窗
      */
     private Boolean expectShowFlag;
     /**
@@ -58,7 +58,7 @@ public class TKFlag extends UnknownFieldEntity {
      */
     private String instantInsureFlagCI;
     /**
-     * 是否意外险标志
+     * 是否意外险标志: 1绑定驾乘意外险(泰乐途标配驾乘保障,配套标识)
      */
     private String isAccidentInsureFlag;
     /**
@@ -90,7 +90,7 @@ public class TKFlag extends UnknownFieldEntity {
     private String quoteFlag;
 
     /**
-     * 报价联动标志
+     * 报价联动标志: 1.主险联动附加产品报价,自动带出泰乐途套餐
      */
     private String quoteLinkageFlag;
 
@@ -119,9 +119,18 @@ public class TKFlag extends UnknownFieldEntity {
      */
     private String renewalFlag;
 
+    /**
+     * 0 = 不启用备选报价方案
+     */
     private String alternativePlanFlag;
 
+    /**
+     * 判定泰乐途最核心字段:渠道来源编码,64827 = 泰乐途专属渠道(决定性标识)
+     */
     private String innerFromId;
 
+    /**
+     * 是否员工内部车
+     */
     private String isStaffCar;
 }

+ 17 - 3
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/TKSimpleService.java

@@ -994,15 +994,16 @@ public class TKSimpleService {
                 preciseInitParam.setFlag(flag);
             }
             flag.setVipWeekFlag("0");
+            flag.setQuoteLinkageFlag("0");
 
             // 无商业险
             if (CollectionUtils.isEmpty(commonQuoteVo.getKindInfoVo())) {
                 flag.setCiFlag("0");
             }
             // 无驾意险,经测试这个值无驾意险的时候请求还是传1,不用改变
-            // if (CollectionUtils.isEmpty(commonQuoteVo.getAccidentalDrivings())) {
-            //     flag.setIsAccidentInsureFlag("0");
-            // }
+            if (CollectionUtils.isEmpty(commonQuoteVo.getAccidentalDrivings())) {
+                flag.setIsAccidentInsureFlag("0");
+            }
         }
 
         // 其他参数
@@ -1067,6 +1068,9 @@ public class TKSimpleService {
             if (commonBiRiskInfoVo != null) {
                 date.setStartDateCI(commonBiRiskInfoVo.getStartDate());
                 date.setEndDateCI(commonBiRiskInfoVo.getEndDate());
+            } else {
+                date.setStartDateCI(date.getStartDateCI());
+                date.setEndDateCI(date.getEndDateCI());
             }
 
             // 获取保司默认选中的商险信息
@@ -1135,9 +1139,19 @@ public class TKSimpleService {
                 driverAccidentVo.setIsSelect("0");
                 driverAccidentVo.setQuantity(0);
                 driverAccidentVo.setQuantityCname("不投保");
+                driverAccidentVo.setPremium(BigDecimal.ZERO);
             }
         }
 
+        // 泰乐途, 默认不投保
+        List<PreciseInitResult.NonCarProductListDTO> nonCarProductList = preciseInitParam.getNonCarProductList();
+        if (CollectionUtils.isNotEmpty(nonCarProductList)) {
+            nonCarProductList.forEach(nonCarProductListDTO -> {
+                nonCarProductListDTO.setIsSelect("0");
+                nonCarProductListDTO.setPremium("0");
+            });
+        }
+
         // 请求接口
         preciseInitParam.setChannelCode("OffWeb");
         preciseInitParam.setInitFlag("quote");

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

@@ -38,7 +38,6 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
-import java.util.Optional;
 
 @QuoteCrawlerService(value = InsuranceCode.INSURANCE_TKIC)
 @RequiredArgsConstructor
@@ -579,16 +578,21 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
         quoteResultsVo.setOrdersNo(commonQuoteVo.getOrder().getOrdersNo());
 
         TKDateInfo date = preciseInitResult.getDate();
+        // todo: 保司返回的时间与报价时选的投保时间不一致(发现保司报价页面时间不能自由选择,投保开始时间会延后,导致保单结束时间也会延后),所以这里将保司返回的时间设置为报价时选的投保时间
         // 交强险
         RiskInfoVo riskInfoVo1 = new RiskInfoVo();
-        riskInfoVo1.setStartDate(DateTimeUtils.convertToDateTime(date.getJqStartDate(), date.getJqStartHour(), date.getJqStartMinute()));
-        riskInfoVo1.setEndDate(DateTimeUtils.convertToDateTime(date.getJqEndDate(), date.getJqEndHour(), date.getJqEndMinute()));
+        // riskInfoVo1.setStartDate(DateTimeUtils.convertToDateTime(date.getJqStartDate(), date.getJqStartHour(), date.getJqStartMinute()));
+        // riskInfoVo1.setEndDate(DateTimeUtils.convertToDateTime(date.getJqEndDate(), date.getJqEndHour(), date.getJqEndMinute()));
+        riskInfoVo1.setStartDate(commonQuoteVo.getCiRiskInfoVo().getStartDate());
+        riskInfoVo1.setEndDate(commonQuoteVo.getCiRiskInfoVo().getEndDate());
         quoteResultsVo.setCiRiskInfoVo(riskInfoVo1);
 
         // 商业险
         RiskInfoVo riskInfoVo2 = new RiskInfoVo();
-        riskInfoVo2.setStartDate(DateTimeUtils.convertToDateTime(date.getSyStartDate(), date.getSyStartHour(), date.getSyStartMinute()));
-        riskInfoVo2.setEndDate(DateTimeUtils.convertToDateTime(date.getSyEndDate(), date.getSyEndHour(), date.getSyEndMinute()));
+        // riskInfoVo2.setStartDate(DateTimeUtils.convertToDateTime(date.getSyStartDate(), date.getSyStartHour(), date.getSyStartMinute()));
+        // riskInfoVo2.setEndDate(DateTimeUtils.convertToDateTime(date.getSyEndDate(), date.getSyEndHour(), date.getSyEndMinute()));
+        riskInfoVo2.setStartDate(commonQuoteVo.getBiRiskInfoVo() == null ? commonQuoteVo.getCiRiskInfoVo().getStartDate() : commonQuoteVo.getBiRiskInfoVo().getStartDate());
+        riskInfoVo2.setEndDate(commonQuoteVo.getBiRiskInfoVo() == null ? commonQuoteVo.getCiRiskInfoVo().getEndDate() : commonQuoteVo.getBiRiskInfoVo().getEndDate());
         quoteResultsVo.setBiRiskInfoVo(riskInfoVo2);
 
         // 驾意险

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

@@ -1,6 +1,8 @@
 package com.jzg.quotation.zijin.crawler.build;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.alibaba.nacos.common.utils.CollectionUtils;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
@@ -8,9 +10,11 @@ import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.RiskInfoVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.commons.util.DateTimeUtils;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.zijin.api.constant.enums.RiskCodeEnum;
 import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.ObjectUtils;
 
 import java.util.List;
 import java.util.Map;
@@ -27,6 +31,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
 
     /**
      * 处理报价失败结果
+     *
      * @param ziJinCrawlerQuotationResponse
      * @return QuoteResultsVo
      */
@@ -35,13 +40,14 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
         quoteResultsVo.setCompanyOrderNo("");
         // 报价失败提示
         quoteResultsVo.setErrorMessage(ziJinCrawlerQuotationResponse.getRtnMsg());
-        //设置报价状态
+        // 设置报价状态
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
         return quoteResultsVo;
     }
 
     /**
      * 处理报价结果
+     *
      * @param ordersNo
      * @param quoteVo
      * @param ziJinCrawlerQuotationResponse
@@ -64,21 +70,24 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
 
         // 交强保费 车船税 商业保费
         buildPremium(quoteResultsVo, ziJinCrawlerQuotationResponse);
-        
+
         // 设置投保单号
         // if (ziJinCrawlerQuotationResponse.getBasePart() != null) {
         //     quoteResultsVo.setCiPolicyNumber(ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo());
         //     quoteResultsVo.setBiPolicyNumber(ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo());
         // }
-        
+
         // 设置警告消息(预核保消息)
         if (ziJinCrawlerQuotationResponse.getBasePart() != null) {
             List<String> warnMessages = new java.util.ArrayList<>();
             warnMessages.add(ziJinCrawlerQuotationResponse.getBasePart().getPreUnderwriteMessage());
             quoteResultsVo.setWarnMessageList(warnMessages);
         }
-        
-        //设置报价状态:带核保
+
+        // 设置评分
+        quoteResultsVo.setScoreVo(ZiJinCrawlerQuoteResultsVoBuild.buildScoreVo(ziJinCrawlerQuotationResponse));
+
+        // 设置报价状态:待核保
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
 
         log.info("quoteResultsVo参数的值:{}", JSON.toJSONString(quoteResultsVo));
@@ -87,6 +96,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
 
     /**
      * 处理交强险数据
+     *
      * @param quotationResponse
      * @return RiskInfoVo
      */
@@ -100,6 +110,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
 
     /**
      * 处理商业险数据
+     *
      * @param quotationResponse
      * @return RiskInfoVo
      */
@@ -125,6 +136,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
 
     /**
      * 处理险种明细列表
+     *
      * @param quotationResponse
      * @return List<KindInfoVo>
      */
@@ -133,7 +145,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
         if (quotationResponse.getItemKindList() == null) {
             return kindInfoVoList;
         }
-        
+
         for (ZiJinCrawlerQuotationResponse.ItemKindList item : quotationResponse.getItemKindList()) {
             KindInfoVo kindInfoVo = new KindInfoVo();
             kindInfoVo.setKindCode(item.getKindCode());
@@ -144,12 +156,13 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
             kindInfoVo.setPremium(item.getPremium());
             kindInfoVoList.add(kindInfoVo);
         }
-        
+
         return kindInfoVoList;
     }
 
     /**
      * 设置商业险,交强险保费
+     *
      * @param quoteResultsVo
      * @param quotationResponse
      */
@@ -157,16 +170,16 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
         if (CollectionUtils.isEmpty(quotationResponse.getPlanList())) {
             return;
         }
-        
+
         // 遍历 planList,根据 riskCode 或 planText 来识别不同类型的费用
         for (ZiJinCrawlerQuotationResponse.PlanList plan : quotationResponse.getPlanList()) {
             if (plan == null || plan.getPlanFee() == null) {
                 continue;
             }
-            
+
             String riskCode = plan.getRiskCode();
             String planText = plan.getPlanText();
-            
+
             // 根据 riskCode 判断类型
             if (RiskCodeEnum.TRAFFIC_CODE.equals(riskCode)) {
                 // 交强险
@@ -182,7 +195,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 }
             }
         }
-        
+
         // 设置非车险(驾意险)保费
         if (quotationResponse.getCarPolicySubInfoList() != null && !quotationResponse.getCarPolicySubInfoList().isEmpty()) {
             ZiJinCrawlerQuotationResponse.CarPolicySubInfoList carPolicySubInfoList = quotationResponse.getCarPolicySubInfoList().get(0);
@@ -190,18 +203,19 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 quoteResultsVo.getCosts().setNiPremium(carPolicySubInfoList.getActualPremium());
             }
         }
-        
+
         // 计算总保费
         // calculateSumPremium(quoteResultsVo);
     }
-    
+
     /**
      * 计算总保费
+     *
      * @param quoteResultsVo
      */
     private static void calculateSumPremium(QuoteResultsVo quoteResultsVo) {
         double sumPremium = 0.0;
-        
+
         if (quoteResultsVo.getCosts().getCiPremium() != null) {
             try {
                 sumPremium += Double.parseDouble(quoteResultsVo.getCosts().getCiPremium());
@@ -209,7 +223,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 log.warn("交强险保费解析失败: {}", quoteResultsVo.getCosts().getCiPremium());
             }
         }
-        
+
         if (quoteResultsVo.getCosts().getBiPremium() != null) {
             try {
                 sumPremium += Double.parseDouble(quoteResultsVo.getCosts().getBiPremium());
@@ -217,7 +231,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 log.warn("商业险保费解析失败: {}", quoteResultsVo.getCosts().getBiPremium());
             }
         }
-        
+
         if (quoteResultsVo.getCosts().getVvTax() != null) {
             try {
                 sumPremium += Double.parseDouble(quoteResultsVo.getCosts().getVvTax());
@@ -225,7 +239,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
                 log.warn("车船税解析失败: {}", quoteResultsVo.getCosts().getVvTax());
             }
         }
-        
+
         if (quoteResultsVo.getCosts().getNiPremium() != null) {
             try {
                 sumPremium += Double.parseDouble(quoteResultsVo.getCosts().getNiPremium());
@@ -237,4 +251,80 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
         quoteResultsVo.getCosts().setSumPremium(String.valueOf(sumPremium));
     }
 
+    // 构建评分
+    private static QuoteResultsVo.ScoreVo buildScoreVo(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+        QuoteResultsVo.ScoreVo scoreVo = new QuoteResultsVo.ScoreVo();
+        List<ZiJinCrawlerQuotationResponse.PriceInfoList> priceInfoList = ziJinCrawlerQuotationResponse.getPriceInfoList();// 定价信息列表
+        if (CollectionUtils.isEmpty(priceInfoList)) {
+            return scoreVo;
+        }
+        ZiJinCrawlerQuotationResponse.PriceInfoList priceInfo = priceInfoList.get(0);
+        JSONArray scoreArray = new JSONArray();
+
+        scoreVo.setJqLossRation(priceInfo.getLrRecomAdjust());
+        scoreVo.setSyLossRation(priceInfo.getLrRecom());
+
+        // 定价评分
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "交强险预测评分")
+                .fluentPut("scoreKey", "revPredScoreAdjust")
+                .fluentPut("score", priceInfo.getRevPredScoreAdjust()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "商业险预测评分")
+                .fluentPut("scoreKey", "revPredScore")
+                .fluentPut("score", priceInfo.getRevPredScore()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "车辆核保分")
+                .fluentPut("scoreKey", "underwrite01")
+                .fluentPut("score", priceInfo.getUnderwrite01()));
+        scoreArray.add(new JSONObject()
+                .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);
+
+        // 车慧达定价信息
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "三者+车损分档预测")
+                .fluentPut("scoreKey", "totalTranche")
+                .fluentPut("score", priceInfo.getTotalTranche()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "车损分档预测")
+                .fluentPut("scoreKey", "vehicleDamageTranche")
+                .fluentPut("score", priceInfo.getVehicleDamageTranche()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "交强+三者分档预测")
+                .fluentPut("scoreKey", "compulsoryThreeTranche")
+                .fluentPut("score", priceInfo.getCompulsoryThreeTranche()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "三者分档预测")
+                .fluentPut("scoreKey", "threeTranche")
+                .fluentPut("score", priceInfo.getThreeTranche()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "交强险分档预测")
+                .fluentPut("scoreKey", "compulsoryTranche")
+                .fluentPut("score", priceInfo.getCompulsoryTranche()));
+        scoreArray.add(new JSONObject()
+                .fluentPut("scoreName", "整车分档预测")
+                .fluentPut("scoreKey", "carLoadTranche")
+                .fluentPut("score", priceInfo.getCarLoadTranche()));
+        scoreVo.setScoreJson(scoreArray);
+        return scoreVo;
+    }
 }

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

@@ -0,0 +1,436 @@
+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.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.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.util.ObjectUtils;
+
+import java.util.*;
+
+/**
+ * @description: 紫金财险爬虫保存报价结果构建器
+ * @author:
+ * @date:
+ **/
+@Slf4j
+public class ZiJinCrawlerSaveQuoteInfoRequestBuild {
+
+    /**
+     * 构建保存报价信息的订单附加信息
+     *
+     * @param quoteVo
+     * @param ziJinCrawlerQuotationRequest
+     * @return
+     */
+    public static ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo buildSaveOrderAttachInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+        return ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo.builder()
+                .carAppliRelation("1")
+                .carInsuredRelation("1")
+                .carCheckStatus("2")
+                .carCheckReason("2")
+                .vehicleId("1")
+                .printModelName(ziJinCrawlerQuotationRequest.getVehicleInfo() != null ? ziJinCrawlerQuotationRequest.getVehicleInfo().getPrintModelName() : "")
+                .printUseNatureCode("")
+                .vehicleOwnerNature(ziJinCrawlerQuotationRequest.getCarOwnerInfo() != null ? ziJinCrawlerQuotationRequest.getCarOwnerInfo().getVehicleOwnerNature() : "1")
+                .ownerAddress(quoteVo.getOwnersInfo().getAddr())
+                .sale4SFlag("0")
+                .policySupplementaryInfoList(new ArrayList<>())
+                .build();
+    }
+
+    /**
+     * 构建保存报价信息的车辆信息
+     *
+     * @param ziJinCrawlerQuotationRequest  报价参数
+     * @param ziJinCrawlerQuotationResponse 报价结果
+     * @return 保存报价信息的车辆信息
+     */
+    public static ZiJinCrawlerSaveQuoteInfoRequest.VehicleInfo buildVehicleInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+        ZiJinCrawlerQuotationRequest.VehicleInfo carInfo = ziJinCrawlerQuotationRequest.getVehicleInfo();
+        // 计算使用年限
+        int useYears = 0;
+        if (carInfo.getEnrollDate() != null) {
+            try {
+                java.time.LocalDate registerDate = java.time.LocalDate.parse(carInfo.getEnrollDate());
+                useYears = java.time.Period.between(registerDate, java.time.LocalDate.now()).getYears();
+            } catch (Exception e) {
+                log.warn("车辆注册日期格式错误,无法计算使用年限,原始值:{}", carInfo.getEnrollDate());
+            }
+        }
+        // 车辆种类和使用性质
+        List<String> vehicleKindAndUseNature = new ArrayList<>();
+        vehicleKindAndUseNature.add(carInfo.getCarKindCode());
+        vehicleKindAndUseNature.add(carInfo.getUseNatureCode());
+
+        return ZiJinCrawlerSaveQuoteInfoRequest.VehicleInfo.builder()
+                .useYears(useYears)
+                .actualValue(carInfo.getActualValue())
+                .agreeActualValue(carInfo.getAgreeActualValue())
+                .brandName(carInfo.getBrandName() != null ? carInfo.getBrandName() : "")
+                .carKindCode(carInfo.getCarKindCode())
+                .carKindDetailId(carInfo.getCarKindDetailId())
+                .carLoanFlag(carInfo.getCarLoanFlag())
+                .certificateDate(carInfo.getCertificateDate() != null ? carInfo.getCertificateDate() : "")
+                .chgOwnerFlag(carInfo.getChgOwnerFlag())
+                // .completekerbmass(carInfo.getCompletekerbmass() != null ? Integer.parseInt(carInfo.getCompletekerbmass()) : 0)
+                .completekerbmass(carInfo.getCompletekerbmass())
+                .ecdemicVehicleFlag(carInfo.getEcdemicVehicleFlag() != null ? carInfo.getEcdemicVehicleFlag() : "0")
+                .engineNo(carInfo.getEngineNo() != null ? carInfo.getEngineNo() : "")
+                .enrollDate(carInfo.getEnrollDate() != null ? carInfo.getEnrollDate() : "")
+                .updateEnrollDate(carInfo.getUpdateEnrollDate() != null ? carInfo.getUpdateEnrollDate() : "")
+                .exhaustCapacity(carInfo.getExhaustCapacity() != null ? carInfo.getExhaustCapacity() : 0)
+                .fuelType(carInfo.getFuelType())
+                .fuelTypeJY(carInfo.getFuelTypeJY())
+                .newEnergyFlag(carInfo.getNewEnergyFlag())
+                .licenseColorCode(carInfo.getLicenseColorCode())
+                .licenseKindCode(carInfo.getLicenseKindCode())
+                .licenseNo(carInfo.getLicenseNo() != null ? carInfo.getLicenseNo() : "")
+                .loanVehicleFlag(carInfo.getLoanVehicleFlag() != null ? carInfo.getLoanVehicleFlag() : "0")
+                .modelCode(carInfo.getModelCode() != null ? carInfo.getModelCode() : "")
+                .noLicenseFlag(carInfo.getNoLicenseFlag())
+                .issueDate(carInfo.getIssueDate() != null ? carInfo.getIssueDate() : "")
+                .oriCarKindName(carInfo.getOriCarKindName())
+                .platVehicleCode(carInfo.getPlatVehicleCode() != null ? carInfo.getPlatVehicleCode() : "")
+                .power(carInfo.getPower() != null ? carInfo.getPower() : "0")
+                .printUseNatureCode("")
+                .purchasePrice(carInfo.getPurchasePrice() != null ? carInfo.getPurchasePrice() : "0")
+                // .seatCount(carInfo.getSeatCount() != null ? Integer.parseInt(carInfo.getSeatCount()) : 5)
+                .seatCount(carInfo.getSeatCount())
+                .useNatureCode(carInfo.getUseNatureCode())
+                .vehicleId(carInfo.getVehicleId())
+                .makeDate(carInfo.getMakeDate() != null ? carInfo.getMakeDate() : "")
+                .makeDateJQ(carInfo.getMakeDateJQ() != null ? carInfo.getMakeDateJQ() : "")
+                .aliasName(carInfo.getAliasName() != null ? carInfo.getAliasName() : "")
+                .carCheckStatus("2")
+                .carCheckReason("2")
+                .vehicleKindAndUseNature(vehicleKindAndUseNature)
+                .oriBrandName(carInfo.getOriBrandName() != null ? carInfo.getOriBrandName() : "")
+                .oriPurchasePrice(carInfo.getOriPurchasePrice() != null ? carInfo.getOriPurchasePrice() : "0")
+                .isInvokeJingYou(carInfo.getIsInvokeJingYou())
+                .vehicleStyleUniqueId(carInfo.getVehicleStyleUniqueId() != null ? carInfo.getVehicleStyleUniqueId() : "")
+                .printModelName(carInfo.getPrintModelName() != null ? carInfo.getPrintModelName() : "")
+                .oriModelName(carInfo.getOriModelName() != null ? carInfo.getOriModelName() : "")
+                .vINNo(carInfo.getVinNo() != null ? carInfo.getVinNo() : "")
+                .modelEnergyType(carInfo.getModelEnergyType())
+                .build();
+    }
+
+    /**
+     * 构建报价保存的车船税减免信息
+     *
+     * @param ziJinCrawlerQuotationResponse
+     * @return
+     */
+    public static ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo buildSaveTaxRelifInfo(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
+        if (ziJinCrawlerQuotationResponse.getCarShipTax() == null) {
+            return null;
+        }
+        ZiJinCrawlerQuotationResponse.CarShipTax carShipTax = ziJinCrawlerQuotationResponse.getCarShipTax();
+        return ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo.builder()
+                .taxRelifFlag(carShipTax.getTaxRelifFlag())
+                .sumPayTax(carShipTax.getSumPayTax() == null ? "0.0" : String.valueOf(carShipTax.getSumPayTax()))
+                .taxpayerName(carShipTax.getTaxpayerName())
+                .taxpayerIdentifier(carShipTax.getTaxpayerIdentifier())
+                .identifyNumber(carShipTax.getIdentifyNumber())
+                .payLastYear(carShipTax.getPayLastYear())
+                .lastCIPaymentTime(carShipTax.getLastCIPaymentTime())
+                .taxActual(carShipTax.getTaxActual() == null ? "0.0" : String.valueOf(carShipTax.getTaxActual()))
+                .previousPay(carShipTax.getPreviousPay() == null ? "0.0" : String.valueOf(carShipTax.getPreviousPay()))
+                .lateFee(carShipTax.getLateFee() == null ? "0.0" : String.valueOf(carShipTax.getLateFee()))
+                .taxRegistryNumber(carShipTax.getTaxRegistryNumber())
+                .isPlatformTax(true)
+                .extendChar1(carShipTax.getExtendChar1())
+                .taxUnit(carShipTax.getTaxUnit())
+                .completeKerbMass(carShipTax.getCompleteKerbMass())
+                .payerCode(carShipTax.getPayerCode())
+                .payStartDate(carShipTax.getPayStartDate())
+                .payEndDate(carShipTax.getPayEndDate())
+                .taxRelifFlagCN(carShipTax.getTaxRelifFlagCN())
+                .exceedDaysCount(carShipTax.getExceedDaysCount())
+                .currentTaxDue(ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo.CurrentTaxDue.builder()
+                        .taxLocationCode(carShipTax.getCurrentTaxDue().getTaxLocationCode())
+                        .taxEndDate(carShipTax.getCurrentTaxDue().getTaxEndDate())
+                        .taxStartDate(carShipTax.getCurrentTaxDue().getTaxStartDate())
+                        .taxUnitTypeCode(carShipTax.getCurrentTaxDue().getTaxUnitTypeCode())
+                        .taxDue(carShipTax.getCurrentTaxDue().getTaxDue() == null ? 0 : ConvertUtil.convertToInteger(carShipTax.getCurrentTaxDue().getTaxDue()))
+                        .unitRate(carShipTax.getCurrentTaxDue().getUnitRate() == null ? 0 : ConvertUtil.convertToInteger(carShipTax.getCurrentTaxDue().getUnitRate()))
+                        .annualTaxAmount(carShipTax.getCurrentTaxDue().getAnnualTaxAmount() == null ? 0 : ConvertUtil.convertToInteger(carShipTax.getCurrentTaxDue().getAnnualTaxAmount()))
+                        .exceedDaysCount(carShipTax.getCurrentTaxDue().getExceedDaysCount())
+                        .overDue(carShipTax.getCurrentTaxDue().getOverDue() == null ? 0 : ConvertUtil.convertToInteger(carShipTax.getCurrentTaxDue().getOverDue()))
+                        .taxConditionCode(carShipTax.getCurrentTaxDue().getTaxConditionCode())
+                        .totalAmount(carShipTax.getCurrentTaxDue().getTotalAmount() == null ? 0 : ConvertUtil.convertToInteger(carShipTax.getCurrentTaxDue().getTotalAmount()))
+                        .build())
+                .delinquentTaxDueList(Optional.ofNullable(ziJinCrawlerQuotationResponse.getCarShipTax().getDelinquentTaxDueList())
+                        .orElseGet(Collections::emptyList).stream().map(currentTaxDue -> ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo.CurrentTaxDue.builder()
+                                .taxDue(currentTaxDue.getTaxDue() == null ? 0 : ConvertUtil.convertToInteger(currentTaxDue.getTaxDue()))
+                                .overDue(currentTaxDue.getOverDue() == null ? 0 : ConvertUtil.convertToInteger(currentTaxDue.getOverDue()))
+                                .totalAmount(currentTaxDue.getTotalAmount() == null ? 0 : ConvertUtil.convertToInteger(currentTaxDue.getTotalAmount()))
+                                .exceedDaysCount(currentTaxDue.getExceedDaysCount() == null ? 0 : ConvertUtil.convertToInteger(currentTaxDue.getExceedDaysCount()))
+                                .unitRate(currentTaxDue.getUnitRate() == null ? 0 : ConvertUtil.convertToInteger(currentTaxDue.getUnitRate()))
+                                .annualTaxAmount(currentTaxDue.getAnnualTaxAmount() == null ? 0 : ConvertUtil.convertToInteger(currentTaxDue.getAnnualTaxAmount()))
+                                .taxStartDate(currentTaxDue.getTaxStartDate())
+                                .taxEndDate(currentTaxDue.getTaxEndDate())
+                                .taxLocationCode(currentTaxDue.getTaxLocationCode())
+                                .taxUnitTypeCode(currentTaxDue.getTaxUnitTypeCode())
+                                .taxConditionCode(currentTaxDue.getTaxConditionCode())
+                                .build()
+                        ).toList())
+                .build();
+    }
+
+    /**
+     * 构建保存报价的险别明细列表信息
+     *
+     * @param ziJinCrawlerQuotationResponse
+     * @return
+     */
+    @NotNull
+    public static 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()) {
+                String amount = kind.getAmount() != null ? kind.getAmount().toString() : "0.0";
+                String premium = kind.getBenchMarkPremium() != null ? kind.getBenchMarkPremium() : "0.0000";
+                ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo itemKind = ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo.builder()
+                        .amount(amount)
+                        .kindCode(kind.getKindCode())
+                        .kindName(kind.getKindName())
+                        .riskCode(kind.getRiskCode())
+                        .premium(premium)
+                        .benchMarkPremium(premium)
+                        .basePremium(kind.getBasePremium() != null ? kind.getBasePremium() : premium)
+                        .serviceTimes(kind.getServiceTimes())
+                        .build();
+                itemKindList.add(itemKind);
+            }
+        }
+        return itemKindList;
+    }
+
+    /**
+     * 构建保存报价的 投保人/被投保人 信息
+     *
+     * @param quoteVo
+     * @param ziJinCrawlerQuotationRequest
+     * @return
+     */
+    @NotNull
+    public static List<ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo> buildSaveInsuredList(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+        // 投保人
+        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
+        String addr = policyHolderInfo.getAddr();
+        String identifyValidDate = policyHolderInfo.getIdentifyValidDate();
+        String identifyValidEndDate = policyHolderInfo.getIdentifyValidEndDate();
+        // 被保人
+        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();
+        String addr1 = insuredPersonInfo.getAddr();
+        String identifyValidDate1 = insuredPersonInfo.getIdentifyValidDate();
+        String identifyValidEndDate1 = insuredPersonInfo.getIdentifyValidEndDate();
+
+        // 投保人信息 (insuredFlag=2), 被保人信息 (insuredFlag=1)
+        List<ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo> insuredList = new ArrayList<>();
+        // 获取被保人信息
+        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(ziJinCrawlerQuotationRequest.getInsuredList())) {
+            for (ZiJinCrawlerQuotationRequest.InsuredList insured : ziJinCrawlerQuotationRequest.getInsuredList()) {
+                ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo insuredInfo = ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo.builder()
+                        .address(insured.getInsuredFlag() == 2 ? addr : addr1)
+                        .identifyNumber(insured.getIdentifyNumber())
+                        .identifyType(ObjectUtils.isEmpty(insured.getIdentifyType()) ? "01" : insured.getIdentifyType())
+                        .insuredFlag(insured.getInsuredFlag())
+                        .insuredName(insured.getInsuredName())
+                        .insuredNature("3")
+                        .insuredType(insured.getInsuredType() != null ? insured.getInsuredType() : "1")
+                        .longAddress(insured.getInsuredFlag() == 2 ? addr : addr1)
+                        .mobile(insured.getMobile())
+                        .sex("2") // 默认值,从request中无法获取性别
+                        .nationality("中国")
+                        .occupation("A1301002")
+                        .addressProvince("")
+                        .addressPrefecture("")
+                        .addressCounty("")
+                        .postCode(insured.getPostCode() != null ? insured.getPostCode() : "030053")
+                        .insuredRelationship("1")
+                        .validDate(insured.getInsuredFlag() == 2 ? identifyValidEndDate : identifyValidEndDate1)
+                        .countryRegions("CHN")
+                        .vehicleRelationCode("1")
+                        .certigier(new HashMap<>())
+                        .chief(new HashMap<>())
+                        .riskLevelName("一般")
+                        .riskLevel("4")
+                        .reserved2("1")
+                        .reserved(new ArrayList<>())
+                        .businessManager(ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo.BusinessManager.builder()
+                                .insuredFlag("1")
+                                .build())
+                        .phoneHolder(ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo.PhoneHolder.builder()
+                                .insuredFlag("2")
+                                .build())
+                        .isPhoneOwner("1")
+                        .issuer("")
+                        .iDStartDate(insured.getInsuredFlag() == 2 ? identifyValidDate : identifyValidDate1)
+                        .build();
+                insuredList.add(insuredInfo);
+            }
+        }
+        return insuredList;
+    }
+
+    /**
+     * 构建保存报价的 车险附加险信息列表
+     *
+     * @param ziJinCrawlerQuotationRequest
+     * @return
+     */
+    @NotNull
+    public static 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()) {
+                ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo carPolicySubInfo = ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo.builder()
+                        .planName(subInfo.getPlanName())
+                        .insureGradeNo(subInfo.getInsureGradeNo())
+                        .isUseInsured(subInfo.getIsUseInsured())
+                        .quantity(subInfo.getQuantity())
+                        .riskCode(subInfo.getRiskCode())
+                        .riskName(subInfo.getRiskName())
+                        .sumAmount(subInfo.getSumAmount() != null ? subInfo.getSumAmount().longValue() : 577000L)
+                        .sumPremium(subInfo.getSumPremium())
+                        .actualPremium(subInfo.getActualPremium())
+                        .productCode(subInfo.getProductCode())
+                        .build();
+                carPolicySubInfoList.add(carPolicySubInfo);
+            }
+        }
+        return carPolicySubInfoList;
+    }
+
+    /**
+     * 构建保存报价 车主信息 请求
+     *
+     * @param quoteVo
+     * @param ziJinCrawlerQuotationRequest
+     * @return
+     */
+    public static ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo buildSaveCarOwnerInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
+        return ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo.builder()
+                .customerAmlPropReqDtoList(new ArrayList<>())
+                .carOwner(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getCarOwner())
+                .ownerIdentifyNumber(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getOwnerIdentifyNumber())
+                .ownerIdentifyType(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getOwnerIdentifyType())
+                .vehicleOwnerNature(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getVehicleOwnerNature())
+                .ownerAddress(quoteVo.getOwnersInfo().getAddr())
+                .build();
+    }
+
+    /**
+     * 构建保存报价 基础信息 请求
+     *
+     * @param quoteVo                       系统前端参数
+     * @param ziJinCrawlerQuotationRequest  报价参数
+     * @param ziJinCrawlerQuotationResponse 报价返回对象
+     */
+    public static 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()
+                .teamType("10")
+                .agentCode(ziJinCrawlerQuotationRequest.getBaseInfo().getAgentCode())
+                .agreementNo(ziJinCrawlerQuotationRequest.getBaseInfo().getAgreementNo())
+                .businessNature(ziJinCrawlerQuotationRequest.getBaseInfo().getBusinessNature())
+                .comCode(ziJinCrawlerQuotationRequest.getBaseInfo().getComCode())
+                .comName(ziJinCrawlerQuotationRequest.getBaseInfo().getComName())
+                .areaCode("140000")
+                .handler1Code(ziJinCrawlerQuotationRequest.getBaseInfo().getHandler1Code())
+                .handler1Name(ziJinCrawlerQuotationRequest.getBaseInfo().getHandler1Name())
+                .operatorCode(ziJinCrawlerQuotationRequest.getBaseInfo().getOperatorCode())
+                .startDate(ziJinCrawlerQuotationRequest.getBaseInfo().getStartDate())
+                .startDateCI(ziJinCrawlerQuotationRequest.getBaseInfo().getStartDateCI())
+                .startHour(ziJinCrawlerQuotationRequest.getBaseInfo().getStartHour())
+                .startHourCI(ziJinCrawlerQuotationRequest.getBaseInfo().getStartHourCI())
+                .startMinute(ziJinCrawlerQuotationRequest.getBaseInfo().getStartMinute())
+                .startMinuteCI(ziJinCrawlerQuotationRequest.getBaseInfo().getStartMinuteCI())
+                .endDate(ziJinCrawlerQuotationRequest.getBaseInfo().getEndDate())
+                .endDateCI(ziJinCrawlerQuotationRequest.getBaseInfo().getEndDateCI())
+                .endHour(ziJinCrawlerQuotationRequest.getBaseInfo().getEndHour())
+                .endHourCI(ziJinCrawlerQuotationRequest.getBaseInfo().getEndHourCI())
+                .endMinute(ziJinCrawlerQuotationRequest.getBaseInfo().getEndMinute())
+                .endMinuteCI(ziJinCrawlerQuotationRequest.getBaseInfo().getEndMinuteCI())
+                .proposalCheckNo(ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo())
+                .goalInsuredFlag(ziJinCrawlerQuotationRequest.getBaseInfo().getGoalInsuredFlag())
+                .configName(ziJinCrawlerQuotationRequest.getBaseInfo().getConfigName())
+                .id(ziJinCrawlerQuotationRequest.getBaseInfo().getId())
+                .businessName(ziJinCrawlerQuotationRequest.getBaseInfo().getBusinessName())
+                .underscoreId(ziJinCrawlerQuotationRequest.getBaseInfo().getId())
+                .desc(ziJinCrawlerQuotationRequest.getBaseInfo().getDesc())
+                .handerCode(ziJinCrawlerQuotationRequest.getBaseInfo().getHanderCode())
+                .handerName(ziJinCrawlerQuotationRequest.getBaseInfo().getHanderName())
+                .calculateFlag(ziJinCrawlerQuotationRequest.getBaseInfo().getCalculateFlag())
+                .isCI(quoteVo.getCiRiskInfoVo() != null)
+                .isBI(quoteVo.getBiRiskInfoVo() != null)
+                .riskCodeEnum(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.builder()
+                        .CSTax(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.CSTaxInfo.builder()
+                                .riskCode(RiskCodeEnum.ACCIDENT_CODE)
+                                .riskName("车船税")
+                                .build())
+                        .CI(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.CIInfo.builder()
+                                .riskCode(RiskCodeEnum.TRAFFIC_CODE)
+                                .riskName("机动车交通事故责任强制保险")
+                                .amount("200000")
+                                .build())
+                        .BI(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.BIInfo.builder()
+                                .riskCode(RiskCodeEnum.BUSINESS_CODE)
+                                .oldRiskCode("0501")
+                                .riskName("机动车商业保险(2020版)")
+                                .oldRiskName("新机动车商业险")
+                                .build())
+                        .productCode("CAR20190517")
+                        .productName("机动车保险")
+                        .useNatureList(Arrays.asList("82", "83", "84", "85", "9A", "9B", "9C", "9D"))
+                        .vehicleKindAndUseNature(Arrays.asList(ziJinCrawlerQuotationRequest.getVehicleInfo().getUseNatureCode(), ziJinCrawlerQuotationRequest.getVehicleInfo().getCarKindCode()))
+                        .icon("iconfont iconjidongche1")
+                        .name("car")
+                        .build())
+                .useRateFlag(true)
+                .argueSolution("1")
+                .autoTransRenewFlag("4")
+                .xbFlag("0")
+                .xbFlagCI("0")
+                .applicationType("T")
+                .split("1")
+                .sumPremiumCI(sumPremiumCI)
+                .sumPremium(sumPremium)
+                .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;
+    }
+
+}

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

@@ -258,11 +258,13 @@ public class ZiJinCrawlerRequestComponent {
      * 验证码(报价出现转保标志)
      *
      * @param ziJinCrawlerRecognizeCodesRequest
+     * @param headers 请求头
      * @return ZiJinCrawlerRecognizeCodesResponse
      */
-    public ZiJinCrawlerRecognizeCodesResponse recognizeCodes(List<ZiJinCrawlerRecognizeCodesRequest> ziJinCrawlerRecognizeCodesRequest) throws IOException {
+    public ZiJinCrawlerRecognizeCodesResponse recognizeCodes(List<ZiJinCrawlerRecognizeCodesRequest> ziJinCrawlerRecognizeCodesRequest, HttpHeaders headers) throws IOException {
         //设置headers
         HttpHeaders httpHeaders = setHttpHeaders();
+        httpHeaders.set("Content-Type", "application/json");
         String jsonString = JSON.toJSONString(ziJinCrawlerRecognizeCodesRequest);
         log.info("ziJinCrawlerRecognizeCodesRequest请求参数的值:{}", jsonString);
         ResponseEntity<ZiJinCrawlerRecognizeCodesResponse> post = requestComponent.post(RequestUrl.SKIP_SING.getRequestUrl(ziJinCrawlerProperties.getBaseUrl()), jsonString, ZiJinCrawlerRecognizeCodesResponse.class, httpHeaders);
@@ -468,7 +470,7 @@ public class ZiJinCrawlerRequestComponent {
      * @return String
      * @throws IOException
      */
-    private static String getCookie() throws IOException {
+    public static String getCookie() throws IOException {
         RS6Item rs6Item = RS6Item.createRS6Instance();
         rs6Item.updata_js_rs6();
         Map<String, String> cookies = rs6Item.updateCookies();
@@ -487,7 +489,7 @@ public class ZiJinCrawlerRequestComponent {
         //headers.setContentType(MediaType.APPLICATION_JSON);
         //获取cookie的值
         String cookie = getCookie();
-        headers.set("Cookie", cookie);
+        headers.set("Cookie", "csrfToken=CrwLEmSfUevAb8PcN7kXff-I; "+ cookie);
         // 设置请求头
         headers.set("Accept", "application/json, text/plain, */*, application/problem+json");
         //headers.set("Accept-Encoding", "gzip, deflate, br, zstd");

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

@@ -351,6 +351,22 @@ public class ZiJinCrawlerQuotationRequest implements Serializable {
          */
         @JsonProperty("renewalFlag")
         private String renewalFlag;
+
+        /**
+         *
+         */
+        @JsonProperty("renewalFlagCI")
+        private String renewalFlagCI;
+
+        /**
+         * “转保标志” 验证码question的值
+         */
+        private String answer;
+
+        /**
+         * ”转保标志“ 验证码questionCI的值
+         */
+        private String answerCI;
     }
 
     /**

+ 2 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/response/ZiJinCrawlerRecognizeCodesResponse.java

@@ -6,6 +6,7 @@ import lombok.NoArgsConstructor;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * @description:
@@ -26,7 +27,7 @@ public class ZiJinCrawlerRecognizeCodesResponse implements Serializable {
     private String rtnMsg;
 
     @JsonProperty("results")
-    private Results results;
+    private List<Results> results;
 
     @NoArgsConstructor
     @Data

+ 19 - 15
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerQuoteProcessServiceImpl.java

@@ -13,6 +13,7 @@ import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerCommonLoginReq
 import com.jzg.quotation.zijin.crawler.entity.response.*;
 import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerQuoteProcessService;
 import com.jzg.quotation.zijin.crawler.util.DESEncryption;
+import com.jzg.quotation.zijin.crawler.util.RS6Item;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpHeaders;
@@ -20,6 +21,7 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
 import java.io.IOException;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -49,10 +51,10 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
     @Override
     public String login(String username, String password) {
         try {
-            //1、获取验证码
+            // 1、获取验证码
             ZiJinCrawlerCaptchaResponse ziJinCrawlerCaptchaResponse = ziJinCrawlerRequestComponent.captcha(3);
 
-            //2、公共登录
+            // 2、公共登录
             ZiJinCrawlerCommonLoginRequest ziJinCrawlerCommonLoginRequest = new ZiJinCrawlerCommonLoginRequest();
             ziJinCrawlerCommonLoginRequest.setUserCode(username);
             ziJinCrawlerCommonLoginRequest.setPassword(password);
@@ -64,7 +66,7 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
             }
             log.info("公共登录响应:{}", JSON.toJSONString(ziJinCrawlerCommonLoginResponse));
 
-            //3、校验验证码并获取token
+            // 3、校验验证码并获取token
             ZiJinCrawlerCheckCaptchaRequest ziJinCrawlerCheckCaptchaRequest = new ZiJinCrawlerCheckCaptchaRequest();
             ZiJinCrawlerTokenInfo ziJinCrawlerTokenInfo = new ZiJinCrawlerTokenInfo();
             ziJinCrawlerTokenInfo.setLoginComCode(ziJinCrawlerCommonLoginResponse.getData().getData().get(0).getComCode());
@@ -84,11 +86,11 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
 
             ZiJinCrawlerCheckCaptchaResponse ziJinCrawlerCheckCaptchaResponse = ziJinCrawlerRequestComponent.checkCaptchaAndGetToken(ziJinCrawlerCheckCaptchaRequest, commonToken);
             log.info("校验验证码并且获取token响应:{}", JSON.toJSONString(ziJinCrawlerCheckCaptchaResponse));
-            //成功
+            // 成功
             if ("0000".equals(ziJinCrawlerCheckCaptchaResponse.getRtnCode())) {
-                //获取token
+                // 获取token
                 String token = ziJinCrawlerCheckCaptchaResponse.getData().getToken();
-                //4、校验token
+                // 4、校验token
                 ZiJinCrawlerCheckTokenRequest ziJinCrawlerCheckTokenRequest = new ZiJinCrawlerCheckTokenRequest();
                 ziJinCrawlerCheckTokenRequest.setExpirationType("H5");
                 ziJinCrawlerCheckTokenRequest.setToken(token);
@@ -100,7 +102,7 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
                     String tokenInfo = ziJinCrawlerCheckTokenResponse.getTokenInfo();
                     ZiJinCrawlerTokenInfo ziJinCrawlerTokenInfo1 = JSON.parseObject(tokenInfo, ZiJinCrawlerTokenInfo.class);
                     String userCode = ziJinCrawlerTokenInfo1.getUserCode();
-                    //缓存用户信息
+                    // 缓存用户信息
                     return ziJinCrawlerCacheComponent.cacheAuthorization(token, userCode, userName);
                 } else {
                     log.error("校验token失败,响应:{}", JSON.toJSONString(ziJinCrawlerCheckTokenResponse));
@@ -136,15 +138,17 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
         headers.set("Authorization", authorization);
         headers.set("Content-Type", "application/json");
         headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
-
-
-
-        //获取cookie的值
-//        String cookie = getCookie();
-//        headers.set("Cookie", cookie);
+        // 获取cookie的值
+        String cookie = null;
+        try {
+            cookie = ZiJinCrawlerRequestComponent.getCookie();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        headers.set("Cookie", "csrfToken=CrwLEmSfUevAb8PcN7kXff-I; " + cookie);
         // 设置请求头
         headers.set("Accept", "application/json, text/plain, */*, application/problem+json");
-        //headers.set("Accept-Encoding", "gzip, deflate, br, zstd");
+        // headers.set("Accept-Encoding", "gzip, deflate, br, zstd");
         headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
         headers.set("Authorization", "1B0234C742C12BD632AA5027EB3A501A");
         headers.set("Cache-Control", "no-cache");
@@ -158,7 +162,7 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
         headers.set("Sec-Fetch-Mode", "cors");
         headers.set("Sec-Fetch-Site", "same-origin");
         headers.set("Tokentype", "DEFULT");
-        //headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36");
+        // headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36");
         headers.set("loginToken", "1B0234C742C12BD632AA5027EB3A501A");
         headers.set("sec-ch-ua", "\"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"");
         headers.set("sec-ch-ua-mobile", "?0");

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

@@ -20,6 +20,7 @@ import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversi
 import com.jzg.quotation.zijin.api.constant.enums.MotorVehicleInsuranceEnum;
 import com.jzg.quotation.zijin.api.constant.enums.RiskCodeEnum;
 import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerQuoteResultsVoBuild;
+import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerSaveQuoteInfoRequestBuild;
 import com.jzg.quotation.zijin.crawler.component.ZiJinBuildingAttributionInformation;
 import com.jzg.quotation.zijin.crawler.component.ZiJinCrawlerCacheComponent;
 import com.jzg.quotation.zijin.crawler.component.ZiJinCrawlerRequestComponent;
@@ -32,6 +33,7 @@ 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;
@@ -204,10 +206,20 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             // 转保标志
             if (ResponseCode.R_0001.getCode().equals(ziJinCrawlerQuotationResponse.getRtnCode())) {
                 if (ziJinCrawlerQuotationResponse.getBasePart() != null) {
-                    ZiJinCrawlerRecognizeCodesResponse ziJinCrawlerRecognizeCodesResponse = ziJinCrawlerRequestComponent.recognizeCodes(buildRecognizeCodesRequests(ziJinCrawlerQuotationResponse));
+                    ZiJinCrawlerRecognizeCodesResponse ziJinCrawlerRecognizeCodesResponse = ziJinCrawlerRequestComponent.recognizeCodes(ZiJinCrawlerSaveQuoteInfoRequestBuild.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");
+                        }
                         ziJinCrawlerQuotationResponse = ziJinCrawlerRequestComponent.quotation(ziJinCrawlerQuotationRequest, headers);
                     }
                 }
@@ -241,15 +253,6 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         }
     }
 
-    private ArrayList<ZiJinCrawlerRecognizeCodesRequest> buildRecognizeCodesRequests(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        ArrayList<ZiJinCrawlerRecognizeCodesRequest> ziJinCrawlerRecognizeCodesRequests = new ArrayList<>();
-        ZiJinCrawlerRecognizeCodesRequest ziJinCrawlerRecognizeCodesRequest = new ZiJinCrawlerRecognizeCodesRequest();
-        ziJinCrawlerRecognizeCodesRequest.setBase64(ziJinCrawlerQuotationResponse.getBasePart().getQuestion());
-        ziJinCrawlerRecognizeCodesRequest.setSerialNo("question");
-        ziJinCrawlerRecognizeCodesRequests.add(ziJinCrawlerRecognizeCodesRequest);
-        return ziJinCrawlerRecognizeCodesRequests;
-    }
-
     /**
      * 核保
      *
@@ -788,8 +791,8 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         baseInfo.setEndMinute("00");
         baseInfo.setEndMinuteCI("00");
         // 经测试:燃油单强设为0,交三不设置(待确认),会返回转保标志,紫金系统可以忽略进行下一步报价
-        // baseInfo.setXbFlag("0");
-        // baseInfo.setXbFlagCI("0");
+        baseInfo.setXbFlag(quoteVo.getBiRiskInfoVo() == null ? "0" : null);
+        baseInfo.setXbFlagCI(quoteVo.getBiRiskInfoVo() == null ? "0" : null);
         baseInfo.setGoalInsuredFlag("0");
         baseInfo.setConfigName("天勤");
         baseInfo.setId("1dec8ac2ced74973842a5b098669813a");
@@ -799,11 +802,11 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         baseInfo.setHanderCode("214003263");
         baseInfo.setHanderName("程涛");
         baseInfo.setDemandNo("01ZKIC140026051910017933666448");
-        // baseInfo.setDemandNoCI("01ZKIC140026051910017933666448");
+        baseInfo.setDemandNoCI("01ZKIC140026051910017933666448");// 这个先放开看行不
         // 经测试:燃油: 单交设为2,交三设为0
         baseInfo.setCalculateFlag(quoteVo.getBiRiskInfoVo() == null ? "2" : "0");
         // 经测试:燃油:单交设为"",交三设为1
-        baseInfo.setRenewalFlag(quoteVo.getBiRiskInfoVo() == null ? "1" : "");
+        baseInfo.setRenewalFlag(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
         return baseInfo;
     }
 
@@ -1746,22 +1749,22 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         ziJinCrawlerSaveQuoteInfoRequest.setOrderNo(ziJinCrawlerQuotationResponse.getOrderNo());
 
         // 设置基础信息
-        ziJinCrawlerSaveQuoteInfoRequest.setBaseInfo(buildSaveBaseInfo(quoteVo, ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
+        ziJinCrawlerSaveQuoteInfoRequest.setBaseInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveBaseInfo(quoteVo, ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
 
         // 设置车主信息
-        ziJinCrawlerSaveQuoteInfoRequest.setCarOwnerInfo(buildSaveCarOwnerInfo(quoteVo, ziJinCrawlerQuotationRequest));
+        ziJinCrawlerSaveQuoteInfoRequest.setCarOwnerInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveCarOwnerInfo(quoteVo, ziJinCrawlerQuotationRequest));
 
         // 设置车险附加险信息列表
-        ziJinCrawlerSaveQuoteInfoRequest.setCarPolicySubInfoList(buildSaveCarPolicySubInfo(ziJinCrawlerQuotationRequest));
+        ziJinCrawlerSaveQuoteInfoRequest.setCarPolicySubInfoList(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveCarPolicySubInfo(ziJinCrawlerQuotationRequest));
 
         // 设置附加险列表
         ziJinCrawlerSaveQuoteInfoRequest.setAttachRiskList(new ArrayList<>());
 
         // 设置 投保人/被保人 列表
-        ziJinCrawlerSaveQuoteInfoRequest.setInsuredList(buildSaveInsuredList(quoteVo, ziJinCrawlerQuotationRequest));
+        ziJinCrawlerSaveQuoteInfoRequest.setInsuredList(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveInsuredList(quoteVo, ziJinCrawlerQuotationRequest));
 
         // 设置险别明细列表
-        ziJinCrawlerSaveQuoteInfoRequest.setItemKindList(buildSaveItemKindList(ziJinCrawlerQuotationResponse));
+        ziJinCrawlerSaveQuoteInfoRequest.setItemKindList(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveItemKindList(ziJinCrawlerQuotationResponse));
 
         // 设置收费信息列表
         ziJinCrawlerSaveQuoteInfoRequest.setChargingInfoList(new ArrayList<>());
@@ -1779,7 +1782,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         ziJinCrawlerSaveQuoteInfoRequest.setSubmitInfo(new HashMap<>());
 
         // 设置车船税减免信息
-        ziJinCrawlerSaveQuoteInfoRequest.setTaxRelifInfo(buildSaveTaxRelifInfo(ziJinCrawlerQuotationResponse));
+        ziJinCrawlerSaveQuoteInfoRequest.setTaxRelifInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveTaxRelifInfo(ziJinCrawlerQuotationResponse));
 
         // 设置终端ID
         ziJinCrawlerSaveQuoteInfoRequest.setTerminalId("KSCD");
@@ -1791,7 +1794,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         ziJinCrawlerSaveQuoteInfoRequest.setInsuranceSign("0");
 
         // 设置车辆信息
-        ziJinCrawlerSaveQuoteInfoRequest.setVehicleInfo(buildVehicleInfo(ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
+        ziJinCrawlerSaveQuoteInfoRequest.setVehicleInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildVehicleInfo(ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse));
 
         // 设置车辆设备保费列表
         ziJinCrawlerSaveQuoteInfoRequest.setCarDevicePremiumDtoList(new ArrayList<>());
@@ -1803,7 +1806,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         ziJinCrawlerSaveQuoteInfoRequest.setItemFileDataList(buildSaveFileDataList(ziJinCrawlerQuotationResponse));
 
         // 设置订单附加信息
-        ziJinCrawlerSaveQuoteInfoRequest.setOrderAttachInfo(buildSaveOrderAttachInfo(quoteVo, ziJinCrawlerQuotationRequest));
+        ziJinCrawlerSaveQuoteInfoRequest.setOrderAttachInfo(ZiJinCrawlerSaveQuoteInfoRequestBuild.buildSaveOrderAttachInfo(quoteVo, ziJinCrawlerQuotationRequest));
 
         // 设置是否包含子机构
         ziJinCrawlerSaveQuoteInfoRequest.setIsIncludeSubCom(1);
@@ -1821,394 +1824,4 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                         .build()
         ).toList();
     }
-
-    private ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo buildSaveOrderAttachInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
-        return ZiJinCrawlerSaveQuoteInfoRequest.OrderAttachInfo.builder()
-                .carAppliRelation("1")
-                .carInsuredRelation("1")
-                .carCheckStatus("2")
-                .carCheckReason("2")
-                .vehicleId("1")
-                .printModelName(ziJinCrawlerQuotationRequest.getVehicleInfo() != null ? ziJinCrawlerQuotationRequest.getVehicleInfo().getPrintModelName() : "")
-                .printUseNatureCode("")
-                .vehicleOwnerNature(ziJinCrawlerQuotationRequest.getCarOwnerInfo() != null ? ziJinCrawlerQuotationRequest.getCarOwnerInfo().getVehicleOwnerNature() : "1")
-                .ownerAddress(quoteVo.getOwnersInfo().getAddr())
-                .sale4SFlag("0")
-                .policySupplementaryInfoList(new ArrayList<>())
-                .build();
-    }
-
-    /**
-     * 构建保存报价信息的车辆信息
-     *
-     * @param ziJinCrawlerQuotationRequest  报价参数
-     * @param ziJinCrawlerQuotationResponse 报价结果
-     * @return 保存报价信息的车辆信息
-     */
-    private ZiJinCrawlerSaveQuoteInfoRequest.VehicleInfo buildVehicleInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest, ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        ZiJinCrawlerQuotationRequest.VehicleInfo carInfo = ziJinCrawlerQuotationRequest.getVehicleInfo();
-        // 计算使用年限
-        int useYears = 0;
-        if (carInfo.getEnrollDate() != null) {
-            try {
-                java.time.LocalDate registerDate = java.time.LocalDate.parse(carInfo.getEnrollDate());
-                useYears = java.time.Period.between(registerDate, java.time.LocalDate.now()).getYears();
-            } catch (Exception e) {
-                log.warn("车辆注册日期格式错误,无法计算使用年限,原始值:{}", carInfo.getEnrollDate());
-            }
-        }
-        // 车辆种类和使用性质
-        List<String> vehicleKindAndUseNature = new ArrayList<>();
-        vehicleKindAndUseNature.add(carInfo.getCarKindCode());
-        vehicleKindAndUseNature.add(carInfo.getUseNatureCode());
-
-        return ZiJinCrawlerSaveQuoteInfoRequest.VehicleInfo.builder()
-                .useYears(useYears)
-                .actualValue(carInfo.getActualValue())
-                .agreeActualValue(carInfo.getAgreeActualValue())
-                .brandName(carInfo.getBrandName() != null ? carInfo.getBrandName() : "")
-                .carKindCode(carInfo.getCarKindCode())
-                .carKindDetailId(carInfo.getCarKindDetailId())
-                .carLoanFlag(carInfo.getCarLoanFlag())
-                .certificateDate(carInfo.getCertificateDate() != null ? carInfo.getCertificateDate() : "")
-                .chgOwnerFlag(carInfo.getChgOwnerFlag())
-                // .completekerbmass(carInfo.getCompletekerbmass() != null ? Integer.parseInt(carInfo.getCompletekerbmass()) : 0)
-                .completekerbmass(carInfo.getCompletekerbmass())
-                .ecdemicVehicleFlag(carInfo.getEcdemicVehicleFlag() != null ? carInfo.getEcdemicVehicleFlag() : "0")
-                .engineNo(carInfo.getEngineNo() != null ? carInfo.getEngineNo() : "")
-                .enrollDate(carInfo.getEnrollDate() != null ? carInfo.getEnrollDate() : "")
-                .updateEnrollDate(carInfo.getUpdateEnrollDate() != null ? carInfo.getUpdateEnrollDate() : "")
-                .exhaustCapacity(carInfo.getExhaustCapacity() != null ? carInfo.getExhaustCapacity() : 0)
-                .fuelType(carInfo.getFuelType())
-                .fuelTypeJY(carInfo.getFuelTypeJY())
-                .newEnergyFlag(carInfo.getNewEnergyFlag())
-                .licenseColorCode(carInfo.getLicenseColorCode())
-                .licenseKindCode(carInfo.getLicenseKindCode())
-                .licenseNo(carInfo.getLicenseNo() != null ? carInfo.getLicenseNo() : "")
-                .loanVehicleFlag(carInfo.getLoanVehicleFlag() != null ? carInfo.getLoanVehicleFlag() : "0")
-                .modelCode(carInfo.getModelCode() != null ? carInfo.getModelCode() : "")
-                .noLicenseFlag(carInfo.getNoLicenseFlag())
-                .issueDate(carInfo.getIssueDate() != null ? carInfo.getIssueDate() : "")
-                .oriCarKindName(carInfo.getOriCarKindName())
-                .platVehicleCode(carInfo.getPlatVehicleCode() != null ? carInfo.getPlatVehicleCode() : "")
-                .power(carInfo.getPower() != null ? carInfo.getPower() : "0")
-                .printUseNatureCode("")
-                .purchasePrice(carInfo.getPurchasePrice() != null ? carInfo.getPurchasePrice() : "0")
-                // .seatCount(carInfo.getSeatCount() != null ? Integer.parseInt(carInfo.getSeatCount()) : 5)
-                .seatCount(carInfo.getSeatCount())
-                .useNatureCode(carInfo.getUseNatureCode())
-                .vehicleId(carInfo.getVehicleId())
-                .makeDate(carInfo.getMakeDate() != null ? carInfo.getMakeDate() : "")
-                .makeDateJQ(carInfo.getMakeDateJQ() != null ? carInfo.getMakeDateJQ() : "")
-                .aliasName(carInfo.getAliasName() != null ? carInfo.getAliasName() : "")
-                .carCheckStatus("2")
-                .carCheckReason("2")
-                .vehicleKindAndUseNature(vehicleKindAndUseNature)
-                .oriBrandName(carInfo.getOriBrandName() != null ? carInfo.getOriBrandName() : "")
-                .oriPurchasePrice(carInfo.getOriPurchasePrice() != null ? carInfo.getOriPurchasePrice() : "0")
-                .isInvokeJingYou(carInfo.getIsInvokeJingYou())
-                .vehicleStyleUniqueId(carInfo.getVehicleStyleUniqueId() != null ? carInfo.getVehicleStyleUniqueId() : "")
-                .printModelName(carInfo.getPrintModelName() != null ? carInfo.getPrintModelName() : "")
-                .oriModelName(carInfo.getOriModelName() != null ? carInfo.getOriModelName() : "")
-                .vINNo(carInfo.getVinNo() != null ? carInfo.getVinNo() : "")
-                .modelEnergyType(carInfo.getModelEnergyType())
-                .build();
-    }
-
-    private ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo buildSaveTaxRelifInfo(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        if (ziJinCrawlerQuotationResponse.getCarShipTax() == null) {
-            return null;
-        }
-        ZiJinCrawlerQuotationResponse.CarShipTax carShipTax = ziJinCrawlerQuotationResponse.getCarShipTax();
-        return ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo.builder()
-                .taxRelifFlag(carShipTax.getTaxRelifFlag())
-                .sumPayTax(carShipTax.getSumPayTax() == null ? "0.0" : String.valueOf(carShipTax.getSumPayTax()))
-                .taxpayerName(carShipTax.getTaxpayerName())
-                .taxpayerIdentifier(carShipTax.getTaxpayerIdentifier())
-                .identifyNumber(carShipTax.getIdentifyNumber())
-                .payLastYear(carShipTax.getPayLastYear())
-                .lastCIPaymentTime(carShipTax.getLastCIPaymentTime())
-                .taxActual(carShipTax.getTaxActual() == null ? "0.0" : String.valueOf(carShipTax.getTaxActual()))
-                .previousPay(carShipTax.getPreviousPay() == null ? "0.0" : String.valueOf(carShipTax.getPreviousPay()))
-                .lateFee(carShipTax.getLateFee() == null ? "0.0" : String.valueOf(carShipTax.getLateFee()))
-                .taxRegistryNumber(carShipTax.getTaxRegistryNumber())
-                .isPlatformTax(true)
-                .extendChar1(carShipTax.getExtendChar1())
-                .taxUnit(carShipTax.getTaxUnit())
-                .completeKerbMass(carShipTax.getCompleteKerbMass())
-                .payerCode(carShipTax.getPayerCode())
-                .payStartDate(carShipTax.getPayStartDate())
-                .payEndDate(carShipTax.getPayEndDate())
-                .taxRelifFlagCN(carShipTax.getTaxRelifFlagCN())
-                .exceedDaysCount(carShipTax.getExceedDaysCount())
-                .currentTaxDue(ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo.CurrentTaxDue.builder()
-                        .taxLocationCode(carShipTax.getCurrentTaxDue().getTaxLocationCode())
-                        .taxEndDate(carShipTax.getCurrentTaxDue().getTaxEndDate())
-                        .taxStartDate(carShipTax.getCurrentTaxDue().getTaxStartDate())
-                        .taxUnitTypeCode(carShipTax.getCurrentTaxDue().getTaxUnitTypeCode())
-                        .taxDue(carShipTax.getCurrentTaxDue().getTaxDue() == null ? 0 : convertToInteger(carShipTax.getCurrentTaxDue().getTaxDue()))
-                        .unitRate(carShipTax.getCurrentTaxDue().getUnitRate() == null ? 0 : convertToInteger(carShipTax.getCurrentTaxDue().getUnitRate()))
-                        .annualTaxAmount(carShipTax.getCurrentTaxDue().getAnnualTaxAmount() == null ? 0 : convertToInteger(carShipTax.getCurrentTaxDue().getAnnualTaxAmount()))
-                        .exceedDaysCount(carShipTax.getCurrentTaxDue().getExceedDaysCount())
-                        .overDue(carShipTax.getCurrentTaxDue().getOverDue() == null ? 0 : convertToInteger(carShipTax.getCurrentTaxDue().getOverDue()))
-                        .taxConditionCode(carShipTax.getCurrentTaxDue().getTaxConditionCode())
-                        .totalAmount(carShipTax.getCurrentTaxDue().getTotalAmount() == null ? 0 : convertToInteger(carShipTax.getCurrentTaxDue().getTotalAmount()))
-                        .build())
-                .delinquentTaxDueList(Optional.ofNullable(ziJinCrawlerQuotationResponse.getCarShipTax().getDelinquentTaxDueList())
-                        .orElseGet(Collections::emptyList).stream().map(currentTaxDue -> ZiJinCrawlerSaveQuoteInfoRequest.TaxRelifInfo.CurrentTaxDue.builder()
-                                .taxDue(currentTaxDue.getTaxDue() == null ? 0 : convertToInteger(currentTaxDue.getTaxDue()))
-                                .overDue(currentTaxDue.getOverDue() == null ? 0 : convertToInteger(currentTaxDue.getOverDue()))
-                                .totalAmount(currentTaxDue.getTotalAmount() == null ? 0 : convertToInteger(currentTaxDue.getTotalAmount()))
-                                .exceedDaysCount(currentTaxDue.getExceedDaysCount() == null ? 0 : convertToInteger(currentTaxDue.getExceedDaysCount()))
-                                .unitRate(currentTaxDue.getUnitRate() == null ? 0 : convertToInteger(currentTaxDue.getUnitRate()))
-                                .annualTaxAmount(currentTaxDue.getAnnualTaxAmount() == null ? 0 : convertToInteger(currentTaxDue.getAnnualTaxAmount()))
-                                .taxStartDate(currentTaxDue.getTaxStartDate())
-                                .taxEndDate(currentTaxDue.getTaxEndDate())
-                                .taxLocationCode(currentTaxDue.getTaxLocationCode())
-                                .taxUnitTypeCode(currentTaxDue.getTaxUnitTypeCode())
-                                .taxConditionCode(currentTaxDue.getTaxConditionCode())
-                                .build()
-                        ).toList())
-                .build();
-    }
-
-    /**
-     * 构建保存的险别明细列表信息
-     *
-     * @param ziJinCrawlerQuotationResponse
-     * @return
-     */
-    @NotNull
-    private List<ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo> buildSaveItemKindList(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
-        List<ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo> itemKindList = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(ziJinCrawlerQuotationResponse.getItemKindList())) {
-            for (ZiJinCrawlerQuotationResponse.ItemKindList kind : ziJinCrawlerQuotationResponse.getItemKindList()) {
-                String amount = kind.getAmount() != null ? kind.getAmount().toString() : "0.0";
-                String premium = kind.getBenchMarkPremium() != null ? kind.getBenchMarkPremium() : "0.0000";
-                ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo itemKind = ZiJinCrawlerSaveQuoteInfoRequest.ItemKindInfo.builder()
-                        .amount(amount)
-                        .kindCode(kind.getKindCode())
-                        .kindName(kind.getKindName())
-                        .riskCode(kind.getRiskCode())
-                        .premium(premium)
-                        .benchMarkPremium(premium)
-                        .basePremium(kind.getBasePremium() != null ? kind.getBasePremium() : premium)
-                        .serviceTimes(kind.getServiceTimes())
-                        .build();
-                itemKindList.add(itemKind);
-            }
-        }
-        return itemKindList;
-    }
-
-    /**
-     * 构建保存的 投保人/被投保人 信息
-     *
-     * @param quoteVo
-     * @param ziJinCrawlerQuotationRequest
-     * @return
-     */
-    @NotNull
-    private List<ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo> buildSaveInsuredList(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
-        // 投保人
-        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
-        String addr = policyHolderInfo.getAddr();
-        String identifyValidDate = policyHolderInfo.getIdentifyValidDate();
-        String identifyValidEndDate = policyHolderInfo.getIdentifyValidEndDate();
-        // 被保人
-        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();
-        String addr1 = insuredPersonInfo.getAddr();
-        String identifyValidDate1 = insuredPersonInfo.getIdentifyValidDate();
-        String identifyValidEndDate1 = insuredPersonInfo.getIdentifyValidEndDate();
-
-        // 投保人信息 (insuredFlag=2), 被保人信息 (insuredFlag=1)
-        List<ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo> insuredList = new ArrayList<>();
-        // 获取被保人信息
-        if (CollectionUtils.isNotEmpty(ziJinCrawlerQuotationRequest.getInsuredList())) {
-            for (ZiJinCrawlerQuotationRequest.InsuredList insured : ziJinCrawlerQuotationRequest.getInsuredList()) {
-                ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo insuredInfo = ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo.builder()
-                        .address(insured.getInsuredFlag() == 2 ? addr : addr1)
-                        .identifyNumber(insured.getIdentifyNumber())
-                        .identifyType(ObjectUtils.isEmpty(insured.getIdentifyType()) ? "01" : insured.getIdentifyType())
-                        .insuredFlag(insured.getInsuredFlag())
-                        .insuredName(insured.getInsuredName())
-                        .insuredNature("3")
-                        .insuredType(insured.getInsuredType() != null ? insured.getInsuredType() : "1")
-                        .longAddress(insured.getInsuredFlag() == 2 ? addr : addr1)
-                        .mobile(insured.getMobile())
-                        .sex("2") // 默认值,从request中无法获取性别
-                        .nationality("中国")
-                        .occupation("A1301002")
-                        .addressProvince("")
-                        .addressPrefecture("")
-                        .addressCounty("")
-                        .postCode(insured.getPostCode() != null ? insured.getPostCode() : "030053")
-                        .insuredRelationship("1")
-                        .validDate(insured.getInsuredFlag() == 2 ? identifyValidEndDate : identifyValidEndDate1)
-                        .countryRegions("CHN")
-                        .vehicleRelationCode("1")
-                        .certigier(new HashMap<>())
-                        .chief(new HashMap<>())
-                        .riskLevelName("一般")
-                        .riskLevel("4")
-                        .reserved2("1")
-                        .reserved(new ArrayList<>())
-                        .businessManager(ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo.BusinessManager.builder()
-                                .insuredFlag("1")
-                                .build())
-                        .phoneHolder(ZiJinCrawlerSaveQuoteInfoRequest.InsuredInfo.PhoneHolder.builder()
-                                .insuredFlag("2")
-                                .build())
-                        .isPhoneOwner("1")
-                        .issuer("")
-                        .iDStartDate(insured.getInsuredFlag() == 2 ? identifyValidDate : identifyValidDate1)
-                        .build();
-                insuredList.add(insuredInfo);
-            }
-        }
-        return insuredList;
-    }
-
-    @NotNull
-    private List<ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo> buildSaveCarPolicySubInfo(ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
-        List<ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo> carPolicySubInfoList = new ArrayList<>();
-        if (CollectionUtils.isNotEmpty(ziJinCrawlerQuotationRequest.getCarPolicySubInfoList())) {
-            for (ZiJinCrawlerQuotationRequest.CarPolicySubInfoList subInfo : ziJinCrawlerQuotationRequest.getCarPolicySubInfoList()) {
-                ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo carPolicySubInfo = ZiJinCrawlerSaveQuoteInfoRequest.CarPolicySubInfo.builder()
-                        .planName(subInfo.getPlanName())
-                        .insureGradeNo(subInfo.getInsureGradeNo())
-                        .isUseInsured(subInfo.getIsUseInsured())
-                        .quantity(subInfo.getQuantity())
-                        .riskCode(subInfo.getRiskCode())
-                        .riskName(subInfo.getRiskName())
-                        .sumAmount(subInfo.getSumAmount() != null ? subInfo.getSumAmount().longValue() : 577000L)
-                        .sumPremium(subInfo.getSumPremium())
-                        .actualPremium(subInfo.getActualPremium())
-                        .productCode(subInfo.getProductCode())
-                        .build();
-                carPolicySubInfoList.add(carPolicySubInfo);
-            }
-        }
-        return carPolicySubInfoList;
-    }
-
-    private ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo buildSaveCarOwnerInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest) {
-        return ZiJinCrawlerSaveQuoteInfoRequest.CarOwnerInfo.builder()
-                .customerAmlPropReqDtoList(new ArrayList<>())
-                .carOwner(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getCarOwner())
-                .ownerIdentifyNumber(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getOwnerIdentifyNumber())
-                .ownerIdentifyType(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getOwnerIdentifyType())
-                .vehicleOwnerNature(ziJinCrawlerQuotationRequest.getCarOwnerInfo().getVehicleOwnerNature())
-                .ownerAddress(quoteVo.getOwnersInfo().getAddr())
-                .build();
-    }
-
-    /**
-     * 构建保存报价 基础信息 请求
-     *
-     * @param quoteVo                       系统前端参数
-     * @param ziJinCrawlerQuotationRequest  报价参数
-     * @param 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()
-                .teamType("10")
-                .agentCode(ziJinCrawlerQuotationRequest.getBaseInfo().getAgentCode())
-                .agreementNo(ziJinCrawlerQuotationRequest.getBaseInfo().getAgreementNo())
-                .businessNature(ziJinCrawlerQuotationRequest.getBaseInfo().getBusinessNature())
-                .comCode(ziJinCrawlerQuotationRequest.getBaseInfo().getComCode())
-                .comName(ziJinCrawlerQuotationRequest.getBaseInfo().getComName())
-                .areaCode("140000")
-                .handler1Code(ziJinCrawlerQuotationRequest.getBaseInfo().getHandler1Code())
-                .handler1Name(ziJinCrawlerQuotationRequest.getBaseInfo().getHandler1Name())
-                .operatorCode(ziJinCrawlerQuotationRequest.getBaseInfo().getOperatorCode())
-                .startDate(ziJinCrawlerQuotationRequest.getBaseInfo().getStartDate())
-                .startDateCI(ziJinCrawlerQuotationRequest.getBaseInfo().getStartDateCI())
-                .startHour(ziJinCrawlerQuotationRequest.getBaseInfo().getStartHour())
-                .startHourCI(ziJinCrawlerQuotationRequest.getBaseInfo().getStartHourCI())
-                .startMinute(ziJinCrawlerQuotationRequest.getBaseInfo().getStartMinute())
-                .startMinuteCI(ziJinCrawlerQuotationRequest.getBaseInfo().getStartMinuteCI())
-                .endDate(ziJinCrawlerQuotationRequest.getBaseInfo().getEndDate())
-                .endDateCI(ziJinCrawlerQuotationRequest.getBaseInfo().getEndDateCI())
-                .endHour(ziJinCrawlerQuotationRequest.getBaseInfo().getEndHour())
-                .endHourCI(ziJinCrawlerQuotationRequest.getBaseInfo().getEndHourCI())
-                .endMinute(ziJinCrawlerQuotationRequest.getBaseInfo().getEndMinute())
-                .endMinuteCI(ziJinCrawlerQuotationRequest.getBaseInfo().getEndMinuteCI())
-                .proposalCheckNo(ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo())
-                .goalInsuredFlag(ziJinCrawlerQuotationRequest.getBaseInfo().getGoalInsuredFlag())
-                .configName(ziJinCrawlerQuotationRequest.getBaseInfo().getConfigName())
-                .id(ziJinCrawlerQuotationRequest.getBaseInfo().getId())
-                .businessName(ziJinCrawlerQuotationRequest.getBaseInfo().getBusinessName())
-                .underscoreId(ziJinCrawlerQuotationRequest.getBaseInfo().getId())
-                .desc(ziJinCrawlerQuotationRequest.getBaseInfo().getDesc())
-                .handerCode(ziJinCrawlerQuotationRequest.getBaseInfo().getHanderCode())
-                .handerName(ziJinCrawlerQuotationRequest.getBaseInfo().getHanderName())
-                .calculateFlag(ziJinCrawlerQuotationRequest.getBaseInfo().getCalculateFlag())
-                .isCI(quoteVo.getCiRiskInfoVo() != null)
-                .isBI(quoteVo.getBiRiskInfoVo() != null)
-                .riskCodeEnum(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.builder()
-                        .CSTax(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.CSTaxInfo.builder()
-                                .riskCode(RiskCodeEnum.ACCIDENT_CODE)
-                                .riskName("车船税")
-                                .build())
-                        .CI(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.CIInfo.builder()
-                                .riskCode(RiskCodeEnum.TRAFFIC_CODE)
-                                .riskName("机动车交通事故责任强制保险")
-                                .amount("200000")
-                                .build())
-                        .BI(ZiJinCrawlerSaveQuoteInfoRequest.BaseInfo.RiskCodeEnum.BIInfo.builder()
-                                .riskCode(RiskCodeEnum.BUSINESS_CODE)
-                                .oldRiskCode("0501")
-                                .riskName("机动车商业保险(2020版)")
-                                .oldRiskName("新机动车商业险")
-                                .build())
-                        .productCode("CAR20190517")
-                        .productName("机动车保险")
-                        .useNatureList(Arrays.asList("82", "83", "84", "85", "9A", "9B", "9C", "9D"))
-                        .vehicleKindAndUseNature(Arrays.asList(ziJinCrawlerQuotationRequest.getVehicleInfo().getUseNatureCode(), ziJinCrawlerQuotationRequest.getVehicleInfo().getCarKindCode()))
-                        .icon("iconfont iconjidongche1")
-                        .name("car")
-                        .build())
-                .useRateFlag(true)
-                .argueSolution("1")
-                .autoTransRenewFlag("4")
-                .xbFlag("0")
-                .xbFlagCI("0")
-                .applicationType("T")
-                .split("1")
-                .sumPremiumCI(sumPremiumCI)
-                .sumPremium(sumPremium)
-                .build();
-    }
-
-    /**
-     * 将数字对象安全转换为整数
-     * 支持 Integer、Long、Float、Double、BigDecimal 等类型
-     *
-     * @param value 待转换的数字对象
-     * @return 转换后的整数值
-     */
-    private int convertToInteger(Object value) {
-        if (value == null) {
-            return 0;
-        }
-        if (value instanceof Number) {
-            return ((Number) value).intValue();
-        }
-        try {
-            // 处理字符串类型的数字(可能包含小数点)
-            String strValue = String.valueOf(value);
-            if (strValue.contains(".")) {
-                return (int) Double.parseDouble(strValue);
-            } else {
-                return Integer.parseInt(strValue);
-            }
-        } catch (NumberFormatException e) {
-            // 如果转换失败,返回默认值 0
-            return 0;
-        }
-    }
-
 }

+ 35 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/util/ConvertUtil.java

@@ -0,0 +1,35 @@
+package com.jzg.quotation.zijin.crawler.util;
+
+/**
+ * 数字转换工具类
+ */
+public class ConvertUtil {
+
+    /**
+     * 将数字对象安全转换为整数
+     * 支持 Integer、Long、Float、Double、BigDecimal 等类型
+     *
+     * @param value 待转换的数字对象
+     * @return 转换后的整数值
+     */
+    public static int convertToInteger(Object value) {
+        if (value == null) {
+            return 0;
+        }
+        if (value instanceof Number) {
+            return ((Number) value).intValue();
+        }
+        try {
+            // 处理字符串类型的数字(可能包含小数点)
+            String strValue = String.valueOf(value);
+            if (strValue.contains(".")) {
+                return (int) Double.parseDouble(strValue);
+            } else {
+                return Integer.parseInt(strValue);
+            }
+        } catch (NumberFormatException e) {
+            // 如果转换失败,返回默认值 0
+            return 0;
+        }
+    }
+}

+ 28 - 2
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/util/RS6Item.java

@@ -16,11 +16,14 @@ import java.io.IOException;
 import java.io.InputStreamReader;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.nio.file.FileSystemException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -169,6 +172,10 @@ public class RS6Item {
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
             throw new IOException("Process interrupted while executing node.js script", e);
+        } finally {
+            // 确保关闭所有资源
+            reader.close();
+            process.destroy();
         }
         return new LinkedHashMap<>(cookies);
     }
@@ -295,14 +302,33 @@ public class RS6Item {
     }
 
     /**
-     * 写入JS文件
+     * 写入JS文件(带有重试机制)
      * @param filename 文件名
      * @param content 文件内容
      * @throws IOException 如果写入文件时发生错误
      */
     private void writeJsFile(String filename, String content) throws IOException {
         Path filePath = Paths.get(scriptDir, filename);
-        Files.write(filePath, content.getBytes(StandardCharsets.UTF_8));
+        int maxRetries = 3;
+        long retryDelayMs = 500;
+        
+        for (int attempt = 1; attempt <= maxRetries; attempt++) {
+            try {
+                Files.write(filePath, content.getBytes(StandardCharsets.UTF_8));
+                return;
+            } catch (FileSystemException e) {
+                if (attempt < maxRetries) {
+                    try {
+                        Thread.sleep(retryDelayMs);
+                    } catch (InterruptedException ie) {
+                        Thread.currentThread().interrupt();
+                        throw new IOException("Interrupted while waiting to write file", ie);
+                    }
+                } else {
+                    throw e;
+                }
+            }
+        }
     }
 
     /**

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tenant/insurance/quotation-zijin/src/main/resources/js/auto.js


+ 1 - 1
tenant/insurance/quotation-zijin/src/main/resources/js/content.js

@@ -1 +1 @@
-___content ="_hYQ6AavokJoelEcr.GeRau9ukUCvnxAejeXOVsqAfh28FWjXbBEv88GeZcKnM8wiUFA.fIx0Pfjsgy0kJCZWgTF7H7Qf39EnkQ8dbBgGdIdPeU.hb30zgA9Jzl_KG9IAQv5xGSMC.HSm4xPhK2SH0lWNuENucw64L3hNeA7xGHWsD3C3Tto_BJB3ajs4j6FlNsQoNvGHOG";
+___content ="fY5znY3ooMK1EoS6a_dp1gC4c5BFiIzRmLdLFzirnbNyyW0nprFYZJtvUKU89vgWOHfEZX9eWSDnCWdcMuH92cafVbQBFoe96OMtzqEg90W85StKcGfP_NQ7DL4mQLfOuaZLolB.oNXFgxrpl3u6W2vFd5OJtl7Zy92qOD.CMacNA.i8khLQ4xddfbXJ12vK7ZCY7wJ_sAV";

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tenant/insurance/quotation-zijin/src/main/resources/js/tsssss.js


Некоторые файлы не были показаны из-за большого количества измененных файлов