Преглед на файлове

Merge branch 'master' into dev_jzg_lipf_v20260622

lipf преди 3 месеца
родител
ревизия
680652636d

+ 2 - 1
authentication/src/main/java/com/jzg/config/SecurityConfig.java

@@ -94,7 +94,8 @@ public class SecurityConfig {
                         .requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**", "/webjars/**", "/favicon.ico",
                                 "/auth/login","/auth/captchaById","/auth/register","/sendSmsCode","/appLogin","/smsCodeLogin","/auth/publicKeyExchange","/appAuth/smsCodeLogin","/send/sendSmsCode",
                                 "/appAuth/appLogin","/auth/sendSmsCode","/auth/forgotPassword","/appAuth/partnerAppLogin",
-                                "/supplementOrder/getOrderDetail","/dict/get", "/getAllButtons","/order/qrCode/**").permitAll()
+                                "/supplementOrder/getOrderDetail","/dict/get", "/getAllButtons","/order/qrCode/**","/appUser/userInfoGet",
+                                "/appUser/distributorInvite","/appUser/invitationRegister").permitAll()
                         .anyRequest().authenticated()  // 其他接口需认证
                 )
 //                .formLogin((form) -> form

+ 3 - 0
authentication/src/main/java/com/jzg/filter/TokenAuthenticationFilter.java

@@ -54,6 +54,9 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
         doList.add("/supplementOrder/getOrderDetail");
         doList.add("/dict/get");
         doList.add("/order/qrCode/index");
+        doList.add("/appUser/userInfoGet");
+        doList.add("/appUser/distributorInvite");
+        doList.add("/appUser/invitationRegister");
         String path = request.getRequestURI();
         for (String pattern : doList) {
             // 使用正则表达式匹配  .* 匹配所有以 pattern 开头的路径

+ 4 - 0
gateway/src/main/java/com/jzg/filter/AuthGlobalFilter.java

@@ -79,6 +79,10 @@ public class AuthGlobalFilter implements GlobalFilter {
         WHITELIST.add("/supplementOrder/getOrderDetail");
         WHITELIST.add("/dict/get");
 
+        WHITELIST.add("/appUser/userInfoGet");
+        WHITELIST.add("/appUser/distributorInvite");
+        WHITELIST.add("/appUser/invitationRegister");
+
         // 本地生活
         WHITELIST.add("/signIn/updateSignCompleteRuleIn");
     }

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

@@ -710,6 +710,38 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
             decryptData = req.quote(new HtCrawlerQuoteRequest(duplQuoteResult.q(), mealid, limitAmount, basePartJSON, personalInsuredJSON), h);
             log.info("resolveQuoteResponse attempt {}/{}: {}", i + 1, MAX_RETRIES, decryptData);
 
+            if (decryptData.contains("TRANS_MESSAGE") && decryptData.contains("终保日期")) {
+                Map<String, String> map = JSONObject.parseObject(decryptData, Map.class);
+                if (map.containsKey("TRANS_MESSAGE") && map.get("TRANS_MESSAGE").contains("交强")) {
+                    Matcher m = PAT_END_DATE2.matcher(decryptData);
+                    if (m.find()) {
+                        String jiaoqiang_startDate = m.group(1);
+                        log.info("报价响应结果CI,终保日期{}", jiaoqiang_startDate);
+                        duplQuoteResult.q().getCiRiskInfoVo().setStartDate(jiaoqiang_startDate + ":00");
+                        LocalDateTime dt = LocalDateTime.parse(jiaoqiang_startDate.replace(" ", "T"), DateTimeFormatter.ofPattern(DATE_FMT_T));
+                        String newEnd = dt.plusYears(1).format(DateTimeFormatter.ofPattern(DATE_FMT));
+                        duplQuoteResult.q().getCiRiskInfoVo().setEndDate(newEnd);
+                        decryptData = req.quote(new HtCrawlerQuoteRequest(duplQuoteResult.q(), mealid, limitAmount, "", personalInsuredJSON), h);
+                        return resolveQuoteResponse(duplQuoteResult, decryptData, mealid, limitAmount, h, personalInsuredJSON);
+                    }
+                }
+                if (map.containsKey("TRANS_MESSAGE") && map.get("TRANS_MESSAGE").contains("商业")) {
+                    Matcher m = PAT_END_DATE2.matcher(decryptData);
+                    if (m.find()) {
+                        String chesun_startDate = m.group(1);
+                        log.info("报价响应结果BI,终保日期{}", chesun_startDate);
+                        duplQuoteResult.q().getBiRiskInfoVo().setStartDate(chesun_startDate);
+                        duplQuoteResult.q().getCiRiskInfoVo().setStartDate(chesun_startDate);
+                        LocalDateTime dt = LocalDateTime.parse(chesun_startDate.replace(" ", "T"), DateTimeFormatter.ofPattern(DATE_FMT_T));
+                        String newEnd = dt.plusYears(1).format(DateTimeFormatter.ofPattern(DATE_FMT));
+                        duplQuoteResult.q().getBiRiskInfoVo().setEndDate(newEnd);
+                        duplQuoteResult.q().getCiRiskInfoVo().setEndDate(newEnd);
+                        decryptData = req.quote(new HtCrawlerQuoteRequest(duplQuoteResult.q(), mealid, limitAmount, "", personalInsuredJSON), h);
+                        return resolveQuoteResponse(duplQuoteResult, decryptData, mealid, limitAmount, h, personalInsuredJSON);
+                    }
+                }
+            }
+
             HtCrawlerQuoteResponse.DataDTO result = null;
             try {
                 result = JSONObject.parseObject(decryptData, HtCrawlerQuoteResponse.DataDTO.class);

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

@@ -306,6 +306,10 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
         if (error == null) {
             return false;
         }
+        if (error.contains("重复投保")) {
+            return false;
+        }
+
         // 匹配 Python 的判断逻辑(第 4773-4787 行)
         return error.contains("成功")
                 || error.contains("此单符合续保条件,已按照续保流程处理")

+ 34 - 19
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java

@@ -301,6 +301,10 @@ public class QuoteVerificationAspect {
         // 7. 计算总应收、总应付、保存费用比例 入库
         saveRatio(insFeeOrders, agreementInfoVo, jqCostType, syCostType, jyCostType);
         calculateTotalPremium(insFeeOrders);
+
+        // 8. 计算分销费用
+//        calculateDistributionFee(insOrdersCosts,insFeeOrders, insOrders);
+
         insFeeOrdersService.save(insFeeOrders);
         return insFeeOrders;
     }
@@ -382,7 +386,7 @@ public class QuoteVerificationAspect {
         BigDecimal addThrowPercent = convertPercent(costType.getAddThrow());
         BigDecimal exportPercent = convertPercent(costType.getExport());
 
-        // 计算应收金额
+        // 去税保费金额
         BigDecimal taxablePremium = premium.divide(taxFactor,5,RoundingMode.HALF_EVEN);
 
         // 计算应付金额(保费 * 出口比例,保留2位小数)
@@ -391,18 +395,24 @@ public class QuoteVerificationAspect {
         // 计算各类费用并设置到订单对象
         setPayable.accept(insFeeOrders, payable);
         BigDecimal commission = taxablePremium.multiply(commissionRatio).setScale(5, RoundingMode.HALF_EVEN);
-        BigDecimal follow = taxablePremium.multiply(followRatio).setScale(5, RoundingMode.HALF_EVEN);
+
         setCommission.accept(insFeeOrders, commission);
-        setFollow.accept(insFeeOrders, follow);
+
         // modify by lipf, 2026年6月16日15:35:09  加投比例,不需要根据平台/私有进行1.06的计算
 
         BigDecimal addAmount = premium.multiply(addThrowPercent).setScale(5, RoundingMode.HALF_EVEN);
         setAdditional.accept(insFeeOrders,addAmount);
 
-        BigDecimal receivable = BigDecimalUtil.add(commission,follow);
+        //应付金额计算
+        BigDecimal receivableRadio = commissionRatio.add(followRatio);
+        BigDecimal receivable = taxablePremium.multiply(receivableRadio).setScale(5,RoundingMode.HALF_EVEN);
         receivable = receivable.setScale(5, RoundingMode.HALF_EVEN);
         setReceivable.accept(insFeeOrders, receivable);
 
+        // 修改 应收-手续费 = 跟单费
+        BigDecimal follow = receivable.subtract(commission);
+        setFollow.accept(insFeeOrders, follow);
+
         // 设置留点比例 入口比例/taxFactor+加投比例-出口比例
         BigDecimal keepPointRateCal  = BigDecimalUtil.subtract(BigDecimalUtil.add(BigDecimalUtil.divide(inletPercent,taxFactor),addThrowPercent),exportPercent)
                 .setScale(5,RoundingMode.HALF_EVEN);
@@ -502,12 +512,18 @@ public class QuoteVerificationAspect {
         insFeeOrders.setJyInletRatio(jyCostType != null
                 ? convertPercent(jyCostType.getInlet() != null ? jyCostType.getInlet() : BigDecimal.ZERO) : BigDecimal.ZERO);
         // 跟单比例
-        insFeeOrders.setJqFollowRatio(jqCostType != null ?
-                calculateFollowRatio(jqCostType, convertPercent(agreementInfoVo.getAgreement().getJqEntranceFeeRatio())) : BigDecimal.ZERO);
-        insFeeOrders.setSyFollowRatio(syCostType != null ?
-                calculateFollowRatio(syCostType, convertPercent(agreementInfoVo.getAgreement().getSyEntranceFeeRatio())) : BigDecimal.ZERO);
-        insFeeOrders.setJyFollowRatio(jyCostType != null ?
-                calculateFollowRatio(jyCostType, convertPercent(agreementInfoVo.getAgreement().getJyEntranceFeeRatio())) : BigDecimal.ZERO);
+        insFeeOrders.setJqFollowRatio(Objects.nonNull(insFeeOrders.getJqFollowRatio()) ?
+                insFeeOrders.getJqFollowRatio() : BigDecimal.ZERO);
+        insFeeOrders.setSyFollowRatio(Objects.nonNull(insFeeOrders.getSyFollowRatio()) ?
+                insFeeOrders.getSyFollowRatio() : BigDecimal.ZERO);
+        insFeeOrders.setJyFollowRatio(Objects.nonNull(insFeeOrders.getJyFollowRatio()) ?
+                insFeeOrders.getJyFollowRatio() : BigDecimal.ZERO);
+//        insFeeOrders.setJqFollowRatio(jqCostType != null ?
+//                calculateFollowRatio(jqCostType, convertPercent(agreementInfoVo.getAgreement().getJqEntranceFeeRatio())) : BigDecimal.ZERO);
+//        insFeeOrders.setSyFollowRatio(syCostType != null ?
+//                calculateFollowRatio(syCostType, convertPercent(agreementInfoVo.getAgreement().getSyEntranceFeeRatio())) : BigDecimal.ZERO);
+//        insFeeOrders.setJyFollowRatio(jyCostType != null ?
+//                calculateFollowRatio(jyCostType, convertPercent(agreementInfoVo.getAgreement().getJyEntranceFeeRatio())) : BigDecimal.ZERO);
         // 加投比例
         insFeeOrders.setJqAdditionalRatio(jqCostType != null
                 ? convertPercent(jqCostType.getAddThrow() != null ? jqCostType.getAddThrow() : BigDecimal.ZERO)
@@ -519,15 +535,14 @@ public class QuoteVerificationAspect {
                 ? convertPercent(jyCostType.getAddThrow() != null ? jyCostType.getAddThrow() : BigDecimal.ZERO)
                 : BigDecimal.ZERO);
         // 留点比例
-        insFeeOrders.setJqKeepPointRatio(jqCostType != null
-                ? convertPercent(jqCostType.getKeepPointRatio() != null ? jqCostType.getKeepPointRatio() : BigDecimal.ZERO)
-                : BigDecimal.ZERO);
-        insFeeOrders.setSyKeepPointRatio(syCostType != null
-                ? convertPercent(syCostType.getKeepPointRatio() != null ? syCostType.getKeepPointRatio() : BigDecimal.ZERO)
-                : BigDecimal.ZERO);
-        insFeeOrders.setJyKeepPointRatio(jyCostType != null
-                ? convertPercent(jyCostType.getKeepPointRatio() != null ? jyCostType.getKeepPointRatio() : BigDecimal.ZERO)
-                : BigDecimal.ZERO);
+        insFeeOrders.setJqKeepPointRatio(Objects.nonNull(insFeeOrders.getJqKeepPointRatio())
+                ? insFeeOrders.getJqKeepPointRatio() : BigDecimal.ZERO);
+
+        insFeeOrders.setSyKeepPointRatio(Objects.nonNull(insFeeOrders.getSyKeepPointRatio())
+                ? insFeeOrders.getSyKeepPointRatio() : BigDecimal.ZERO);
+
+        insFeeOrders.setJyKeepPointRatio(Objects.nonNull(insFeeOrders.getJyKeepPointRatio())
+                ? insFeeOrders.getJyKeepPointRatio() : BigDecimal.ZERO);
 
         // 出口比例
         insFeeOrders.setJqExportRatio(jqCostType != null

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

@@ -1,23 +1,745 @@
 package com.jzg.quotation.zijin.crawler.build;
 
+import com.alibaba.fastjson.JSON;
+import com.jzg.commons.constants.quote.enums.quote.EnergyTypeCode;
+import com.jzg.commons.constants.quote.enums.quote.LicenseKindCode;
+import com.jzg.commons.entity.quote.vo.*;
 import com.jzg.commons.util.StringUtils;
+import com.jzg.quotation.zijin.api.constant.enums.MotorVehicleInsuranceEnum;
+import com.jzg.quotation.zijin.api.constant.enums.RiskCodeEnum;
+import com.jzg.quotation.zijin.crawler.component.ZiJinCrawlerRequestComponent;
+import com.jzg.quotation.zijin.crawler.entity.ZiJinCrawlerConfigureParameters;
+import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerGetCarActualValueRequest;
+import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerGetOrderNoRequest;
 import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerQuotationRequest;
 import com.jzg.quotation.zijin.crawler.entity.request.ZiJinCrawlerRecognizeCodesRequest;
-import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
-import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerRecognizeCodesResponse;
+import com.jzg.quotation.zijin.crawler.entity.response.*;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.http.HttpHeaders;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
- * @description: 紫金财险爬虫报价“转保标志”再次报价构建器
+ * @description: 紫金财险爬虫报价构建器
  * @author: wangrq
  * @date: 2026/6/6 16:05
  **/
+@Component
+@RequiredArgsConstructor
 @Slf4j
 public class ZiJinCrawlerQuoteRequestBuild {
 
+    private final ZiJinCrawlerRequestComponent ziJinCrawlerRequestComponent;
+
+    /**
+     * 构建报价请求对象
+     *
+     * @param quoteVo                               请求对象
+     * @param parameters                            紫金财险爬虫配置参数
+     * @param attributionInformationVo              归属信息配置信息
+     * @param ziJinCrawlerGetOrderNoResponse        获取订单号响应对象
+     * @param headers                               请求头
+     * @param ziJinCrawlerGetCarActualValueResponse 获取实际价值响应对象
+     * @param ziJinCrawlerGetOrderNoRequest         获取订单号请求对象
+     * @param ziJinCrawlerCarResponse               获取车辆信息响应对象
+     * @return 报价请求对象
+     */
+    public ZiJinCrawlerQuotationRequest buildZiJinCrawlerQuotationRequest(QuoteVo quoteVo, ZiJinCrawlerConfigureParameters parameters, AttributionInformationVo attributionInformationVo, ZiJinCrawlerGetOrderNoResponse ziJinCrawlerGetOrderNoResponse, HttpHeaders headers, ZiJinCrawlerGetCarActualValueResponse ziJinCrawlerGetCarActualValueResponse, ZiJinCrawlerGetOrderNoRequest ziJinCrawlerGetOrderNoRequest, ZiJinCrawlerCarResponse ziJinCrawlerCarResponse) {
+        // 报价接口
+        ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest = new ZiJinCrawlerQuotationRequest();
+        // 设置基础信息
+        ziJinCrawlerQuotationRequest.setBaseInfo(buildBaseInfo(quoteVo, parameters, attributionInformationVo.getUsername()));
+
+        // 设置车主信息
+        ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = buildCarOwnerInfo(quoteVo);
+        ziJinCrawlerQuotationRequest.setCarOwnerInfo(carOwnerInfo);
+
+        // 设置保险标志(固定"0")
+        ziJinCrawlerQuotationRequest.setInsuranceSign("0");
+
+        // 设置被保险人列表
+        ziJinCrawlerQuotationRequest.setInsuredList(buildInsuredList(quoteVo, carOwnerInfo));
+
+        // 设置订单ID - 从getOrderNo接口返回的动态获取
+        ziJinCrawlerQuotationRequest.setOrderId(ziJinCrawlerGetOrderNoResponse.getOrderId());
+        // 设置订单来源(固定"KSCD_PROD")
+        ziJinCrawlerQuotationRequest.setOrderOrigin("KSCD_PROD");
+        // 设置需求单校验标志(固定"1")
+        ziJinCrawlerQuotationRequest.setDemandNoCheckFlag("1");
+        // 设置产品代码(固定"CAR20190517"-机动车保险代码)
+        ziJinCrawlerQuotationRequest.setProductCode("CAR20190517");
+        // 设置产品名称(固定"机动车保险")
+        ziJinCrawlerQuotationRequest.setProductName("机动车保险");
+
+        // 设置减税信息
+        ziJinCrawlerQuotationRequest.setTaxRelifInfo(buildTaxRelifInfo(quoteVo, carOwnerInfo, parameters.getComCode(), headers));
+        // 设置险种列表
+        Double actualValue = null;
+        if (ziJinCrawlerGetCarActualValueResponse != null && org.springframework.util.StringUtils.hasLength(ziJinCrawlerGetCarActualValueResponse.getActualValue())) {
+            actualValue = Double.parseDouble(ziJinCrawlerGetCarActualValueResponse.getActualValue());
+        }
+        ziJinCrawlerQuotationRequest.setItemKindList(buildItemKindList(quoteVo, actualValue));
+
+        // 设置附加保单信息列表(推荐产品、驾意险、健康险、责任险、家财险、企业财产险)
+        ziJinCrawlerQuotationRequest.setCarPolicySubInfoList(buildCarPolicySubInfoList(quoteVo));
+
+        // 设置车辆信息
+        ziJinCrawlerQuotationRequest.setVehicleInfo(buildVehicleInfo(quoteVo, actualValue, ziJinCrawlerGetOrderNoRequest.getModelCode(), ziJinCrawlerGetOrderNoRequest.getIacVehicleCode(), ziJinCrawlerCarResponse));
+
+        // 设置盈利数据列表
+        // todo: 完了看是否要调整
+        ziJinCrawlerQuotationRequest.setProfitDataList(buildProfitDataList(quoteVo));
+
+        // 设置税务字段
+        ziJinCrawlerQuotationRequest.setTaxFields("identifyNumber,taxpayerIdentifier,taxpayerName,taxRegistryNumber");
+        // 设置附加险列表(空列表)
+        ziJinCrawlerQuotationRequest.setAttachRiskList(new ArrayList<>());
+        // 设置车载设备保费列表(空列表)
+        ziJinCrawlerQuotationRequest.setCarDevicePremiumDtoList(new ArrayList<>());
+
+        return ziJinCrawlerQuotationRequest;
+    }
+
+    /**
+     * 构建获取订单号请求对象
+     * 参数来源对照Python get_orderid_orderno方法:
+     * brandName -> 车型匹配后的vehicleName
+     * licenseNo -> quoteVo车牌号
+     * operatorCode -> 配置参数userCode
+     * proposalAreaCode -> configInfo中的proposalAreaCode
+     * proposalCityCode -> configInfo中的proposalCityCode
+     * userComCode -> 配置参数comCode
+     * vinNo -> quoteVo车架号
+     * modelCode -> 车型匹配后的vehicleCode
+     *
+     * @param quoteVo     报价实体
+     * @param parameters  配置参数
+     * @param configInfo  归属配置信息
+     * @param carResponse 车辆查询响应
+     * @return ZiJinCrawlerGetOrderNoRequest
+     */
+    public ZiJinCrawlerGetOrderNoRequest buildGetOrderNoRequest(QuoteVo quoteVo, ZiJinCrawlerConfigureParameters parameters,
+                                                                Map<String, String> configInfo, ZiJinCrawlerCarResponse carResponse) {
+        ZiJinCrawlerGetOrderNoRequest request = new ZiJinCrawlerGetOrderNoRequest();
+
+        // 从车辆查询响应中匹配车型,获取brandName和modelCode
+        // 对应Python: brandName = PPcarinfo['vehicleName'], modelCode = PPcarinfo['vehicleCode']
+        String brandName = "";
+        String modelCode = "";
+        String iacVehicleCode = "";
+        if (carResponse != null && carResponse.getVehicleModelInfoList() != null && !carResponse.getVehicleModelInfoList().isEmpty()) {
+            // 按purchasePrice和seatCount匹配车型,与Python逻辑一致
+            String purchasePrice = quoteVo.getCarInfoVo().getPurchasePrice();// 新车购置价[元]
+            String seatCount = quoteVo.getCarInfoVo().getSeatCount();// 座位数[座]
+            ZiJinCrawlerCarResponse.VehicleModelInfo matchedModel = null; // 车辆型号信息类
+            for (ZiJinCrawlerCarResponse.VehicleModelInfo model : carResponse.getVehicleModelInfoList()) {
+                if (purchasePrice != null && model.getPurchasePrice() != null
+                        && Double.parseDouble(model.getPurchasePrice()) == Double.parseDouble(purchasePrice)
+                        && model.getSeat() != null && seatCount != null
+                        && Double.parseDouble(model.getSeat()) >= Double.parseDouble(seatCount)) {
+                    matchedModel = model;
+                    break;
+                }
+            }
+            // 如果没有匹配到,且只有一个车型,则使用该车型(与Python逻辑一致)
+            if (matchedModel == null && carResponse.getVehicleModelInfoList().size() == 1) {
+                ZiJinCrawlerCarResponse.VehicleModelInfo onlyModel = carResponse.getVehicleModelInfoList().get(0);
+                if (onlyModel.getSeat() != null && seatCount != null
+                        && Double.parseDouble(onlyModel.getSeat()) >= Double.parseDouble(seatCount)) {
+                    matchedModel = onlyModel;
+                }
+            }
+            if (matchedModel == null) {
+                List<ZiJinCrawlerCarResponse.VehicleModelInfo> vehicleModelInfoList = carResponse.getVehicleModelInfoList();
+                List<String> vehicleNameList = vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getVehicleName).distinct().collect(Collectors.toList());
+                List<String> vehicleCodeList = vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getVehicleCode).distinct().collect(Collectors.toList());
+                List<String> iacVehicleCodeList = vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getIacVehicleCode).distinct().collect(Collectors.toList());
+
+                if (CollectionUtils.isNotEmpty(vehicleNameList)
+                        && CollectionUtils.isNotEmpty(vehicleCodeList)
+                        && CollectionUtils.isNotEmpty(iacVehicleCodeList)
+                        && vehicleNameList.size() == 1
+                        && vehicleCodeList.size() == 1
+                        && iacVehicleCodeList.size() == 1
+                ) {
+                    matchedModel = new ZiJinCrawlerCarResponse.VehicleModelInfo();
+                    matchedModel.setVehicleName(vehicleNameList.get(0));
+                    matchedModel.setVehicleCode(vehicleCodeList.get(0));
+                    matchedModel.setIacVehicleCode(iacVehicleCodeList.get(0));
+                }
+            }
+
+            if (matchedModel != null) {
+                brandName = matchedModel.getVehicleName();
+                modelCode = matchedModel.getVehicleCode();
+                iacVehicleCode = matchedModel.getIacVehicleCode();
+            }
+        }
+
+        request.setBrandName(brandName);
+        request.setLicenseNo(quoteVo.getCarInfoVo().getLicenseNo());
+        // operatorCode对应Python: operatorCode = self.baseInfo['handler1Code']
+        request.setOperatorCode(parameters.getUserCode());// 操作员编号
+        request.setOrderOrigin("KSCD_PROD");
+        // proposalAreaCode对应Python: proposalAreaCode = self.get_areacode(userComCode)
+        request.setProposalAreaCode(configInfo.getOrDefault("proposalAreaCode", ""));
+        // proposalCityCode对应Python: proposalCityCode = proposalAreaCode
+        request.setProposalCityCode(configInfo.getOrDefault("proposalCityCode", configInfo.getOrDefault("proposalAreaCode", "")));
+        // userComCode对应Python: userComCode = self.baseInfo['comCode']
+        request.setUserComCode(parameters.getComCode());// 用户公司代码
+        request.setVinNo(quoteVo.getCarInfoVo().getVinNo());
+        request.setModelCode(modelCode);// 车型代码
+        request.setProductCode("CAR20190517");
+        request.setProductName("机动车保险");
+        request.setTerminalId("KSCD");
+        request.setTerminalIdType("Vue-PC");
+        request.setIacVehicleCode(iacVehicleCode);// IAC车辆代码(行业车型编码)
+        return request;
+    }
+
+
+    /**
+     * 构建获取车辆实际价值请求对象
+     *
+     * @return ZiJinCrawlerGetCarActualValueRequest
+     */
+    @NotNull
+    public ZiJinCrawlerGetCarActualValueRequest buildGetCarActualValueRequest(QuoteVo quoteVo) {
+        ZiJinCrawlerGetCarActualValueRequest ziJinCrawlerGetCarActualValueRequest = new ZiJinCrawlerGetCarActualValueRequest();
+        ziJinCrawlerGetCarActualValueRequest.setCarKindCode(quoteVo.getCarInfoVo().getCarKindCode());
+        ziJinCrawlerGetCarActualValueRequest.setEnrollDate(quoteVo.getCarInfoVo().getRegisterDate());
+        ziJinCrawlerGetCarActualValueRequest.setUpdateEnrollDate(quoteVo.getCarInfoVo().getRegisterDate());
+        ziJinCrawlerGetCarActualValueRequest.setPurchasePrice(quoteVo.getCarInfoVo().getPurchasePrice());
+        ziJinCrawlerGetCarActualValueRequest.setSeatCount(Integer.valueOf(quoteVo.getCarInfoVo().getSeatCount()));
+        ziJinCrawlerGetCarActualValueRequest.setUseNatureCode("02".equals(quoteVo.getCarInfoVo().getCarNatureCode()) ? "85" : quoteVo.getCarInfoVo().getCarNatureCode());
+        ziJinCrawlerGetCarActualValueRequest.setStartDate(quoteVo.getCiRiskInfoVo().getStartDate().substring(0, 10));
+        ziJinCrawlerGetCarActualValueRequest.setNewEnergyFlag(quoteVo.getCarInfoVo().getEnergyTypeCode());
+        ziJinCrawlerGetCarActualValueRequest.setModelEnergyType(ObjectUtils.isEmpty(quoteVo.getCarInfoVo().getModelEnergyType()) ? "D1" : quoteVo.getCarInfoVo().getModelEnergyType());
+        return ziJinCrawlerGetCarActualValueRequest;
+    }
+
+    /**
+     * 构建报价基础信息对象
+     *
+     * @return ZiJinCrawlerQuotationRequest.BaseInfo
+     */
+    private ZiJinCrawlerQuotationRequest.BaseInfo buildBaseInfo(QuoteVo quoteVo, ZiJinCrawlerConfigureParameters parameters, String operatorCode) {
+        ZiJinCrawlerQuotationRequest.BaseInfo baseInfo = new ZiJinCrawlerQuotationRequest.BaseInfo();
+        baseInfo.setAgentCode(parameters.getAgentCode());
+        baseInfo.setAgreementNo(parameters.getAgentCode() + "-01");
+        baseInfo.setBusinessNature("1");
+        baseInfo.setComCode(parameters.getComCode());
+        baseInfo.setComName(parameters.getComName());
+        baseInfo.setHandler1Code(parameters.getUserCode());
+        baseInfo.setHandler1Name(parameters.getUserName());
+        baseInfo.setOperatorCode(operatorCode);
+        baseInfo.setStartDate(quoteVo.getCiRiskInfoVo().getStartDate().substring(0, 10));
+        baseInfo.setStartDateCI(quoteVo.getCiRiskInfoVo().getStartDate().substring(0, 10));
+        baseInfo.setStartHour("00");
+        baseInfo.setStartHourCI("00");
+        baseInfo.setStartMinute("00");
+        baseInfo.setStartMinuteCI("00");
+        baseInfo.setEndDate(quoteVo.getCiRiskInfoVo().getEndDate().substring(0, 10));
+        baseInfo.setEndDateCI(quoteVo.getCiRiskInfoVo().getEndDate().substring(0, 10));
+        baseInfo.setEndHour("24");
+        baseInfo.setEndHourCI("24");
+        baseInfo.setEndMinute("00");
+        baseInfo.setEndMinuteCI("00");
+        // 经测试:燃油单强设为0,交三不设置(待确认),会返回转保标志,紫金系统可以忽略进行下一步报价
+        baseInfo.setXbFlag(quoteVo.getBiRiskInfoVo() == null ? "0" : null);
+        baseInfo.setXbFlagCI(quoteVo.getBiRiskInfoVo() == null ? "0" : null);
+        baseInfo.setGoalInsuredFlag("0");
+        baseInfo.setConfigName("");
+        baseInfo.setId("1dec8ac2ced74973842a5b098669813a");
+        baseInfo.setBusinessName(parameters.getBusinessNatureName());
+        baseInfo.setIdMongo("1dec8ac2ced74973842a5b098669813a");
+        baseInfo.setDesc("");
+        baseInfo.setHanderCode(parameters.getUserCode());
+        baseInfo.setHanderName(parameters.getUserName());
+        baseInfo.setDemandNo("01ZKIC140026051910017933666448");
+        if (quoteVo.getBiRiskInfoVo() != null) {
+            baseInfo.setDemandNoCI("01ZKIC140026051910017933666448");// 这个先放开看行不
+        }
+        // 经测试:燃油: 单交设为2,交三设为0
+        baseInfo.setCalculateFlag(quoteVo.getBiRiskInfoVo() == null ? "2" : "0");
+        // 经测试:燃油:单交设为"",交三设为1?。 这个是续保标志,延顺日期的时候设置为1(完了测试一下)
+        baseInfo.setRenewalFlag(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
+        // 经测试:燃油:单交设为"",交三设为1?。 这个是续保标志,延顺日期的时候设置为1(完了测试一下)
+        baseInfo.setRenewalFlagCI(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
+        return baseInfo;
+    }
+
+
+    /**
+     * 构建车主信息对象
+     * 参数来源对照Python get_owner_info方法:
+     * carOwner -> quoteVo车主姓名
+     * ownerIdentifyNumber -> quoteVo车主证件号码
+     * ownerIdentifyType -> 根据证件类型映射(01-身份证)
+     * vehicleOwnerNature -> 根据人员类型映射(1-个人, 5-企业)
+     * ownerAddress -> quoteVo车主地址
+     *
+     * @param quoteVo 报价实体
+     * @return ZiJinCrawlerQuotationRequest.CarOwnerInfo
+     */
+    private ZiJinCrawlerQuotationRequest.CarOwnerInfo buildCarOwnerInfo(QuoteVo quoteVo) {
+        ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = new ZiJinCrawlerQuotationRequest.CarOwnerInfo();
+
+        CustomerInfoVo ownersInfo = quoteVo.getOwnersInfo();
+        if (ownersInfo != null) {
+            carOwnerInfo.setCarOwner(ownersInfo.getName());// 车主姓名
+            carOwnerInfo.setOwnerIdentifyNumber(ownersInfo.getIdentifyNumber());// 车主证件号码
+
+            // 根据证件类型映射车主性质和证件类型代码
+            String identifyType = ownersInfo.getIdentifyType();
+            String personType = ownersInfo.getPersonType();
+
+            // 证件类型映射,参考Python get_owner_i方法
+            // 个人类型(1) -> vehicleOwnerNature="1"
+            // 企业类型(2) -> vehicleOwnerNature="5"
+            if ("2".equals(personType)) {
+                // 企业
+                carOwnerInfo.setVehicleOwnerNature("5");
+                // 企业证件类型映射
+                carOwnerInfo.setOwnerIdentifyType(mapEnterpriseIdentifyType(identifyType));
+            } else {
+                // 个人(默认)
+                carOwnerInfo.setVehicleOwnerNature("1");
+                carOwnerInfo.setOwnerIdentifyType("01");// 01-身份证
+            }
+        }
+
+        return carOwnerInfo;
+    }
+
+    /**
+     * 构建被保险人列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
+     */
+    /**
+     * 构建被保险人列表
+     * 参数来源对照Python get_insuredList_info方法:
+     * insuredList包含两个对象:投保人(insuredFlag=2)和被保人(insuredFlag=1)
+     *
+     * @param quoteVo      报价实体
+     * @param carOwnerInfo 车主信息(用于判断与车主关系)
+     * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
+     */
+    private List<ZiJinCrawlerQuotationRequest.InsuredList> buildInsuredList(QuoteVo quoteVo,
+                                                                            ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo) {
+        List<ZiJinCrawlerQuotationRequest.InsuredList> insuredList = new ArrayList<>();
+
+        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();// 投保人
+        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();// 被保人
+
+        // 获取车主性质,用于判断投保人/被保人类型
+        String vehicleOwnerNature = carOwnerInfo != null ? carOwnerInfo.getVehicleOwnerNature() : "1";
+
+        // 1. 构建投保人信息 (insuredFlag=2)
+        if (policyHolderInfo != null) {
+            ZiJinCrawlerQuotationRequest.InsuredList policyHolder = new ZiJinCrawlerQuotationRequest.InsuredList();
+            buildInsuredItem(policyHolder, policyHolderInfo, 2, vehicleOwnerNature,
+                    carOwnerInfo != null ? carOwnerInfo.getOwnerIdentifyNumber() : null);
+            insuredList.add(policyHolder);
+        }
+
+        // 2. 构建被保人信息 (insuredFlag=1)
+        if (insuredPersonInfo != null) {
+            ZiJinCrawlerQuotationRequest.InsuredList insuredPerson = new ZiJinCrawlerQuotationRequest.InsuredList();
+            buildInsuredItem(insuredPerson, insuredPersonInfo, 1, vehicleOwnerNature,
+                    carOwnerInfo != null ? carOwnerInfo.getOwnerIdentifyNumber() : null);
+            insuredList.add(insuredPerson);
+        }
+
+        return insuredList;
+    }
+
+    /**
+     * 构建单个被保险人对象
+     *
+     * @param insuredItem         被保险人对象
+     * @param customerInfo        客户信息
+     * @param insuredFlag         被保险人标志(1-被保人, 2-投保人)
+     * @param vehicleOwnerNature  车主性质(1-个人, 5-企业)
+     * @param ownerIdentifyNumber 车主证件号码(用于判断与车主关系)
+     */
+    private void buildInsuredItem(ZiJinCrawlerQuotationRequest.InsuredList insuredItem,
+                                  CustomerInfoVo customerInfo, int insuredFlag, String vehicleOwnerNature,
+                                  String ownerIdentifyNumber) {
+        insuredItem.setInsuredName(customerInfo.getName());
+        insuredItem.setIdentifyNumber(customerInfo.getIdentifyNumber());
+
+        // 证件类型映射
+        String identifyType = customerInfo.getIdentifyType();
+        String personType = customerInfo.getPersonType();
+        if ("2".equals(personType)) {
+            // 企业
+            insuredItem.setIdentifyType(mapEnterpriseIdentifyType(identifyType));
+        } else {
+            // 个人(默认)
+            insuredItem.setIdentifyType("01");// 01-身份证
+        }
+
+        // 性别映射
+        String gender = customerInfo.getGender();
+        insuredItem.setSex("男".equals(gender) ? "1" : "2");
+
+        // 根据车主性质设置投保人/被保人类型
+        // 个人车主("1"): 投保人/被保人都是自然人
+        // 企业车主("5"): 投保人是法人,被保人是自然人
+        if ("5".equals(vehicleOwnerNature) && insuredFlag == 2) {
+            // 企业车主的投保人
+            insuredItem.setInsuredNature("4");// 4-法人或其他组织
+            insuredItem.setInsuredType("2");
+        } else {
+            // 个人车主或被保人
+            insuredItem.setInsuredNature("3");// 3-自然人
+            insuredItem.setInsuredType("1");
+        }
+
+        insuredItem.setMobile(customerInfo.getMobile());
+        insuredItem.setPostCode(org.springframework.util.StringUtils.hasLength(customerInfo.getPostCode()) ? customerInfo.getPostCode() : "030000");
+        insuredItem.setInsuredFlag(insuredFlag);
+    }
+
+
+    /**
+     * 构建险种列表
+     * 根据交强险和商业险的险种信息动态构建险种列表
+     *
+     * @param quoteVo     报价实体
+     * @param actualValue 车辆实际价值
+     * @return List<ZiJinCrawlerQuotationRequest.ItemKindList>
+     */
+    private List<ZiJinCrawlerQuotationRequest.ItemKindList> buildItemKindList(QuoteVo quoteVo, Double actualValue) {
+        List<ZiJinCrawlerQuotationRequest.ItemKindList> itemKindList = new ArrayList<>();
+
+        // 交通事故强制责任险  1. 检查是否有交强险(riskCode='0507')
+        if (quoteVo.getCiRiskInfoVo() != null) {
+            ZiJinCrawlerQuotationRequest.ItemKindList ciItem = new ZiJinCrawlerQuotationRequest.ItemKindList();
+            ciItem.setAmount("200000");// 这个需要查一下是哪的数据
+            ciItem.setKindCode(MotorVehicleInsuranceEnum.MVI_BZ.getCode());
+            ciItem.setKindName(MotorVehicleInsuranceEnum.MVI_BZ.getName());
+            ciItem.setRiskCode(RiskCodeEnum.TRAFFIC_CODE);
+            itemKindList.add(ciItem);
+        }
+
+        // 机动车第三者责任保险、附加医保外用药责任险、道路救援服务特约条款
+        // 根据商业险险种列表构建
+        if (quoteVo.getBiRiskInfoVo() != null && CollectionUtils.isNotEmpty(quoteVo.getKindInfoVo())) {
+            for (KindInfoVo kindItem : quoteVo.getKindInfoVo()) {
+                ZiJinCrawlerQuotationRequest.ItemKindList item = new ZiJinCrawlerQuotationRequest.ItemKindList();
+                item.setKindCode(kindItem.getKindCode());
+                item.setKindName(kindItem.getKindName());
+                item.setRiskCode(RiskCodeEnum.BUSINESS_CODE);
+                item.setAmount(kindItem.getAmount());
+                item.setUnitAmount(kindItem.getUnitAmount());
+                item.setServiceTimes(kindItem.getServiceTimes());
+                item.setQuantity(ObjectUtils.isEmpty(kindItem.getQuantity()) ? null : Integer.parseInt(kindItem.getQuantity()));
+                itemKindList.add(item);
+            }
+        }
+
+        return itemKindList;
+    }
+
+    /**
+     * 构建附加保单信息列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
+     */
+    /**
+     * 构建附加保单信息列表(驾乘险)
+     * 参数来源对照Python get_fcx_main方法:
+     * 根据驾乘险列表动态构建附加保单信息
+     * 目前只支持 rideRiskCode == "0733"(紫金驾驶人意外伤害保险)
+     *
+     * @param quoteVo 报价实体
+     * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
+     */
+    private List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> buildCarPolicySubInfoList(QuoteVo quoteVo) {
+        List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> carPolicySubInfoList = new ArrayList<>();
+
+        if (CollectionUtils.isEmpty(quoteVo.getAccidentalDrivings())) {
+            return carPolicySubInfoList;
+        }
+
+        for (AccidentalDrivingVo accidentalDriving : quoteVo.getAccidentalDrivings()) {
+            ZiJinCrawlerQuotationRequest.CarPolicySubInfoList carPolicySubInfo = new ZiJinCrawlerQuotationRequest.CarPolicySubInfoList();
+            carPolicySubInfo.setInsureGradeNo(accidentalDriving.getProductCode());
+            carPolicySubInfo.setProductCode(accidentalDriving.getProductCode());
+            carPolicySubInfo.setPlanName(accidentalDriving.getProductName());
+            carPolicySubInfo.setRiskCode(accidentalDriving.getRiskCode());
+            carPolicySubInfo.setRiskName(accidentalDriving.getProductName());
+            carPolicySubInfo.setSumAmount(ObjectUtils.isEmpty(accidentalDriving.getSumAmount()) ? 0 : (int) Double.parseDouble(accidentalDriving.getSumAmount()));
+            carPolicySubInfo.setQuantity(accidentalDriving.getQuantity() == 0 ? "0" : String.valueOf(accidentalDriving.getQuantity()));
+            carPolicySubInfo.setIsUseInsured("1");
+            carPolicySubInfo.setSumPremium(ObjectUtils.isEmpty(accidentalDriving.getPremium()) ? 0 : (int) Double.parseDouble(accidentalDriving.getPremium()));
+            carPolicySubInfoList.add(carPolicySubInfo);
+        }
+        return carPolicySubInfoList;
+    }
+
+    /**
+     * 构建减税信息对象
+     *
+     * @param quoteVo      报价实体
+     * @param carOwnerInfo 车主信息
+     * @param comCode      保险公司代码
+     * @param headers      请求头
+     * @return ZiJinCrawlerQuotationRequest.TaxRelifInfo
+     */
+    private ZiJinCrawlerQuotationRequest.TaxRelifInfo buildTaxRelifInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo, String comCode, HttpHeaders headers) {
+        ZiJinCrawlerQuotationRequest.TaxRelifInfo taxRelifInfo = new ZiJinCrawlerQuotationRequest.TaxRelifInfo();
+
+        // 只有投保交强险时才构建完整的税务信息
+        // 交强险riskCode为"0507"
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+
+        // 获取税务登记证号
+        String taxRegistryNumber = "";
+        try {
+            ZiJinCrawlerGetTaxRegistryNumberResponse taxResponse = ziJinCrawlerRequestComponent.getTaxRegistryNumber(comCode, headers);
+            if (taxResponse != null && org.springframework.util.StringUtils.hasLength(taxResponse.getData())) {
+                taxRegistryNumber = taxResponse.getData();
+            }
+        } catch (Exception e) {
+            log.error("获取税务登记证号失败: {}", e.getMessage());
+        }
+
+        // 设置税务信息
+        taxRelifInfo.setTaxRelifFlag(quoteVo.getVehicleAndVesselTaxVo().getTaxRelifFlag());// 1 正常缴税 2 免税 3 减税 4 已完税 5 不征
+
+        if (carOwnerInfo != null) {
+            taxRelifInfo.setTaxpayerName(carOwnerInfo.getCarOwner());// 纳税人姓名
+            taxRelifInfo.setTaxpayerIdentifier(carOwnerInfo.getOwnerIdentifyType());// 纳税人标识(证件类型)
+            taxRelifInfo.setIdentifyNumber(carOwnerInfo.getOwnerIdentifyNumber());// 证件号码
+        }
+
+        taxRelifInfo.setTaxRegistryNumber(taxRegistryNumber);// 税务登记证号
+
+        // 整备质量(公斤转吨)
+        if (carInfoVo != null && org.springframework.util.StringUtils.hasLength(carInfoVo.getCompleteKerbMass())) {
+            String completeKerbMassTon = carInfoVo.completeKerbMassToTonCount();
+            taxRelifInfo.setCompleteKerbMass(completeKerbMassTon);
+        }
+
+        return taxRelifInfo;
+    }
+
+    /**
+     * 构建车辆信息对象
+     *
+     * @return ZiJinCrawlerQuotationRequest.VehicleInfo
+     */
+    /**
+     * 构建车辆信息对象
+     * 参数来源对照Python get_car_info_main方法:
+     * - carInfoVo: 车辆基本信息
+     * - actualValue: 车辆实际价值(从API获取)
+     *
+     * @param quoteVo     报价实体
+     * @param actualValue 车辆实际价值
+     * @return VehicleInfo
+     */
+    private ZiJinCrawlerQuotationRequest.VehicleInfo buildVehicleInfo(QuoteVo quoteVo, Double actualValue, String modelCode, String iacVehicleCode, ZiJinCrawlerCarResponse ziJinCrawlerCarResponse) {
+        log.info("quoteVo参数的值:{}", JSON.toJSONString(quoteVo));
+        ZiJinCrawlerQuotationRequest.VehicleInfo vehicleInfo = new ZiJinCrawlerQuotationRequest.VehicleInfo();
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+
+        if (carInfoVo == null) {
+            return vehicleInfo;
+        }
+
+        // 基础车辆信息
+        if (actualValue != null) {
+            vehicleInfo.setActualValue(actualValue);
+            vehicleInfo.setAgreeActualValue(actualValue);
+        }
+        vehicleInfo.setBrandName(carInfoVo.getBrandName());
+        vehicleInfo.setColorCode("02"); // 默认黑色
+
+        // 车辆种类代码转换(A0->客车, A1->货车等)
+        vehicleInfo.setCarKindCode(org.springframework.util.StringUtils.hasLength(carInfoVo.getCarKindCode()) ? carInfoVo.getCarKindCode() : "A0");
+
+        vehicleInfo.setCarKindDetailId(carInfoVo.getCarKindDetailIdCode());
+
+        // 交强险过户标志
+        vehicleInfo.setCarLoanFlag(carInfoVo.isTransfer() ? "1" : "0");
+
+        // 购车发票日期(使用注册日期)
+        vehicleInfo.setCertificateDate(carInfoVo.getRegisterDate());
+
+        // 过户标志
+        vehicleInfo.setChgOwnerFlag(carInfoVo.isTransfer() ? "1" : "0");
+
+        // 整备质量
+        vehicleInfo.setCompletekerbmass(ObjectUtils.isEmpty(carInfoVo.getCompleteKerbMass()) ? 0 : Integer.parseInt(carInfoVo.getCompleteKerbMass()));
+
+        // 外地车标志(默认0)
+        vehicleInfo.setEcdemicVehicleFlag("0");
+
+        vehicleInfo.setEngineNo(carInfoVo.getEngineNo());
+
+        // 日期相关
+        vehicleInfo.setEnrollDate(carInfoVo.getRegisterDate());
+        vehicleInfo.setUpdateEnrollDate(carInfoVo.getRegisterDate());
+        vehicleInfo.setIssueDate(carInfoVo.getIssueDate());
+
+        // 过户日期处理
+        if (carInfoVo.isTransfer()) {
+            vehicleInfo.setMakeDate(carInfoVo.getTransferDate());
+            vehicleInfo.setMakeDateJQ(carInfoVo.getTransferDate());
+        }
+
+        // 车辆技术参数
+        if (org.springframework.util.StringUtils.hasLength(carInfoVo.getDisplacement())) {
+            // displacement是升(L),需要转换为毫升(ml)
+            double displacement = Double.parseDouble(carInfoVo.getDisplacement());
+            vehicleInfo.setExhaustCapacity((int) (displacement * 1000));
+        }
+
+        // 能源类型
+        vehicleInfo.setFuelType(carInfoVo.getEnergyTypeCode());
+        vehicleInfo.setFuelTypeJY(ObjectUtils.isEmpty(carInfoVo.getModelEnergyType()) ? ziJinCrawlerCarResponse.getVehicleModelInfoList().get(0).getPowerTypeCode() : carInfoVo.getModelEnergyType());
+
+        // 新能源标志, 0-燃油,1-新能源
+        // carInfoVo.isNewEnergyMark() 这个字段前端没传无法判断
+        vehicleInfo.setNewEnergyFlag(EnergyTypeCode.ENERGY_TYPE_CODE_0.getCode().equals(carInfoVo.getEnergyTypeCode()) ? "0" : "1");
+
+        vehicleInfo.setPower(carInfoVo.getPowerScale());
+        vehicleInfo.setModelEnergyType(ObjectUtils.isEmpty(carInfoVo.getModelEnergyType()) ? ziJinCrawlerCarResponse.getVehicleModelInfoList().get(0).getPowerTypeCode() : carInfoVo.getModelEnergyType());
+
+        // 牌照和车辆识别
+        vehicleInfo.setLicenseColorCode(org.springframework.util.StringUtils.hasLength(carInfoVo.getLicenseColorCode()) ? carInfoVo.getLicenseColorCode() : "01");
+        // 经测试:燃油和新能源都是02
+        if (org.springframework.util.StringUtils.hasLength(carInfoVo.getLicenseKindCode()) && (LicenseKindCode.L02.getCode().equals(carInfoVo.getLicenseKindCode()) || LicenseKindCode.L08.getCode().equals(carInfoVo.getLicenseKindCode()))) {
+            vehicleInfo.setLicenseKindCode("02");
+        } else {
+            vehicleInfo.setLicenseKindCode(carInfoVo.getLicenseKindCode());
+        }
+        vehicleInfo.setLicenseNo(carInfoVo.getLicenseNo());
+
+        // 贷款车标志
+        vehicleInfo.setLoanVehicleFlag(carInfoVo.isLoanStatus() ? "1" : "0");
+
+        // 车型代码
+        vehicleInfo.setModelCode(modelCode);
+
+        // 是否新车未上牌
+        vehicleInfo.setNoLicenseFlag("0".equals(carInfoVo.getIsRegistered()) ? "0" : "1");
+
+        vehicleInfo.setVehicleId("1");
+        vehicleInfo.setVinNo(carInfoVo.getVinNo());
+
+        // 车辆分类和用途
+        vehicleInfo.setSeatCount(ObjectUtils.isEmpty(carInfoVo.getSeatCount()) ? 0 : Integer.parseInt(carInfoVo.getSeatCount()));
+
+        // 使用性质代码
+        vehicleInfo.setUseNatureCode("02".equals(quoteVo.getCarInfoVo().getCarNatureCode()) ? "85" : quoteVo.getCarInfoVo().getCarNatureCode());
+        vehicleInfo.setOriCarKindName(carInfoVo.getCarTypeCode());
+
+        // 平台车辆代码
+        vehicleInfo.setPlatVehicleCode(iacVehicleCode);
+
+        // 车型唯一ID
+        vehicleInfo.setVehicleStyleUniqueId("");
+
+        // 价格和商业信息
+        vehicleInfo.setPurchasePrice(carInfoVo.getPurchasePrice());
+        vehicleInfo.setSale4SFlag("0");
+        vehicleInfo.setOriPurchasePrice(carInfoVo.getPurchasePrice());
+        vehicleInfo.setIsInvokeJingYou("1");
+
+        // 型号名称
+        vehicleInfo.setPrintVehicleModelName(carInfoVo.getBrandName());
+        vehicleInfo.setAliasName(carInfoVo.getBrandName());
+        vehicleInfo.setOriBrandName(carInfoVo.getBrandName());
+        vehicleInfo.setOriModelName(carInfoVo.getBrandName());
+        vehicleInfo.setPrintModelName(carInfoVo.getBrandName());
+        return vehicleInfo;
+    }
+
+    /**
+     * 构建盈利数据列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
+     */
+//    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList() {
+//        List<ZiJinCrawlerQuotationRequest.ProfitDataList> profitDataList = new ArrayList<>();
+//
+//        // 第一个盈利数据项
+//        ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+//        profitData1.setProfitCode("C31");
+//        profitData1.setProfitRate("1.05");
+//        profitDataList.add(profitData1);
+//
+//        // 第二个盈利数据项
+//        ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+//        profitData2.setProfitCode("C32");
+//        profitData2.setProfitRate("1.000000");
+//        profitDataList.add(profitData2);
+//        return profitDataList;
+//    }
+
+
+    /**
+     * 构建盈利数据列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
+     */
+    /**
+     * 构建盈利数据列表
+     * 参数来源对照Python代码:
+     * - coefficient: 自主定价系数,从 otherInfo 获取
+     * 只有当 coefficient 不为空且大于0时,才构建盈利数据列表
+     *
+     * @param quoteVo 报价实体
+     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
+     */
+    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList(QuoteVo quoteVo) {
+        List<ZiJinCrawlerQuotationRequest.ProfitDataList> profitDataList = new ArrayList<>();
+
+        // 获取自主定价系数
+        String coefficient = null;
+        if (quoteVo.getOtherInfo() != null) {
+            coefficient = quoteVo.getOtherInfo().getCoefficient();
+        }
+
+        // 只有当 coefficient 不为空且大于0时,才构建盈利数据列表
+        if (org.springframework.util.StringUtils.hasLength(coefficient)) {
+            try {
+                double coefficientValue = Double.parseDouble(coefficient);
+                if (coefficientValue > 0) {
+                    // 第一个盈利数据项 - 自主定价系数
+                    ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+                    profitData1.setProfitCode("C31");
+                    profitData1.setProfitRate(coefficient);
+                    profitDataList.add(profitData1);
+
+                    // 第二个盈利数据项 - 固定值
+                    ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+                    profitData2.setProfitCode("C32");
+                    profitData2.setProfitRate("1.000000");
+                    profitDataList.add(profitData2);
+                }
+            } catch (NumberFormatException e) {
+                // coefficient 不是有效数字,不构建盈利数据列表
+            }
+        }
+
+        return profitDataList;
+    }
+
     /**
      * 构建识别码请求
      *
@@ -60,4 +782,29 @@ public class ZiJinCrawlerQuoteRequestBuild {
         }
     }
 
+    /**
+     * 企业证件类型映射
+     * 参考Python get_owner_i方法中的IDType映射
+     *
+     * @param identifyType 证件类型
+     * @return 映射后的证件类型代码
+     */
+    private String mapEnterpriseIdentifyType(String identifyType) {
+        if (identifyType == null) {
+            return "11";// 默认工商注册号码
+        }
+        // 证件类型映射:工商注册号码->11, 统一社会信用代码->73, 组织机构代码->71
+        switch (identifyType) {
+            case "11": // 工商注册号码
+            case "2":  // 企业类型默认
+                return "11";
+            case "73": // 统一社会信用代码
+                return "73";
+            case "71": // 组织机构代码
+                return "71";
+            default:
+                return "11";// 默认工商注册号码
+        }
+    }
+
 }

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

@@ -5,7 +5,6 @@ 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.constants.quote.enums.quote.KindCode;
 import com.jzg.commons.entity.po.InsFeeOrders;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
@@ -66,7 +65,7 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
             // 设置交强险投保时间信息
             quoteResultsVo.setCiRiskInfoVo(buildCiRiskInfoVo(ziJinCrawlerQuotationResponse));
             // 设置商业险投保时间信息
-            quoteResultsVo.setBiRiskInfoVo(buildBiRiskInfoVo(ziJinCrawlerQuotationResponse));
+            quoteResultsVo.setBiRiskInfoVo(buildBiRiskInfoVo(quoteVo.getBiRiskInfoVo(), ziJinCrawlerQuotationResponse));
             // 设置商业险种的详细保费
             quoteResultsVo.setKindInfoVo(buildKindInfoVoList(quoteVo.getKindInfoVo(), ziJinCrawlerQuotationResponse));
         }
@@ -122,8 +121,8 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
      * @return RiskInfoVo
      */
     public static RiskInfoVo buildCiRiskInfoVo(ZiJinCrawlerQuotationResponse quotationResponse) {
-        RiskInfoVo riskInfoVo = new RiskInfoVo();
         ZiJinCrawlerQuotationResponse.BasePart basePart = quotationResponse.getBasePart();
+        RiskInfoVo riskInfoVo = new RiskInfoVo();
         riskInfoVo.setStartDate(basePart.getStartDateCI() == null ? null : DateTimeUtils.convertToDateTime(basePart.getStartDateCI(), basePart.getStartHourCI(), basePart.getStartMinuteCI()));
         riskInfoVo.setEndDate(basePart.getEndDateCI() == null ? null : DateTimeUtils.convertToDateTime(basePart.getEndDateCI(), basePart.getEndHourCI(), basePart.getEndMinuteCI()));
         return riskInfoVo;
@@ -135,7 +134,10 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
      * @param quotationResponse
      * @return RiskInfoVo
      */
-    public static RiskInfoVo buildBiRiskInfoVo(ZiJinCrawlerQuotationResponse quotationResponse) {
+    public static RiskInfoVo buildBiRiskInfoVo(RiskInfoVo biRiskInfoVo, ZiJinCrawlerQuotationResponse quotationResponse) {
+        if (biRiskInfoVo == null) {
+            return null;
+        }
         RiskInfoVo riskInfoVo = new RiskInfoVo();
         ZiJinCrawlerQuotationResponse.BasePart basePart = quotationResponse.getBasePart();
         riskInfoVo.setStartDate(basePart.getStartDate() == null ? null : DateTimeUtils.convertToDateTime(basePart.getStartDate(), basePart.getStartHour(), basePart.getStartMinute()));
@@ -264,7 +266,12 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
         quoteResultsVo.getCosts().setSumPremium(String.valueOf(sumPremium));
     }
 
-    // 构建评分
+    /**
+     * 构建评分
+     *
+     * @param ziJinCrawlerQuotationResponse
+     * @return
+     */
     private static QuoteResultsVo.ScoreVo buildScoreVo(ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse) {
         QuoteResultsVo.ScoreVo scoreVo = new QuoteResultsVo.ScoreVo();
 

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

@@ -0,0 +1,37 @@
+package com.jzg.quotation.zijin.crawler.build;
+
+import com.jzg.commons.constants.dict.InsOrderStatusEnum;
+import com.jzg.commons.entity.quote.vo.aggregated.UnderwritingResultsVo;
+import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerUnderwritingResponse;
+import com.jzg.quotation.zijin.crawler.enums.ResponseCode;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @Description: 构建紫金财险爬虫核保结果VO
+ * @Author: wangrq
+ * @Date: 2026/06/24 17:33
+ * @Version: 1.0
+ */
+@Slf4j
+public class ZiJinCrawlerUnderwritingResultsVoBuild {
+
+    @NotNull
+    public static UnderwritingResultsVo buildUnderwritingResultsVo(ZiJinCrawlerUnderwritingResponse ziJinCrawlerUnderwritingResponse) {
+        UnderwritingResultsVo underwritingResultsVo = new UnderwritingResultsVo();
+        // 核保成功
+        if (ResponseCode.R_0000.getCode().equals(ziJinCrawlerUnderwritingResponse.getRtnCode())) {
+            underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
+            underwritingResultsVo.setJqApplyNo(ziJinCrawlerUnderwritingResponse.getData().getResultObj().getProposalNoCI());
+            underwritingResultsVo.setSyApplyNo(ziJinCrawlerUnderwritingResponse.getData().getResultObj().getProposalNo());
+        } else {
+            underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
+            StringBuilder sb = new StringBuilder();
+            if (null != ziJinCrawlerUnderwritingResponse.getRtnMsg()) {
+                sb.append(String.format("错误信息:%s", ziJinCrawlerUnderwritingResponse.getRtnMsg()));
+            }
+            underwritingResultsVo.setUnderwritingResult(sb.toString());
+        }
+        return underwritingResultsVo;
+    }
+}

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

@@ -4,9 +4,8 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.google.zxing.NotFoundException;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
-import com.jzg.commons.constants.quote.enums.quote.EnergyTypeCode;
-import com.jzg.commons.constants.quote.enums.quote.LicenseKindCode;
-import com.jzg.commons.entity.quote.vo.*;
+import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
+import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.entity.quote.vo.base.OrderBase;
@@ -20,11 +19,10 @@ import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.commons.utils.DateTimeUtil;
 import com.jzg.quotation.commons.utils.TimeProcessing;
-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.ZiJinCrawlerQuoteRequestBuild;
 import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerQuoteResultsVoBuild;
 import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerSaveQuoteInfoRequestBuild;
+import com.jzg.quotation.zijin.crawler.build.ZiJinCrawlerUnderwritingResultsVoBuild;
 import com.jzg.quotation.zijin.crawler.component.ZiJinBuildingAttributionInformation;
 import com.jzg.quotation.zijin.crawler.component.ZiJinCrawlerCacheComponent;
 import com.jzg.quotation.zijin.crawler.component.ZiJinCrawlerRequestComponent;
@@ -40,7 +38,6 @@ import com.jzg.quotation.zijin.crawler.util.Base64ImageExtractor;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
-import org.jetbrains.annotations.NotNull;
 import org.springframework.http.HttpHeaders;
 import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
@@ -79,6 +76,8 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
 
     private final ZiJinCrawlerSaveQuoteInfoRequestBuild ziJinCrawlerSaveQuoteInfoRequestBuild;
 
+    private final ZiJinCrawlerQuoteRequestBuild ziJinCrawlerQuoteRequestBuild;
+
 
     /**
      * 登录
@@ -132,70 +131,20 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             log.info("ziJinCrawlerCarResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerCarResponse));
 
             // 车辆和交通查询(获取订单号)
-            ZiJinCrawlerGetOrderNoRequest ziJinCrawlerGetOrderNoRequest = buildGetOrderNoRequest(quoteVo, parameters, attributionInformationVo.getConfigInfo(), ziJinCrawlerCarResponse);
+            ZiJinCrawlerGetOrderNoRequest ziJinCrawlerGetOrderNoRequest = ziJinCrawlerQuoteRequestBuild.buildGetOrderNoRequest(quoteVo, parameters, attributionInformationVo.getConfigInfo(), ziJinCrawlerCarResponse);
             log.info("ziJinCrawlerGetOrderNoRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerGetOrderNoRequest));
-            String modelCode = ziJinCrawlerGetOrderNoRequest.getModelCode();// 车辆模型代码
-            String iacVehicleCode = ziJinCrawlerGetOrderNoRequest.getIacVehicleCode();// IAC车辆代码(行业车型编码)
             ZiJinCrawlerGetOrderNoResponse ziJinCrawlerGetOrderNoResponse = ziJinCrawlerRequestComponent.getOrderNo(ziJinCrawlerGetOrderNoRequest, headers);
             log.info("ziJinCrawlerGetOrderNoResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerGetOrderNoResponse));
 
             // 获取车辆实际价值
-            ZiJinCrawlerGetCarActualValueRequest ziJinCrawlerGetCarActualValueRequest = buildGetCarActualValueRequest(quoteVo);
+            ZiJinCrawlerGetCarActualValueRequest ziJinCrawlerGetCarActualValueRequest = ziJinCrawlerQuoteRequestBuild.buildGetCarActualValueRequest(quoteVo);
             log.info("ziJinCrawlerGetCarActualValueRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerGetCarActualValueRequest));
             ZiJinCrawlerGetCarActualValueResponse ziJinCrawlerGetCarActualValueResponse = ziJinCrawlerRequestComponent.getCarActualValue(ziJinCrawlerGetCarActualValueRequest, headers);
             log.info("ziJinCrawlerGetCarActualValueResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerGetCarActualValueResponse));
 
-            // 报价接口
-            ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest = new ZiJinCrawlerQuotationRequest();
-            // 设置基础信息
-            ziJinCrawlerQuotationRequest.setBaseInfo(buildBaseInfo(quoteVo, parameters, attributionInformationVo.getUsername()));
-
-            // 设置车主信息
-            ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = buildCarOwnerInfo(quoteVo);
-            ziJinCrawlerQuotationRequest.setCarOwnerInfo(carOwnerInfo);
-
-            // 设置保险标志(固定"0")
-            ziJinCrawlerQuotationRequest.setInsuranceSign("0");
-
-            // 设置被保险人列表
-            ziJinCrawlerQuotationRequest.setInsuredList(buildInsuredList(quoteVo, carOwnerInfo));
-
-            // 设置订单ID - 从getOrderNo接口返回的动态获取
-            ziJinCrawlerQuotationRequest.setOrderId(ziJinCrawlerGetOrderNoResponse.getOrderId());
-            // 设置订单来源(固定"KSCD_PROD")
-            ziJinCrawlerQuotationRequest.setOrderOrigin("KSCD_PROD");
-            // 设置需求单校验标志(固定"1")
-            ziJinCrawlerQuotationRequest.setDemandNoCheckFlag("1");
-            // 设置产品代码(固定"CAR20190517"-机动车保险代码)
-            ziJinCrawlerQuotationRequest.setProductCode("CAR20190517");
-            // 设置产品名称(固定"机动车保险")
-            ziJinCrawlerQuotationRequest.setProductName("机动车保险");
-
-            // 设置减税信息
-            ziJinCrawlerQuotationRequest.setTaxRelifInfo(buildTaxRelifInfo(quoteVo, carOwnerInfo, parameters.getComCode(), headers));
-            // 设置险种列表
-            Double actualValue = null;
-            if (ziJinCrawlerGetCarActualValueResponse != null && StringUtils.hasLength(ziJinCrawlerGetCarActualValueResponse.getActualValue())) {
-                actualValue = Double.parseDouble(ziJinCrawlerGetCarActualValueResponse.getActualValue());
-            }
-            ziJinCrawlerQuotationRequest.setItemKindList(buildItemKindList(quoteVo, actualValue));
-
-            // 设置附加保单信息列表(推荐产品、驾意险、健康险、责任险、家财险、企业财产险)
-            ziJinCrawlerQuotationRequest.setCarPolicySubInfoList(buildCarPolicySubInfoList(quoteVo));
+            // 构建报价请求
+            ZiJinCrawlerQuotationRequest ziJinCrawlerQuotationRequest = ziJinCrawlerQuoteRequestBuild.buildZiJinCrawlerQuotationRequest(quoteVo, parameters, attributionInformationVo, ziJinCrawlerGetOrderNoResponse, headers, ziJinCrawlerGetCarActualValueResponse, ziJinCrawlerGetOrderNoRequest, ziJinCrawlerCarResponse);
 
-            // 设置车辆信息
-            ziJinCrawlerQuotationRequest.setVehicleInfo(buildVehicleInfo(quoteVo, actualValue, modelCode, iacVehicleCode, ziJinCrawlerCarResponse));
-
-            // 设置盈利数据列表
-            // todo: 完了看是否要调整
-            ziJinCrawlerQuotationRequest.setProfitDataList(buildProfitDataList(quoteVo));
-
-            // 设置税务字段
-            ziJinCrawlerQuotationRequest.setTaxFields("identifyNumber,taxpayerIdentifier,taxpayerName,taxRegistryNumber");
-            // 设置附加险列表(空列表)
-            ziJinCrawlerQuotationRequest.setAttachRiskList(new ArrayList<>());
-            // 设置车载设备保费列表(空列表)
-            ziJinCrawlerQuotationRequest.setCarDevicePremiumDtoList(new ArrayList<>());
             // 报价
             log.info("ziJinCrawlerQuotationRequest参数:{}", JSON.toJSONString(ziJinCrawlerQuotationRequest));
             ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse = ziJinCrawlerRequestComponent.quotation(ziJinCrawlerQuotationRequest, headers);
@@ -262,6 +211,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         }
     }
 
+
     /**
      * 核保
      *
@@ -279,7 +229,6 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         ZiJinCrawlerUnderwritingResponse ziJinCrawlerUnderwritingResponse = null;
         try {
             ZiJinCrawlerUnderwritingRequest ziJinCrawlerUnderwritingRequest = new ZiJinCrawlerUnderwritingRequest("KSCD_PROD", ziJinCrawlerOrder.getOrderNo());
-            // 核保
             ziJinCrawlerUnderwritingResponse = ziJinCrawlerRequestComponent.underwriting(ziJinCrawlerUnderwritingRequest, headers);
             log.info("ziJinCrawlerUnderwritingResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerUnderwritingResponse));
         } catch (Exception e) {
@@ -287,21 +236,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             throw new RuntimeException(e);
         }
 
-        UnderwritingResultsVo underwritingResultsVo = new UnderwritingResultsVo();
-        // 核保成功
-        if ("0000".equals(ziJinCrawlerUnderwritingResponse.getRtnCode())) {
-            underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
-            underwritingResultsVo.setJqApplyNo(ziJinCrawlerUnderwritingResponse.getData().getResultObj().getProposalNoCI());
-            underwritingResultsVo.setSyApplyNo(ziJinCrawlerUnderwritingResponse.getData().getResultObj().getProposalNo());
-        } else {
-            underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
-            StringBuilder sb = new StringBuilder();
-            if (null != ziJinCrawlerUnderwritingResponse.getRtnMsg()) {
-                sb.append(String.format("错误信息:%s", ziJinCrawlerUnderwritingResponse.getRtnMsg()));
-            }
-            underwritingResultsVo.setUnderwritingResult(sb.toString());
-        }
-        return underwritingResultsVo;
+        return ZiJinCrawlerUnderwritingResultsVoBuild.buildUnderwritingResultsVo(ziJinCrawlerUnderwritingResponse);
     }
 
 
@@ -454,7 +389,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             }
 
             ZiJinCrawlerUploadImageInfoListRequest ziJinCrawlerUploadImageInfoListRequest = new ZiJinCrawlerUploadImageInfoListRequest(dataDTOS, ziJinCrawlerOrder.getBusUniqueId());
-            // 保存影像信息
+            // 上传影像信息
             ziJinCrawlerRequestComponent.uploadImageInfoList(ziJinCrawlerUploadImageInfoListRequest, headers);
 
             // 缓存影像信息
@@ -636,714 +571,6 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         return ziJinCrawlerQueryCarPolicyListRequest;
     }
 
-    /**
-     * 构建获取订单号请求对象
-     *
-     * @return ZiJinCrawlerGetOrderNoRequest
-     */
-//    private ZiJinCrawlerGetOrderNoRequest buildGetOrderNoRequest() {
-//        ZiJinCrawlerGetOrderNoRequest request = new ZiJinCrawlerGetOrderNoRequest();
-//        request.setBrandName("荣威CSA6452NEAQ多用途乘用车");
-//        request.setLicenseNo("晋HJW581");
-//        request.setOperatorCode("214000151");
-//        request.setOrderOrigin("KSCD_PROD");
-//        request.setProposalAreaCode("140000");
-//        request.setProposalCityCode("140000");
-//        request.setUserComCode("2140000601");
-//        request.setVinNo("LSJA24U69MS091895");
-//        request.setModelCode("RWD1598SQQ");
-//        request.setProductCode("CAR20190517");
-//        request.setProductName("机动车保险");
-//        request.setTerminalId("KSCD");
-//        request.setTerminalIdType("Vue-PC");
-//        return request;
-//    }
-
-
-    /**
-     * 构建获取订单号请求对象
-     * 参数来源对照Python get_orderid_orderno方法:
-     * brandName -> 车型匹配后的vehicleName
-     * licenseNo -> quoteVo车牌号
-     * operatorCode -> 配置参数userCode
-     * proposalAreaCode -> configInfo中的proposalAreaCode
-     * proposalCityCode -> configInfo中的proposalCityCode
-     * userComCode -> 配置参数comCode
-     * vinNo -> quoteVo车架号
-     * modelCode -> 车型匹配后的vehicleCode
-     *
-     * @param quoteVo     报价实体
-     * @param parameters  配置参数
-     * @param configInfo  归属配置信息
-     * @param carResponse 车辆查询响应
-     * @return ZiJinCrawlerGetOrderNoRequest
-     */
-    private ZiJinCrawlerGetOrderNoRequest buildGetOrderNoRequest(QuoteVo quoteVo, ZiJinCrawlerConfigureParameters parameters,
-                                                                 Map<String, String> configInfo, ZiJinCrawlerCarResponse carResponse) {
-        ZiJinCrawlerGetOrderNoRequest request = new ZiJinCrawlerGetOrderNoRequest();
-
-        // 从车辆查询响应中匹配车型,获取brandName和modelCode
-        // 对应Python: brandName = PPcarinfo['vehicleName'], modelCode = PPcarinfo['vehicleCode']
-        String brandName = "";
-        String modelCode = "";
-        String iacVehicleCode = "";
-        if (carResponse != null && carResponse.getVehicleModelInfoList() != null && !carResponse.getVehicleModelInfoList().isEmpty()) {
-            // 按purchasePrice和seatCount匹配车型,与Python逻辑一致
-            String purchasePrice = quoteVo.getCarInfoVo().getPurchasePrice();// 新车购置价[元]
-            String seatCount = quoteVo.getCarInfoVo().getSeatCount();// 座位数[座]
-            ZiJinCrawlerCarResponse.VehicleModelInfo matchedModel = null; // 车辆型号信息类
-            for (ZiJinCrawlerCarResponse.VehicleModelInfo model : carResponse.getVehicleModelInfoList()) {
-                if (purchasePrice != null && model.getPurchasePrice() != null
-                        && Double.parseDouble(model.getPurchasePrice()) == Double.parseDouble(purchasePrice)
-                        && model.getSeat() != null && seatCount != null
-                        && Double.parseDouble(model.getSeat()) >= Double.parseDouble(seatCount)) {
-                    matchedModel = model;
-                    break;
-                }
-            }
-            // 如果没有匹配到,且只有一个车型,则使用该车型(与Python逻辑一致)
-            if (matchedModel == null && carResponse.getVehicleModelInfoList().size() == 1) {
-                ZiJinCrawlerCarResponse.VehicleModelInfo onlyModel = carResponse.getVehicleModelInfoList().get(0);
-                if (onlyModel.getSeat() != null && seatCount != null
-                        && Double.parseDouble(onlyModel.getSeat()) >= Double.parseDouble(seatCount)) {
-                    matchedModel = onlyModel;
-                }
-            }
-            if (matchedModel == null) {
-                List<ZiJinCrawlerCarResponse.VehicleModelInfo> vehicleModelInfoList = carResponse.getVehicleModelInfoList();
-                List<String> vehicleNameList = vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getVehicleName).distinct().collect(Collectors.toList());
-                List<String> vehicleCodeList = vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getVehicleCode).distinct().collect(Collectors.toList());
-                List<String> iacVehicleCodeList = vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getIacVehicleCode).distinct().collect(Collectors.toList());
-
-                if (CollectionUtils.isNotEmpty(vehicleNameList)
-                        && CollectionUtils.isNotEmpty(vehicleCodeList)
-                        && CollectionUtils.isNotEmpty(iacVehicleCodeList)
-                        && vehicleNameList.size() == 1
-                        && vehicleCodeList.size() == 1
-                        && iacVehicleCodeList.size() == 1
-                ) {
-                    matchedModel = new ZiJinCrawlerCarResponse.VehicleModelInfo();
-                    matchedModel.setVehicleName(vehicleNameList.get(0));
-                    matchedModel.setVehicleCode(vehicleCodeList.get(0));
-                    matchedModel.setIacVehicleCode(iacVehicleCodeList.get(0));
-                }
-            }
-
-            if (matchedModel != null) {
-                brandName = matchedModel.getVehicleName();
-                modelCode = matchedModel.getVehicleCode();
-                iacVehicleCode = matchedModel.getIacVehicleCode();
-            }
-        }
-
-        request.setBrandName(brandName);
-        request.setLicenseNo(quoteVo.getCarInfoVo().getLicenseNo());
-        // operatorCode对应Python: operatorCode = self.baseInfo['handler1Code']
-        request.setOperatorCode(parameters.getUserCode());
-        request.setOrderOrigin("KSCD_PROD");
-        // proposalAreaCode对应Python: proposalAreaCode = self.get_areacode(userComCode)
-        request.setProposalAreaCode(configInfo.getOrDefault("proposalAreaCode", ""));
-        // proposalCityCode对应Python: proposalCityCode = proposalAreaCode
-        request.setProposalCityCode(configInfo.getOrDefault("proposalCityCode", configInfo.getOrDefault("proposalAreaCode", "")));
-        // userComCode对应Python: userComCode = self.baseInfo['comCode']
-        request.setUserComCode(parameters.getComCode());
-        request.setVinNo(quoteVo.getCarInfoVo().getVinNo());
-        request.setModelCode(modelCode);
-        request.setProductCode("CAR20190517");
-        request.setProductName("机动车保险");
-        request.setTerminalId("KSCD");
-        request.setTerminalIdType("Vue-PC");
-
-        //
-        // request.setBrandName("哈弗CC6460AZ04B多用途乘用车");//品牌名称
-        // request.setModelCode("CC6460AZ04B");//车型代码
-        request.setOperatorCode("214000151");// 操作员编号
-        request.setUserComCode("2140000601");// 用户公司代码
-        request.setIacVehicleCode(iacVehicleCode);// IAC车辆代码(行业车型编码)
-
-        return request;
-    }
-
-
-    /**
-     * 构建获取车辆实际价值请求对象
-     *
-     * @return ZiJinCrawlerGetCarActualValueRequest
-     */
-    @NotNull
-    private static ZiJinCrawlerGetCarActualValueRequest buildGetCarActualValueRequest(QuoteVo quoteVo) {
-        ZiJinCrawlerGetCarActualValueRequest ziJinCrawlerGetCarActualValueRequest = new ZiJinCrawlerGetCarActualValueRequest();
-        ziJinCrawlerGetCarActualValueRequest.setCarKindCode(quoteVo.getCarInfoVo().getCarKindCode());
-        ziJinCrawlerGetCarActualValueRequest.setEnrollDate(quoteVo.getCarInfoVo().getRegisterDate());
-        ziJinCrawlerGetCarActualValueRequest.setUpdateEnrollDate(quoteVo.getCarInfoVo().getRegisterDate());
-        ziJinCrawlerGetCarActualValueRequest.setPurchasePrice(quoteVo.getCarInfoVo().getPurchasePrice());
-        ziJinCrawlerGetCarActualValueRequest.setSeatCount(Integer.valueOf(quoteVo.getCarInfoVo().getSeatCount()));
-        ziJinCrawlerGetCarActualValueRequest.setUseNatureCode("02".equals(quoteVo.getCarInfoVo().getCarNatureCode()) ? "85" : quoteVo.getCarInfoVo().getCarNatureCode());
-        ziJinCrawlerGetCarActualValueRequest.setStartDate(quoteVo.getCiRiskInfoVo().getStartDate().substring(0, 10));
-        ziJinCrawlerGetCarActualValueRequest.setNewEnergyFlag(quoteVo.getCarInfoVo().getEnergyTypeCode());
-        ziJinCrawlerGetCarActualValueRequest.setModelEnergyType(ObjectUtils.isEmpty(quoteVo.getCarInfoVo().getModelEnergyType()) ? "D1" : quoteVo.getCarInfoVo().getModelEnergyType());
-        return ziJinCrawlerGetCarActualValueRequest;
-    }
-
-    /**
-     * 构建报价基础信息对象
-     *
-     * @return ZiJinCrawlerQuotationRequest.BaseInfo
-     */
-    private ZiJinCrawlerQuotationRequest.BaseInfo buildBaseInfo(QuoteVo quoteVo, ZiJinCrawlerConfigureParameters parameters, String operatorCode) {
-        ZiJinCrawlerQuotationRequest.BaseInfo baseInfo = new ZiJinCrawlerQuotationRequest.BaseInfo();
-        baseInfo.setAgentCode(parameters.getAgentCode());
-        baseInfo.setAgreementNo(parameters.getAgentCode() + "-01");
-        baseInfo.setBusinessNature("1");
-        baseInfo.setComCode(parameters.getComCode());
-        baseInfo.setComName(parameters.getComName());
-        baseInfo.setHandler1Code(parameters.getUserCode());
-        baseInfo.setHandler1Name(parameters.getUserName());
-        baseInfo.setOperatorCode(operatorCode);
-        baseInfo.setStartDate(quoteVo.getCiRiskInfoVo().getStartDate().substring(0, 10));
-        baseInfo.setStartDateCI(quoteVo.getCiRiskInfoVo().getStartDate().substring(0, 10));
-        baseInfo.setStartHour("00");
-        baseInfo.setStartHourCI("00");
-        baseInfo.setStartMinute("00");
-        baseInfo.setStartMinuteCI("00");
-        baseInfo.setEndDate(quoteVo.getCiRiskInfoVo().getEndDate().substring(0, 10));
-        baseInfo.setEndDateCI(quoteVo.getCiRiskInfoVo().getEndDate().substring(0, 10));
-        baseInfo.setEndHour("24");
-        baseInfo.setEndHourCI("24");
-        baseInfo.setEndMinute("00");
-        baseInfo.setEndMinuteCI("00");
-        // 经测试:燃油单强设为0,交三不设置(待确认),会返回转保标志,紫金系统可以忽略进行下一步报价
-        baseInfo.setXbFlag(quoteVo.getBiRiskInfoVo() == null ? "0" : null);
-        baseInfo.setXbFlagCI(quoteVo.getBiRiskInfoVo() == null ? "0" : null);
-        baseInfo.setGoalInsuredFlag("0");
-        baseInfo.setConfigName("");
-        baseInfo.setId("1dec8ac2ced74973842a5b098669813a");
-        baseInfo.setBusinessName(parameters.getBusinessNatureName());
-        baseInfo.setIdMongo("1dec8ac2ced74973842a5b098669813a");
-        baseInfo.setDesc("");
-        baseInfo.setHanderCode(parameters.getUserCode());
-        baseInfo.setHanderName(parameters.getUserName());
-        baseInfo.setDemandNo("01ZKIC140026051910017933666448");
-        if (quoteVo.getBiRiskInfoVo() != null) {
-            baseInfo.setDemandNoCI("01ZKIC140026051910017933666448");// 这个先放开看行不
-        }
-        // 经测试:燃油: 单交设为2,交三设为0
-        baseInfo.setCalculateFlag(quoteVo.getBiRiskInfoVo() == null ? "2" : "0");
-        // 经测试:燃油:单交设为"",交三设为1?。 这个是续保标志,延顺日期的时候设置为1(完了测试一下)
-        baseInfo.setRenewalFlag(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
-        // 经测试:燃油:单交设为"",交三设为1?。 这个是续保标志,延顺日期的时候设置为1(完了测试一下)
-        baseInfo.setRenewalFlagCI(quoteVo.getBiRiskInfoVo() == null ? "" : "1");
-        return baseInfo;
-    }
-
-
-    /**
-     * 构建车主信息对象
-     * 参数来源对照Python get_owner_info方法:
-     * carOwner -> quoteVo车主姓名
-     * ownerIdentifyNumber -> quoteVo车主证件号码
-     * ownerIdentifyType -> 根据证件类型映射(01-身份证)
-     * vehicleOwnerNature -> 根据人员类型映射(1-个人, 5-企业)
-     * ownerAddress -> quoteVo车主地址
-     *
-     * @param quoteVo 报价实体
-     * @return ZiJinCrawlerQuotationRequest.CarOwnerInfo
-     */
-    private ZiJinCrawlerQuotationRequest.CarOwnerInfo buildCarOwnerInfo(QuoteVo quoteVo) {
-        ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = new ZiJinCrawlerQuotationRequest.CarOwnerInfo();
-
-        CustomerInfoVo ownersInfo = quoteVo.getOwnersInfo();
-        if (ownersInfo != null) {
-            carOwnerInfo.setCarOwner(ownersInfo.getName());// 车主姓名
-            carOwnerInfo.setOwnerIdentifyNumber(ownersInfo.getIdentifyNumber());// 车主证件号码
-
-            // 根据证件类型映射车主性质和证件类型代码
-            String identifyType = ownersInfo.getIdentifyType();
-            String personType = ownersInfo.getPersonType();
-
-            // 证件类型映射,参考Python get_owner_i方法
-            // 个人类型(1) -> vehicleOwnerNature="1"
-            // 企业类型(2) -> vehicleOwnerNature="5"
-            if ("2".equals(personType)) {
-                // 企业
-                carOwnerInfo.setVehicleOwnerNature("5");
-                // 企业证件类型映射
-                carOwnerInfo.setOwnerIdentifyType(mapEnterpriseIdentifyType(identifyType));
-            } else {
-                // 个人(默认)
-                carOwnerInfo.setVehicleOwnerNature("1");
-                carOwnerInfo.setOwnerIdentifyType("01");// 01-身份证
-            }
-        }
-
-        return carOwnerInfo;
-    }
-
-
-    /**
-     * 企业证件类型映射
-     * 参考Python get_owner_i方法中的IDType映射
-     *
-     * @param identifyType 证件类型
-     * @return 映射后的证件类型代码
-     */
-    private String mapEnterpriseIdentifyType(String identifyType) {
-        if (identifyType == null) {
-            return "11";// 默认工商注册号码
-        }
-        // 证件类型映射:工商注册号码->11, 统一社会信用代码->73, 组织机构代码->71
-        switch (identifyType) {
-            case "11": // 工商注册号码
-            case "2":  // 企业类型默认
-                return "11";
-            case "73": // 统一社会信用代码
-                return "73";
-            case "71": // 组织机构代码
-                return "71";
-            default:
-                return "11";// 默认工商注册号码
-        }
-    }
-
-    /**
-     * 构建被保险人列表
-     *
-     * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
-     */
-    /**
-     * 构建被保险人列表
-     * 参数来源对照Python get_insuredList_info方法:
-     * insuredList包含两个对象:投保人(insuredFlag=2)和被保人(insuredFlag=1)
-     *
-     * @param quoteVo      报价实体
-     * @param carOwnerInfo 车主信息(用于判断与车主关系)
-     * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
-     */
-    private List<ZiJinCrawlerQuotationRequest.InsuredList> buildInsuredList(QuoteVo quoteVo,
-                                                                            ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo) {
-        List<ZiJinCrawlerQuotationRequest.InsuredList> insuredList = new ArrayList<>();
-
-        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();// 投保人
-        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();// 被保人
-
-        // 获取车主性质,用于判断投保人/被保人类型
-        String vehicleOwnerNature = carOwnerInfo != null ? carOwnerInfo.getVehicleOwnerNature() : "1";
-
-        // 1. 构建投保人信息 (insuredFlag=2)
-        if (policyHolderInfo != null) {
-            ZiJinCrawlerQuotationRequest.InsuredList policyHolder = new ZiJinCrawlerQuotationRequest.InsuredList();
-            buildInsuredItem(policyHolder, policyHolderInfo, 2, vehicleOwnerNature,
-                    carOwnerInfo != null ? carOwnerInfo.getOwnerIdentifyNumber() : null);
-            insuredList.add(policyHolder);
-        }
-
-        // 2. 构建被保人信息 (insuredFlag=1)
-        if (insuredPersonInfo != null) {
-            ZiJinCrawlerQuotationRequest.InsuredList insuredPerson = new ZiJinCrawlerQuotationRequest.InsuredList();
-            buildInsuredItem(insuredPerson, insuredPersonInfo, 1, vehicleOwnerNature,
-                    carOwnerInfo != null ? carOwnerInfo.getOwnerIdentifyNumber() : null);
-            insuredList.add(insuredPerson);
-        }
-
-        return insuredList;
-    }
-
-    /**
-     * 构建单个被保险人对象
-     *
-     * @param insuredItem         被保险人对象
-     * @param customerInfo        客户信息
-     * @param insuredFlag         被保险人标志(1-被保人, 2-投保人)
-     * @param vehicleOwnerNature  车主性质(1-个人, 5-企业)
-     * @param ownerIdentifyNumber 车主证件号码(用于判断与车主关系)
-     */
-    private void buildInsuredItem(ZiJinCrawlerQuotationRequest.InsuredList insuredItem,
-                                  CustomerInfoVo customerInfo, int insuredFlag, String vehicleOwnerNature,
-                                  String ownerIdentifyNumber) {
-        insuredItem.setInsuredName(customerInfo.getName());
-        insuredItem.setIdentifyNumber(customerInfo.getIdentifyNumber());
-
-        // 证件类型映射
-        String identifyType = customerInfo.getIdentifyType();
-        String personType = customerInfo.getPersonType();
-        if ("2".equals(personType)) {
-            // 企业
-            insuredItem.setIdentifyType(mapEnterpriseIdentifyType(identifyType));
-        } else {
-            // 个人(默认)
-            insuredItem.setIdentifyType("01");// 01-身份证
-        }
-
-        // 性别映射
-        String gender = customerInfo.getGender();
-        insuredItem.setSex("男".equals(gender) ? "1" : "2");
-
-        // 根据车主性质设置投保人/被保人类型
-        // 个人车主("1"): 投保人/被保人都是自然人
-        // 企业车主("5"): 投保人是法人,被保人是自然人
-        if ("5".equals(vehicleOwnerNature) && insuredFlag == 2) {
-            // 企业车主的投保人
-            insuredItem.setInsuredNature("4");// 4-法人或其他组织
-            insuredItem.setInsuredType("2");
-        } else {
-            // 个人车主或被保人
-            insuredItem.setInsuredNature("3");// 3-自然人
-            insuredItem.setInsuredType("1");
-        }
-
-        insuredItem.setMobile(customerInfo.getMobile());
-        insuredItem.setPostCode(StringUtils.hasLength(customerInfo.getPostCode()) ?
-                customerInfo.getPostCode() : "030000");
-        insuredItem.setInsuredFlag(insuredFlag);
-    }
-
-    /**
-     * 构建减税信息对象
-     *
-     * @return ZiJinCrawlerQuotationRequest.TaxRelifInfo
-     */
-    private ZiJinCrawlerQuotationRequest.TaxRelifInfo buildTaxRelifInfo2() {
-        ZiJinCrawlerQuotationRequest.TaxRelifInfo taxRelifInfo = new ZiJinCrawlerQuotationRequest.TaxRelifInfo();
-        taxRelifInfo.setTaxRelifFlag("1");
-        taxRelifInfo.setTaxpayerName("王婧");
-        taxRelifInfo.setTaxpayerIdentifier("01");
-        taxRelifInfo.setIdentifyNumber("14092519990322002X");
-        taxRelifInfo.setTaxRegistryNumber("911401005929792152");
-        taxRelifInfo.setCompleteKerbMass("1.539");
-        return taxRelifInfo;
-    }
-
-
-    /**
-     * 构建减税信息对象
-     *
-     * @param quoteVo      报价实体
-     * @param carOwnerInfo 车主信息
-     * @param comCode      保险公司代码
-     * @param headers      请求头
-     * @return ZiJinCrawlerQuotationRequest.TaxRelifInfo
-     */
-    private ZiJinCrawlerQuotationRequest.TaxRelifInfo buildTaxRelifInfo(QuoteVo quoteVo, ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo, String comCode, HttpHeaders headers) {
-        ZiJinCrawlerQuotationRequest.TaxRelifInfo taxRelifInfo = new ZiJinCrawlerQuotationRequest.TaxRelifInfo();
-
-        // 只有投保交强险时才构建完整的税务信息
-        // 交强险riskCode为"0507"
-        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
-
-        // 获取税务登记证号
-        String taxRegistryNumber = "";
-        try {
-            ZiJinCrawlerGetTaxRegistryNumberResponse taxResponse = ziJinCrawlerRequestComponent.getTaxRegistryNumber(comCode, headers);
-            if (taxResponse != null && StringUtils.hasLength(taxResponse.getData())) {
-                taxRegistryNumber = taxResponse.getData();
-            }
-        } catch (Exception e) {
-            log.error("获取税务登记证号失败: {}", e.getMessage());
-        }
-
-        // 设置税务信息
-        taxRelifInfo.setTaxRelifFlag(quoteVo.getVehicleAndVesselTaxVo().getTaxRelifFlag());// 1 正常缴税 2 免税 3 减税 4 已完税 5 不征
-
-        if (carOwnerInfo != null) {
-            taxRelifInfo.setTaxpayerName(carOwnerInfo.getCarOwner());// 纳税人姓名
-            taxRelifInfo.setTaxpayerIdentifier(carOwnerInfo.getOwnerIdentifyType());// 纳税人标识(证件类型)
-            taxRelifInfo.setIdentifyNumber(carOwnerInfo.getOwnerIdentifyNumber());// 证件号码
-        }
-
-        taxRelifInfo.setTaxRegistryNumber(taxRegistryNumber);// 税务登记证号
-
-        // 整备质量(公斤转吨)
-        if (carInfoVo != null && StringUtils.hasLength(carInfoVo.getCompleteKerbMass())) {
-            String completeKerbMassTon = carInfoVo.completeKerbMassToTonCount();
-            taxRelifInfo.setCompleteKerbMass(completeKerbMassTon);
-        }
-
-        return taxRelifInfo;
-    }
-
-
-    /**
-     * 构建险种列表
-     * 根据交强险和商业险的险种信息动态构建险种列表
-     *
-     * @param quoteVo     报价实体
-     * @param actualValue 车辆实际价值
-     * @return List<ZiJinCrawlerQuotationRequest.ItemKindList>
-     */
-    private List<ZiJinCrawlerQuotationRequest.ItemKindList> buildItemKindList(QuoteVo quoteVo, Double actualValue) {
-        List<ZiJinCrawlerQuotationRequest.ItemKindList> itemKindList = new ArrayList<>();
-
-        // 交通事故强制责任险  1. 检查是否有交强险(riskCode='0507')
-        if (quoteVo.getCiRiskInfoVo() != null) {
-            ZiJinCrawlerQuotationRequest.ItemKindList ciItem = new ZiJinCrawlerQuotationRequest.ItemKindList();
-            ciItem.setAmount("200000");// 这个需要查一下是哪的数据
-            ciItem.setKindCode(MotorVehicleInsuranceEnum.MVI_BZ.getCode());
-            ciItem.setKindName(MotorVehicleInsuranceEnum.MVI_BZ.getName());
-            ciItem.setRiskCode(RiskCodeEnum.TRAFFIC_CODE);
-            itemKindList.add(ciItem);
-        }
-
-        // 机动车第三者责任保险、附加医保外用药责任险、道路救援服务特约条款
-        // 根据商业险险种列表构建
-        if (quoteVo.getBiRiskInfoVo() != null && CollectionUtils.isNotEmpty(quoteVo.getKindInfoVo())) {
-            for (KindInfoVo kindItem : quoteVo.getKindInfoVo()) {
-                ZiJinCrawlerQuotationRequest.ItemKindList item = new ZiJinCrawlerQuotationRequest.ItemKindList();
-                item.setKindCode(kindItem.getKindCode());
-                item.setKindName(kindItem.getKindName());
-                item.setRiskCode(RiskCodeEnum.BUSINESS_CODE);
-                item.setAmount(kindItem.getAmount());
-                item.setUnitAmount(kindItem.getUnitAmount());
-                item.setServiceTimes(kindItem.getServiceTimes());
-                item.setQuantity(ObjectUtils.isEmpty(kindItem.getQuantity()) ? null : Integer.parseInt(kindItem.getQuantity()));
-                itemKindList.add(item);
-            }
-        }
-
-        return itemKindList;
-    }
-
-    /**
-     * 构建附加保单信息列表
-     *
-     * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
-     */
-    /**
-     * 构建附加保单信息列表(驾乘险)
-     * 参数来源对照Python get_fcx_main方法:
-     * 根据驾乘险列表动态构建附加保单信息
-     * 目前只支持 rideRiskCode == "0733"(紫金驾驶人意外伤害保险)
-     *
-     * @param quoteVo 报价实体
-     * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
-     */
-    private List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> buildCarPolicySubInfoList(QuoteVo quoteVo) {
-        List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> carPolicySubInfoList = new ArrayList<>();
-
-        if (CollectionUtils.isEmpty(quoteVo.getAccidentalDrivings())) {
-            return carPolicySubInfoList;
-        }
-
-        for (AccidentalDrivingVo accidentalDriving : quoteVo.getAccidentalDrivings()) {
-            ZiJinCrawlerQuotationRequest.CarPolicySubInfoList carPolicySubInfo = new ZiJinCrawlerQuotationRequest.CarPolicySubInfoList();
-            carPolicySubInfo.setInsureGradeNo(accidentalDriving.getProductCode());
-            carPolicySubInfo.setProductCode(accidentalDriving.getProductCode());
-            carPolicySubInfo.setPlanName(accidentalDriving.getProductName());
-            carPolicySubInfo.setRiskCode(accidentalDriving.getRiskCode());
-            carPolicySubInfo.setRiskName(accidentalDriving.getProductName());
-            carPolicySubInfo.setSumAmount(ObjectUtils.isEmpty(accidentalDriving.getSumAmount()) ? 0 : (int) Double.parseDouble(accidentalDriving.getSumAmount()));
-            carPolicySubInfo.setQuantity(accidentalDriving.getQuantity() == 0 ? "0" : String.valueOf(accidentalDriving.getQuantity()));
-            carPolicySubInfo.setIsUseInsured("1");
-            carPolicySubInfo.setSumPremium(ObjectUtils.isEmpty(accidentalDriving.getPremium()) ? 0 : (int) Double.parseDouble(accidentalDriving.getPremium()));
-            carPolicySubInfoList.add(carPolicySubInfo);
-        }
-        return carPolicySubInfoList;
-    }
-
-    /**
-     * 构建车辆信息对象
-     *
-     * @return ZiJinCrawlerQuotationRequest.VehicleInfo
-     */
-    /**
-     * 构建车辆信息对象
-     * 参数来源对照Python get_car_info_main方法:
-     * - carInfoVo: 车辆基本信息
-     * - actualValue: 车辆实际价值(从API获取)
-     *
-     * @param quoteVo     报价实体
-     * @param actualValue 车辆实际价值
-     * @return VehicleInfo
-     */
-    private ZiJinCrawlerQuotationRequest.VehicleInfo buildVehicleInfo(QuoteVo quoteVo, Double actualValue, String modelCode, String iacVehicleCode, ZiJinCrawlerCarResponse ziJinCrawlerCarResponse) {
-        log.info("quoteVo参数的值:{}", JSON.toJSONString(quoteVo));
-        ZiJinCrawlerQuotationRequest.VehicleInfo vehicleInfo = new ZiJinCrawlerQuotationRequest.VehicleInfo();
-        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
-
-        if (carInfoVo == null) {
-            return vehicleInfo;
-        }
-
-        // 基础车辆信息
-        if (actualValue != null) {
-            vehicleInfo.setActualValue(actualValue);
-            vehicleInfo.setAgreeActualValue(actualValue);
-        }
-        vehicleInfo.setBrandName(carInfoVo.getBrandName());
-        vehicleInfo.setColorCode("02"); // 默认黑色
-
-        // 车辆种类代码转换(A0->客车, A1->货车等)
-        vehicleInfo.setCarKindCode(StringUtils.hasLength(carInfoVo.getCarKindCode()) ? carInfoVo.getCarKindCode() : "A0");
-
-        vehicleInfo.setCarKindDetailId(carInfoVo.getCarKindDetailIdCode());
-
-        // 交强险过户标志
-        vehicleInfo.setCarLoanFlag(carInfoVo.isTransfer() ? "1" : "0");
-
-        // 购车发票日期(使用注册日期)
-        vehicleInfo.setCertificateDate(carInfoVo.getRegisterDate());
-
-        // 过户标志
-        vehicleInfo.setChgOwnerFlag(carInfoVo.isTransfer() ? "1" : "0");
-
-        // 整备质量
-        vehicleInfo.setCompletekerbmass(ObjectUtils.isEmpty(carInfoVo.getCompleteKerbMass()) ? 0 : Integer.parseInt(carInfoVo.getCompleteKerbMass()));
-
-        // 外地车标志(默认0)
-        vehicleInfo.setEcdemicVehicleFlag("0");
-
-        vehicleInfo.setEngineNo(carInfoVo.getEngineNo());
-
-        // 日期相关
-        vehicleInfo.setEnrollDate(carInfoVo.getRegisterDate());
-        vehicleInfo.setUpdateEnrollDate(carInfoVo.getRegisterDate());
-        vehicleInfo.setIssueDate(carInfoVo.getIssueDate());
-
-        // 过户日期处理
-        if (carInfoVo.isTransfer()) {
-            vehicleInfo.setMakeDate(carInfoVo.getTransferDate());
-            vehicleInfo.setMakeDateJQ(carInfoVo.getTransferDate());
-        }
-
-        // 车辆技术参数
-        if (StringUtils.hasLength(carInfoVo.getDisplacement())) {
-            // displacement是升(L),需要转换为毫升(ml)
-            double displacement = Double.parseDouble(carInfoVo.getDisplacement());
-            vehicleInfo.setExhaustCapacity((int) (displacement * 1000));
-        }
-
-        // 能源类型
-        vehicleInfo.setFuelType(carInfoVo.getEnergyTypeCode());
-        vehicleInfo.setFuelTypeJY(ObjectUtils.isEmpty(carInfoVo.getModelEnergyType()) ? ziJinCrawlerCarResponse.getVehicleModelInfoList().get(0).getPowerTypeCode() : carInfoVo.getModelEnergyType());
-
-        // 新能源标志, 0-燃油,1-新能源
-        // carInfoVo.isNewEnergyMark() 这个字段前端没传无法判断
-        vehicleInfo.setNewEnergyFlag(EnergyTypeCode.ENERGY_TYPE_CODE_0.getCode().equals(carInfoVo.getEnergyTypeCode()) ? "0" : "1");
-
-        vehicleInfo.setPower(carInfoVo.getPowerScale());
-        vehicleInfo.setModelEnergyType(ObjectUtils.isEmpty(carInfoVo.getModelEnergyType()) ? ziJinCrawlerCarResponse.getVehicleModelInfoList().get(0).getPowerTypeCode() : carInfoVo.getModelEnergyType());
-
-        // 牌照和车辆识别
-        vehicleInfo.setLicenseColorCode(StringUtils.hasLength(carInfoVo.getLicenseColorCode()) ? carInfoVo.getLicenseColorCode() : "01");
-        // 经测试:燃油和新能源都是02
-        if (StringUtils.hasLength(carInfoVo.getLicenseKindCode()) && (LicenseKindCode.L02.getCode().equals(carInfoVo.getLicenseKindCode()) || LicenseKindCode.L08.getCode().equals(carInfoVo.getLicenseKindCode()))) {
-            vehicleInfo.setLicenseKindCode("02");
-        } else {
-            vehicleInfo.setLicenseKindCode(carInfoVo.getLicenseKindCode());
-        }
-        vehicleInfo.setLicenseNo(carInfoVo.getLicenseNo());
-
-        // 贷款车标志
-        vehicleInfo.setLoanVehicleFlag(carInfoVo.isLoanStatus() ? "1" : "0");
-
-        // 车型代码
-        vehicleInfo.setModelCode(modelCode);
-
-        // 是否新车未上牌
-        vehicleInfo.setNoLicenseFlag("0".equals(carInfoVo.getIsRegistered()) ? "0" : "1");
-
-        vehicleInfo.setVehicleId("1");
-        vehicleInfo.setVinNo(carInfoVo.getVinNo());
-
-        // 车辆分类和用途
-        vehicleInfo.setSeatCount(ObjectUtils.isEmpty(carInfoVo.getSeatCount()) ? 0 : Integer.parseInt(carInfoVo.getSeatCount()));
-
-        // 使用性质代码
-        vehicleInfo.setUseNatureCode("02".equals(quoteVo.getCarInfoVo().getCarNatureCode()) ? "85" : quoteVo.getCarInfoVo().getCarNatureCode());
-        vehicleInfo.setOriCarKindName(carInfoVo.getCarTypeCode());
-
-        // 平台车辆代码
-        vehicleInfo.setPlatVehicleCode(iacVehicleCode);
-
-        // 车型唯一ID
-        vehicleInfo.setVehicleStyleUniqueId("");
-
-        // 价格和商业信息
-        vehicleInfo.setPurchasePrice(carInfoVo.getPurchasePrice());
-        vehicleInfo.setSale4SFlag("0");
-        vehicleInfo.setOriPurchasePrice(carInfoVo.getPurchasePrice());
-        vehicleInfo.setIsInvokeJingYou("1");
-
-        // 型号名称
-        vehicleInfo.setPrintVehicleModelName(carInfoVo.getBrandName());
-        vehicleInfo.setAliasName(carInfoVo.getBrandName());
-        vehicleInfo.setOriBrandName(carInfoVo.getBrandName());
-        vehicleInfo.setOriModelName(carInfoVo.getBrandName());
-        vehicleInfo.setPrintModelName(carInfoVo.getBrandName());
-
-        return vehicleInfo;
-    }
-
-
-    /**
-     * 构建盈利数据列表
-     *
-     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
-     */
-//    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList() {
-//        List<ZiJinCrawlerQuotationRequest.ProfitDataList> profitDataList = new ArrayList<>();
-//
-//        // 第一个盈利数据项
-//        ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
-//        profitData1.setProfitCode("C31");
-//        profitData1.setProfitRate("1.05");
-//        profitDataList.add(profitData1);
-//
-//        // 第二个盈利数据项
-//        ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
-//        profitData2.setProfitCode("C32");
-//        profitData2.setProfitRate("1.000000");
-//        profitDataList.add(profitData2);
-//        return profitDataList;
-//    }
-
-
-    /**
-     * 构建盈利数据列表
-     *
-     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
-     */
-    /**
-     * 构建盈利数据列表
-     * 参数来源对照Python代码:
-     * - coefficient: 自主定价系数,从 otherInfo 获取
-     * 只有当 coefficient 不为空且大于0时,才构建盈利数据列表
-     *
-     * @param quoteVo 报价实体
-     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
-     */
-    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList(QuoteVo quoteVo) {
-        List<ZiJinCrawlerQuotationRequest.ProfitDataList> profitDataList = new ArrayList<>();
-
-        // 获取自主定价系数
-        String coefficient = null;
-        if (quoteVo.getOtherInfo() != null) {
-            coefficient = quoteVo.getOtherInfo().getCoefficient();
-        }
-
-        // 只有当 coefficient 不为空且大于0时,才构建盈利数据列表
-        if (StringUtils.hasLength(coefficient)) {
-            try {
-                double coefficientValue = Double.parseDouble(coefficient);
-                if (coefficientValue > 0) {
-                    // 第一个盈利数据项 - 自主定价系数
-                    ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
-                    profitData1.setProfitCode("C31");
-                    profitData1.setProfitRate(coefficient);
-                    profitDataList.add(profitData1);
-
-                    // 第二个盈利数据项 - 固定值
-                    ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
-                    profitData2.setProfitCode("C32");
-                    profitData2.setProfitRate("1.000000");
-                    profitDataList.add(profitData2);
-                }
-            } catch (NumberFormatException e) {
-                // coefficient 不是有效数字,不构建盈利数据列表
-            }
-        }
-
-        return profitDataList;
-    }
 
     /**
      * 截取重复投保终保日期的正则表达式