Procházet zdrojové kódy

Merge remote-tracking branch 'origin/dev_jzg_lipf_v20260622' into dev_jzg_lipf_v20260622

jiakai před 1 měsícem
rodič
revize
2bb5f65175
34 změnil soubory, kde provedl 3073 přidání a 481 odebrání
  1. 2 0
      commons/src/main/java/com/jzg/commons/entity/costs/vo/ValidateSchemeRuleVo.java
  2. 8 6
      commons/src/main/java/com/jzg/commons/entity/po/PtlAgreementUndwrtRulesDictLabal.java
  3. 1 0
      tenant/costsorrule/src/main/java/com/jzg/costsorrule/controller/RuleController.java
  4. 81 177
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/GsCrawlerLoginComponent.java
  5. 183 150
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/GsCrawlerRequestComponent.java
  6. 159 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/enums/RequestUrl.java
  7. 2 2
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/CreatOrderRequest.java
  8. 28 4
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/GuoShouCrawlerQuoteResultsVoBuild.java
  9. 4 4
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/InsuranceApplicationEntity.java
  10. 19 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/ProductUnderwriteRequest.java
  11. 5 4
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/SubmitInsuranceInformationRequest.java
  12. 701 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/ApiResponse.java
  13. 349 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/GetUserInfoResponse.java
  14. 143 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/LoginInfoResponse.java
  15. 67 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/RedisResultDTO.java
  16. 3 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/UserInfoResponse.java
  17. 33 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/properties/GuoShouCrawlerProperties.java
  18. 592 123
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/service/Impl/GuoshouCrawlerRequestImpl.java
  19. 452 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/util/ModularDataProcessor.java
  20. 54 0
      tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/util/RsaUtils.java
  21. 1 1
      tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestBuilder.java
  22. 2 2
      tenant/insurance/quotation-renbaonew/src/main/java/com/jzg/quotation/renbaonew/crawler/service/impl/RenBaoNewCrawlerRequestImpl.java
  23. 17 2
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java
  24. 5 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/api/constant/TransCode.java
  25. 24 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/build/ZmCrawlerQuoteResultVoBuild.java
  26. 9 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/component/ZmCrawlerRequestComponent.java
  27. 2 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/constant/enums/RequestUrl.java
  28. 32 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/entity/Request/ZmCrawlerSearchCommonViewTraceRequest.java
  29. 41 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/entity/Response/ZmCrawlerSearchCommonViewTraceResponse.java
  30. 17 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/service/Impl/ZhongMeiCrawlerRequestImpl.java
  31. 3 3
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostServiceImpl.java
  32. 16 2
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementDispatchServiceImpl.java
  33. 12 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementUndwrtRulesAttrServiceImpl.java
  34. 6 1
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java

+ 2 - 0
commons/src/main/java/com/jzg/commons/entity/costs/vo/ValidateSchemeRuleVo.java

@@ -64,6 +64,8 @@ public class ValidateSchemeRuleVo {
         this.quoteVo.getCarInfoVo().setCarKindCode(
                 vehicleUseCode.stream().filter(x->x.getValue().equals(this.quoteVo.getCarInfoVo().getCarKindCode())).findFirst().get().getValue()
         );
+
+        this.quoteVo.setProductCode(schemeRuleFilterVo.getProductId());
         System.out.printf(JSONObject.toJSONString(this.quoteVo));
     }
 }

+ 8 - 6
commons/src/main/java/com/jzg/commons/entity/po/PtlAgreementUndwrtRulesDictLabal.java

@@ -21,12 +21,14 @@ public class PtlAgreementUndwrtRulesDictLabal {
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
-    public String getIdStr(){
-        if(id == null){
-            return StringUtils.EMPTY;
-        }
-        return Objects.toString(this.id);
-    }
+    @TableField(exist = false)
+    private String idStr;
+//    public String getIdStr(){
+//        if(id == null){
+//            return StringUtils.EMPTY;
+//        }
+//        return Objects.toString(this.id);
+//    }
 
     @TableField(value = "parent_id")
     private Integer parentId;

+ 1 - 0
tenant/costsorrule/src/main/java/com/jzg/costsorrule/controller/RuleController.java

@@ -95,6 +95,7 @@ public class RuleController extends BaseController {
 
         //将传入的对象转换成Map对象用于校验因子
         ruleService.traverseJsonObject(JSON.parseObject(JSON.toJSONString(validateDispatchRuleVo.getQuoteVo())),attrMap);
+        attrMap.put("insruanceproduct",validateDispatchRuleVo.getQuoteVo().getProductCode());
         List<PtlAgreementUndwrtRulesAttr> rulesAttrs = ptlAgreementUndwrtRulesAttrMapper.selectList(new LambdaQueryWrapper<>());
 
         //转换对象 将List<PtlSchemeRulesAttrLink>转换为List<RuleAttrLinkVo>

+ 81 - 177
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/GsCrawlerLoginComponent.java

@@ -1,28 +1,27 @@
 package com.jzg.quotation.guoshou.crawler.component;
 
 import cn.hutool.core.util.ReUtil;
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
+import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.component.RequestComponent;
+import com.jzg.quotation.guoshou.crawler.component.enums.RequestUrl;
 import com.jzg.quotation.guoshou.crawler.constant.GsConstants;
+import com.jzg.quotation.guoshou.crawler.entity.response.*;
+import com.jzg.quotation.guoshou.crawler.properties.GuoShouCrawlerProperties;
+import com.jzg.quotation.guoshou.crawler.util.RsaUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
 
-import java.io.IOException;
 import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 @Slf4j
@@ -30,150 +29,69 @@ import java.util.concurrent.TimeUnit;
 @RequiredArgsConstructor
 
 public class GsCrawlerLoginComponent {
-    private String uname;
-    private String pwd;
-    private String token;
-    private String tkMessage;
-    private String bid;
-    private String userId;
-    private String phone;
-    private String identifyNumber;
-    private String userCode;
-    private String h5Token;
-    private String gstcItem;
-    private String businessOffice;
-    private String provincialCom;
-    private String h5Url;
-    private String viewtoken;
 
+    private final GsCrawlerRequestComponent gsCrawlerRequestComponent;
+    private final GuoShouCrawlerProperties guoShouCrawlerProperties;
     private final StringRedisTemplate redisTemplate;
     private final RequestComponent requestComponent;
+    private final int MAXIMUM_LOGIN = 3;
 
-    /**
-     * 获取token(硬编码部分+接口请求部分)
-     */
-    public void getToken() {
-        // 硬编码token映射
-        Map<String, String> tokenMap = new HashMap<String, String>() {{
-            put("142230198812181723", "9ed09b3d3cf84abf85a63582a5a1ba40");
-            put("140702199001207189", "8aac4ed3e4c44110b37e9bd9d62aaf9c");
-            put("140123198503130219", "20b1e8e8e05347d78afbd46532871a3d");
-        }};
 
-        // 优先使用硬编码token
-        if (tokenMap.containsKey(uname)) {
-            this.token = tokenMap.get(uname);
-            return;
+    public UserInfoResponse.UserData getLoginInfo(AttributionInformationVo attributionInformationVo) {
+        String username = attributionInformationVo.getConfigInfo().get("username");
+        for (int retryCount = 0; retryCount < MAXIMUM_LOGIN; retryCount++) {
+            try {
+                RedisResultDTO redisValue = getRedisKey(attributionInformationVo);
+                UserInfoResponse loginInfo = gsCrawlerRequestComponent.getLoginInfo(redisValue);
+                // 正常返回
+                if (loginInfo != null && "200".equals(loginInfo.getStatus())) {
+                    loginInfo.getData().setRedisResultDTO(redisValue);
+                    redisTemplate.opsForValue().set(GsConstants.GS_REDIS_LOGIN_KEY + username,JSONObject.toJSONString(redisValue),GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
+                    return loginInfo.getData();
+                }
+                // 登录失败:清理缓存
+                log.warn("登录信息获取失败,状态异常,username:{},msg:{},重试次数:{}",
+                        username,
+                        loginInfo == null ? "响应为空" : loginInfo.getMsg(),
+                        retryCount + 1);
+                redisTemplate.delete(GsConstants.GS_REDIS_LOGIN_KEY + username);
+            } catch (Exception e) {
+                log.error("调用登录接口出现异常,username:{}", username, e);
+            }
         }
+        // 达到最大重试次数
+        log.error("登录信息获取失败,已达到最大重试次数:{},username:{}", MAXIMUM_LOGIN, username);
+        throw new SystemException("登录信息获取失败,已达到最大重试次数");
+    }
 
-        // 硬编码没有则调用接口
-
-        // 设置请求头
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("Content-Type", GsConstants.CONTENT_TYPE);
-        headers.add("User-Agent", "Android 2.3.7");
-        // 构造请求体
-        JSONObject data = new JSONObject();
-        data.put("password", pwd);
-        data.put("phone", uname);
-        data.put("User-Agent", "Android 2.3.7");
-        try {
-            ResponseEntity<JSONObject> responseEntity = requestComponent.post(GsConstants.CHECK_PASSWORD_URL, JSONObject.toJSONString(data), JSONObject.class, headers);
-            JSONObject body = responseEntity.getBody();
-
-            // 原Python代码中这部分逻辑被注释,这里保留结构
-            /*
-            if ("200".equals(resJson.getString("status"))) {
-                // 获取Set-Cookie(原代码逻辑)
-                this.token = response.getFirstHeader("Set-Cookie").getValue();
-            } else {
-                this.tkMessage = resJson.getString("message");
-            }
-            */
-        } catch (Exception e) {
-            e.printStackTrace();
+    public RedisResultDTO getRedisKey(AttributionInformationVo attributionInformationVo) {
+        String username = attributionInformationVo.getConfigInfo().get("username");
+        RedisResultDTO value = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + username),RedisResultDTO.class);
+        if (Objects.isNull(value)) {
+            return login(attributionInformationVo);
         }
+        return value;
     }
 
+
     /**
      * 获取用户ID等基础信息
      */
-    public void getUserId() {
-        if (token == null || token.isEmpty()) {
-            return;
-        }
-        CloseableHttpClient client = HttpClients.createDefault();
-        HttpGet get = new HttpGet(GsConstants.USER_INFO_URL);
-        // 设置请求头
-        get.setHeader("token", token);
-        get.setHeader("Host", "messh.chinalife-p.com.cn");
-        get.setHeader("User-Agent", "okhttp/4.9.0");
-        get.setHeader("Content-Type", GsConstants.CONTENT_TYPE);
-        get.setHeader("If-Modified-Since", "Mon, 03 Mar 2025 02:55:57 GMT");
-        try {
-            HttpResponse response = client.execute(get);
-            String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
-            JSONObject resJson = JSON.parseObject(result);
-            if (!"200".equals(resJson.getString("status"))){
-                throw new RuntimeException("获取用户信息失败");
-            }
-            JSONObject data = resJson.getJSONObject("data");
-            this.bid = data.getString("provinceBid");
-            this.userId = data.getString("userId");
-            this.phone = data.getString("phone");
-            this.identifyNumber = data.getString("userCode");
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                client.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
+    public GetUserInfoResponse getUserId(HttpHeaders headers) {
+        return requestComponent.get(RequestUrl.USER_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()), new LinkedMultiValueMap<>(), null, GetUserInfoResponse.class, headers);
     }
 
     /**
      * 获取用户编码等H5链接相关信息
      */
-    public void getUserCode() {
-        if (token == null || token.isEmpty()) {
-            return;
-        }
-        CloseableHttpClient client = HttpClients.createDefault();
-        HttpGet get = new HttpGet(GsConstants.MY_STORE_URL);
-        // 设置请求头
-        get.setHeader("token", token);
-        get.setHeader("AndroidVersion", "1.1.108");
-        get.setHeader("Host", "messh.chinalife-p.com.cn");
-        get.setHeader("User-Agent", "okhttp/4.9.0");
-        get.setHeader("If-Modified-Since", "Thu, 04 Jul 2024 09:35:54 GMT");
-        try {
-            HttpResponse response = client.execute(get);
-            String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
-            log.info("result:{}", result);
-            JSONObject resJson = JSON.parseObject(result);
-            this.h5Url = resJson.getJSONObject("data").getString("jumpLink");
-            log.info("H5链接:{}", h5Url);
-            // 正则提取参数(使用hutool的ReUtil简化正则操作)
-            this.viewtoken = ReUtil.getGroup1("token=(.+)", h5Url);
-            this.userCode = ReUtil.getGroup1("userCode=(.*?)&", h5Url);
-            this.gstcItem = ReUtil.getGroup1("gstcItem=(.*?)&", h5Url);
-        } catch (IOException e) {
-            e.printStackTrace();
-        } finally {
-            try {
-                client.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
+    public ApiResponse getUserCode(HttpHeaders headers) {
+        return requestComponent.get(RequestUrl.MY_STORE_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),new LinkedMultiValueMap<>(),"",ApiResponse.class,headers);
     }
 
     /**
      * 获取H5 Token
      */
-    public void getH5Token() {
+    public String getH5Token(String bid) {
         // 设置请求头
         HttpHeaders headers = new HttpHeaders();
         headers.add("Content-Type", GsConstants.CONTENT_TYPE);
@@ -187,21 +105,21 @@ public class GsCrawlerLoginComponent {
         data.put("bid", "");
 
         try {
-            ResponseEntity<JSONObject> responseEntity = requestComponent.post(GsConstants.GET_TOKEN_URL, JSONObject.toJSONString(data), JSONObject.class, headers);
+            headers.set("secretParameter",RsaUtils.generateSecretParameter(data));
+            ResponseEntity<JSONObject> responseEntity = requestComponent.post(RequestUrl.GET_TOKEN_URL.getRequestUrl(guoShouCrawlerProperties.getTokenUrl()),data, JSONObject.class, headers);
             JSONObject body = responseEntity.getBody();
-            this.h5Token = body.getJSONObject("data").getString("token");
+            return  body.getJSONObject("data").getString("token");
         } catch (Exception e) {
             e.printStackTrace();
         }
+        return "";
     }
 
     /**
      * 获取营业网点等信息
      */
-    public void getBusinessOffice() {
-        if (h5Token == null || h5Token.isEmpty() || userCode == null || userCode.isEmpty()) {
-            return;
-        }
+    public LoginInfoResponse getBusinessOffice(String h5Token,String bid,String userCode,String viewtoken) {
+
         // 设置请求头
         HttpHeaders headers = new HttpHeaders();
         headers.add("User-Agent", GsConstants.USER_AGENT);
@@ -214,40 +132,39 @@ public class GsCrawlerLoginComponent {
         data.put("systemSource", "gstc");
         data.put("salesGethdbyhpFlag", "1");
         data.put("token", viewtoken);
-        try {
-            ResponseEntity<JSONObject> responseEntity = requestComponent.post(GsConstants.GET_LOGIN_INFO_URL, JSONObject.toJSONString(data), JSONObject.class, headers);
-            JSONObject jsonObject = responseEntity.getBody().getJSONObject("data");
-            this.businessOffice = jsonObject.getString("userDepartment");
-            this.userId = jsonObject.getString("userCode");
-            this.provincialCom = jsonObject.getString("provincialCom");
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        ResponseEntity<LoginInfoResponse> responseEntity = requestComponent.post(RequestUrl.GET_LOGIN_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()), JSONObject.toJSONString(data), LoginInfoResponse.class, headers);
+        return responseEntity.getBody();
     }
 
     /**
      * @return 结果Map或错误信息
      */
-    public void login(AttributionInformationVo attributionInformationVo) {
+    public RedisResultDTO login(AttributionInformationVo attributionInformationVo) {
         try {
-            this.uname = attributionInformationVo.getConfigInfo().get("username");
-            this.token = attributionInformationVo.getConfigInfo().get("token");
-            if (token != null && !token.isEmpty()) {
-                this.getUserId();
-                this.getUserCode();
-                this.getH5Token();
-                this.getBusinessOffice();
-
-                Map<String, String> result = new HashMap<>();
-                result.put("token", h5Token);
-                result.put("userCode", userCode);
-                result.put("bid", bid);
-                result.put("gstcItem", URLDecoder.decode(gstcItem, StandardCharsets.UTF_8));
-                result.put("businessOffice", businessOffice);
-                result.put("userID", userId);
-                result.put("H5URL", this.h5Url);
-                result.put("viewtoken", viewtoken);
-                redisTemplate.opsForValue().set(GsConstants.GS_REDIS_LOGIN_KEY +this.uname,JSONObject.toJSONString(result),GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
+            String uname = attributionInformationVo.getConfigInfo().get("username");
+            String token = attributionInformationVo.getConfigInfo().get("token");
+            if (StringUtils.isNotEmpty(token)) {
+                HttpHeaders httpHeaders = new HttpHeaders();
+                httpHeaders.set("token", token);
+                httpHeaders.set("Host", "messh.chinalife-p.com.cn");
+                httpHeaders.set("User-Agent", "okhttp/4.9.0");
+                httpHeaders.set("Content-Type", GsConstants.CONTENT_TYPE);
+                httpHeaders.set("If-Modified-Since", "Mon, 03 Mar 2025 02:55:57 GMT");
+                GetUserInfoResponse userInfoResponse = getUserId(httpHeaders);
+                GetUserInfoResponse.UserData userData = userInfoResponse.getData();
+                String bid = userData.getProvinceBid();
+                String userId = userData.getUserId();
+                String phone = userData.getPhone();
+                ApiResponse code = getUserCode(httpHeaders);
+                ApiResponse.StoreData data = code.getData();
+                String h5Url = data.getJumpLink();
+                // 正则提取参数(使用hutool的ReUtil简化正则操作)
+                String viewtoken = ReUtil.getGroup1("token=(.+)", h5Url);
+                String userCode = ReUtil.getGroup1("userCode=(.*?)&", h5Url);
+                String gstcItem = ReUtil.getGroup1("gstcItem=(.*?)&", h5Url);
+                String h5Token = getH5Token(bid);
+                LoginInfoResponse businessOffice = getBusinessOffice(h5Token, bid, userCode, viewtoken);
+                return new RedisResultDTO().build(h5Token, userCode, bid, gstcItem, businessOffice.getData().getUserDepartment(), businessOffice.getData().getUserCode(), h5Url, viewtoken);
             } else {
                 throw new RuntimeException("登录失败");
             }
@@ -257,18 +174,5 @@ public class GsCrawlerLoginComponent {
         }
     }
 
-    /**
-     * 获取H5 Token的快捷方法
-     * @return H5 Token
-     */
-//    public String getUrl() {
-//        this.getToken();
-//        if (token != null && !token.isEmpty()) {
-//            this.getUserId();
-//            this.getUserCode();
-//            return h5Token;
-//        }
-//        return null;
-//    }
 
 }

+ 183 - 150
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/GsCrawlerRequestComponent.java

@@ -3,9 +3,11 @@ package com.jzg.quotation.guoshou.crawler.component;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.quotation.commons.component.RequestComponent;
+import com.jzg.quotation.guoshou.crawler.component.enums.RequestUrl;
 import com.jzg.quotation.guoshou.crawler.constant.GsConstants;
 import com.jzg.quotation.guoshou.crawler.entity.request.*;
 import com.jzg.quotation.guoshou.crawler.entity.response.*;
+import com.jzg.quotation.guoshou.crawler.properties.GuoShouCrawlerProperties;
 import com.jzg.quotation.guoshou.crawler.util.RsaUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -30,6 +32,7 @@ import java.util.Objects;
 @RequiredArgsConstructor
 public class GsCrawlerRequestComponent {
 
+    private final GuoShouCrawlerProperties guoShouCrawlerProperties;
     private final RequestComponent requestComponent;
     private final RsaUtils rsaUtils;
 
@@ -48,23 +51,6 @@ public class GsCrawlerRequestComponent {
         return headers;
     }
 
-    /**
-     * 从redis字符串中解析token
-     * @param redisValue redis存储的JSON字符串
-     * @return token
-     */
-    public String getToken(String redisValue) {
-        // 空值保护
-        if (redisValue == null || redisValue.isEmpty()) {
-            throw new IllegalArgumentException("redisValue不能为空");
-        }
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
-        String token = jsonObject.getString("token");
-        if (token == null || token.isEmpty()) {
-            throw new RuntimeException("从redisValue中解析token失败,token为空");
-        }
-        return token;
-    }
 
     /**
      * 通用响应状态检查(JSON对象类型)
@@ -111,7 +97,7 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         ResponseEntity<GsCrawlerCarQueryResponse> responseEntity = requestComponent.post(
-                GsConstants.CAR_INFO_URL,
+                RequestUrl.CAR_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(carQueryRequest),
                 GsCrawlerCarQueryResponse.class,
                 getHeaders(token)
@@ -119,8 +105,6 @@ public class GsCrawlerRequestComponent {
 
         GsCrawlerCarQueryResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "查询车辆信息");
-        log.info("查询车辆信息成功,结果:{}", body);
-
         // 空值保护
         return body.getData() != null ? body.getData().getData() : List.of();
     }
@@ -128,19 +112,13 @@ public class GsCrawlerRequestComponent {
     /**
      * 查询订单号
      * @param insuranceApplicationEntity 请求参数
-     * @param redisValue redis存储的JSON字符串
      * @return 订单号
      */
-    public String queryOrderNo(InsuranceApplicationEntity insuranceApplicationEntity, String redisValue) {
+    public String queryOrderNo(InsuranceApplicationEntity insuranceApplicationEntity, String token) {
         Objects.requireNonNull(insuranceApplicationEntity, "insuranceApplicationEntity不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
-        String token = jsonObject.getString("token");
-        Objects.requireNonNull(token, "从redisValue中解析的token不能为空");
 
         ResponseEntity<RenewalSaveResponse> responseEntity = requestComponent.post(
-                GsConstants.ORDER_ID_URL,
+                RequestUrl.ORDER_ID_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(insuranceApplicationEntity),
                 RenewalSaveResponse.class,
                 getHeaders(token)
@@ -148,7 +126,6 @@ public class GsCrawlerRequestComponent {
 
         RenewalSaveResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "查询订单号");
-        log.info("查询订单号成功,结果:{}", body);
 
         // 空值保护
         return body.getData() != null ? body.getData().getOrderNo() : "";
@@ -165,7 +142,7 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         ResponseEntity<CarInsuranceQueryResponse> responseEntity = requestComponent.post(
-                GsConstants.QUERY_INS_URL,
+                RequestUrl.QUERY_INS_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(informationRequest),
                 CarInsuranceQueryResponse.class,
                 getHeaders(token)
@@ -180,21 +157,19 @@ public class GsCrawlerRequestComponent {
 
     /**
      * 获取绑定信息
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param userCode 用户编码
      * @return 绑定信息列表
      */
-    public List<JSONObject> getBindInfo(String redisValue, String userCode) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public List<JSONObject> getBindInfo(String token, String userCode) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(userCode, "userCode不能为空");
 
         Map<String, Object> bindParam = new HashMap<>();
         bindParam.put("userCode", rsaUtils.encrypt(userCode));
         bindParam.put("systemSource", "gstc");
-
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.BIND_INFO_URL,
+                RequestUrl.BIND_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(bindParam),
                 JSONObject.class,
                 getHeaders(token)
@@ -212,28 +187,25 @@ public class GsCrawlerRequestComponent {
      * @param redisValue redis存储的JSON字符串
      * @return 用户信息响应
      */
-    public UserInfoResponse getLoginInfo(String redisValue) {
+    public UserInfoResponse getLoginInfo(RedisResultDTO redisValue) {
         Objects.requireNonNull(redisValue, "redisValue不能为空");
 
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
         JSONObject data = new JSONObject();
         try {
-            data.put("userCode", URLDecoder.decode(jsonObject.getString("userCode"), StandardCharsets.UTF_8));
+            data.put("userCode",URLDecoder.decode(redisValue.getUserCode(), StandardCharsets.UTF_8));
         } catch (Exception e) {
             log.error("解码userCode失败", e);
             throw new RuntimeException("解码userCode失败", e);
         }
-        data.put("bid", jsonObject.getString("bid"));
+        data.put("bid", redisValue.getBid());
         data.put("systemSource", "gstc");
         data.put("salesGethdbyhpFlag", "1");
-        data.put("token", jsonObject.getString("viewtoken"));
-
-        String token = getToken(redisValue);
+        data.put("token", redisValue.getViewtoken());
         ResponseEntity<UserInfoResponse> responseEntity = requestComponent.post(
-                GsConstants.GET_LOGIN_INFO_URL,
+                RequestUrl.GET_LOGIN_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(data),
                 UserInfoResponse.class,
-                getHeaders(token)
+                getHeaders(redisValue.getToken())
         );
 
         // 空值保护
@@ -249,10 +221,8 @@ public class GsCrawlerRequestComponent {
     public SubmitResponse submitInsuranceInformationRequest(SubmitInsuranceInformationRequest submitInsuranceInformationRequest, String token) {
         Objects.requireNonNull(submitInsuranceInformationRequest, "submitInsuranceInformationRequest不能为空");
         Objects.requireNonNull(token, "token不能为空");
-
-        log.info("提交保险信息请求参数:{}", JSONObject.toJSONString(submitInsuranceInformationRequest));
         ResponseEntity<SubmitResponse> responseEntity = requestComponent.post(
-                GsConstants.SUBMIT_INS_URL,
+                RequestUrl.SUBMIT_INS_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(submitInsuranceInformationRequest),
                 SubmitResponse.class,
                 getHeaders(token)
@@ -278,7 +248,7 @@ public class GsCrawlerRequestComponent {
         headers.add("Connection", "keep-alive");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.ENCRYPTION_CONVERT_URL,
+                RequestUrl.ENCRYPTION_CONVERT_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 JSONObject.toJSONString(jsonObject),
                 JSONObject.class,
                 headers
@@ -305,7 +275,7 @@ public class GsCrawlerRequestComponent {
         jsonObject.put("orderId", orderNo);
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.CAR_CONFIRM_URL,
+                RequestUrl.CAR_CONFIRM_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(jsonObject),
                 JSONObject.class,
                 getHeaders(token)
@@ -328,7 +298,7 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.UPDATE_CAR_INFO_URL,
+                RequestUrl.UPDATE_CAR_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(carInfo),
                 JSONObject.class,
                 getHeaders(token)
@@ -350,7 +320,7 @@ public class GsCrawlerRequestComponent {
 
         try {
             ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                    GsConstants.GET_PLAT_CAR_INFO_URL,
+                    RequestUrl.GET_PLAT_CAR_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                     JSONObject.toJSONString(platCarInfoRequest),
                     JSONObject.class,
                     getHeaders(token)
@@ -383,7 +353,7 @@ public class GsCrawlerRequestComponent {
 
         try {
             ResponseEntity<InsuranceInitResponse> responseEntity = requestComponent.post(
-                    GsConstants.CALCULATION_INITIALIZATION_URL,
+                    RequestUrl.CALCULATION_INITIALIZATION_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                     JSONObject.toJSONString(initializationRequest),
                     InsuranceInitResponse.class,
                     getHeaders(token)
@@ -412,16 +382,13 @@ public class GsCrawlerRequestComponent {
         Objects.requireNonNull(token, "token不能为空");
 
         try {
-            log.info("开始计算保费,请求参数:{}", JSONObject.toJSONString(doCalculateRequest));
             ResponseEntity<PremiumCalculateResponse> responseEntity = requestComponent.post(
-                    GsConstants.CALCULATE_URL,
+                    RequestUrl.CALCULATE_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                     JSONObject.toJSONString(doCalculateRequest),
                     PremiumCalculateResponse.class,
                     getHeaders(token)
             );
-
             PremiumCalculateResponse body = responseEntity.getBody();
-            log.info("保费计算成功,结果:{}", body != null ? JSONObject.toJSONString(body.getData()) : "无数据");
             return Objects.requireNonNull(body, "保费计算响应体为空");
         } catch (Exception e) {
             e.printStackTrace();
@@ -439,18 +406,14 @@ public class GsCrawlerRequestComponent {
     public FeeCalculateResponse.DataDTO creatOrder(String token, JSONObject data) {
         Objects.requireNonNull(token, "token不能为空");
         Objects.requireNonNull(data, "data不能为空");
-
         ResponseEntity<FeeCalculateResponse> responseEntity = requestComponent.post(
-                GsConstants.CREAT_ORDER_URL,
+                RequestUrl.CREAT_ORDER_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(data),
                 FeeCalculateResponse.class,
                 getHeaders(token)
         );
-
         FeeCalculateResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "创建订单");
-        log.info("创建订单成功");
-
         // 空值保护
         return body.getData() != null ? body.getData() : null;
     }
@@ -469,15 +432,13 @@ public class GsCrawlerRequestComponent {
         accidentParam.put("tranNo", orderId);
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.DO_ACCIDENT_RECORD,
+                RequestUrl.DO_ACCIDENT_RECORD.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(accidentParam),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "添加事故记录");
-
         // 空值保护
         JSONObject data = body.getJSONObject("data");
         return data != null ? data : new JSONObject();
@@ -486,71 +447,59 @@ public class GsCrawlerRequestComponent {
     /**
      * 自动生成数据
      * @param generateDataRequest 请求参数
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      */
-    public void doAutoGenerate(GenerateDataRequest generateDataRequest, String redisValue) {
+    public void doAutoGenerate(GenerateDataRequest generateDataRequest, String token) {
         Objects.requireNonNull(generateDataRequest, "generateDataRequest不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
                 GsConstants.DO_AUTO_GENERATE,
                 JSONObject.toJSONString(generateDataRequest),
                 JSONObject.class,
                 getHeaders(token)
         );
-
-        log.info("自动生成数据成功,响应:{}", JSONObject.toJSONString(responseEntity.getBody()));
     }
 
     /**
      * 获取MES订单详情
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param value 请求参数
      * @return 订单详情
      */
-    public JSONObject doMesOrderDetail(String redisValue, JSONObject value) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public JSONObject doMesOrderDetail(String token, JSONObject value) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(value, "value不能为空");
-
         JSONObject detailData = new JSONObject();
         detailData.put("orderNo", value.getString("orderId"));
         detailData.put("structureId", value.getString("structureId"));
         detailData.put("userCode", value.getString("userCode"));
         detailData.put("userLoginType", "1");
         detailData.put("sellCode", null);
-
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.DO_MESORDER_DETAIL,
+                RequestUrl.DO_MESORDER_DETAIL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(detailData),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取MES订单详情");
-        log.info("获取MES订单详情成功,响应:{}", JSONObject.toJSONString(body));
-
         return body;
     }
 
     /**
      * 获取上传状态
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param quote 报价信息
      */
-    public void getUploadSuccess(String redisValue, JSONObject quote) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public void getUploadSuccess(String token, JSONObject quote) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(quote, "quote不能为空");
 
         JSONObject uploadStatusData = new JSONObject();
         uploadStatusData.put("orderNo", quote.getString("orderId"));
         uploadStatusData.put("userCode", quote.getString("userCode"));
-
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.GET_UPLOAD_SUCCESS,
+                RequestUrl.GET_UPLOAD_SUCCESS.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(uploadStatusData),
                 JSONObject.class,
                 getHeaders(token)
@@ -558,68 +507,58 @@ public class GsCrawlerRequestComponent {
 
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取上传状态");
-        log.info("获取上传状态成功,响应:{}", JSONObject.toJSONString(body));
     }
 
     /**
      * 查询日志
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param logData 日志查询参数
      * @return 日志响应
      */
-    public QueryLogResponse doQueryLog(String redisValue, JSONObject logData) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public QueryLogResponse doQueryLog(String token, JSONObject logData) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(logData, "logData不能为空");
-
-        String token = getToken(redisValue);
         ResponseEntity<QueryLogResponse> responseEntity = requestComponent.post(
-                GsConstants.DO_QUERY_LOG,
+                RequestUrl.DO_QUERY_LOG.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(logData),
                 QueryLogResponse.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "查询日志响应体为空");
     }
 
     /**
      * 检查图片
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @param uploadRequest 图片上传请求
      * @return 图片检查响应
      */
-    public CheckImageResponse doCheckImage(String redisValue, ImageUploadRequest uploadRequest) {
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+    public CheckImageResponse doCheckImage(String token, ImageUploadRequest uploadRequest) {
+        Objects.requireNonNull(token, "redisValue不能为空");
         Objects.requireNonNull(uploadRequest, "uploadRequest不能为空");
-
-        String token = getToken(redisValue);
         ResponseEntity<CheckImageResponse> responseEntity = requestComponent.post(
-                GsConstants.CHECK_IMAGES_ALL,
+                RequestUrl.CHECK_IMAGES_ALL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(uploadRequest),
                 CheckImageResponse.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "检查图片响应体为空");
     }
 
     /**
      * 上传图片
      * @param imageBusinessRequest 图片上传请求
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      */
-    public void uploadImages(UploadImagesRequest imageBusinessRequest, String redisValue) {
+    public void uploadImages(UploadImagesRequest imageBusinessRequest, String token) {
         Objects.requireNonNull(imageBusinessRequest, "imageBusinessRequest不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<UploadImageResponse> responseEntity = requestComponent.post(
-                GsConstants.UPLOAD_URL,
-                JSONObject.toJSONString(imageBusinessRequest),
+                RequestUrl.UPLOAD_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
+                imageBusinessRequest,
                 UploadImageResponse.class,
                 getHeaders(token)
         );
-
         UploadImageResponse body = responseEntity.getBody();
         checkCustomResponseStatus(body, "上传图片");
         log.info("上传图片成功");
@@ -628,42 +567,36 @@ public class GsCrawlerRequestComponent {
     /**
      * 完成核保任务
      * @param heBaoData 核保数据
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return 核保响应
      */
-    public JSONObject doCompleteTask(OrderEntity heBaoData, String redisValue) {
+    public JSONObject doCompleteTask(OrderEntity heBaoData, String token) {
         Objects.requireNonNull(heBaoData, "heBaoData不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.HE_BAO_URL,
+                RequestUrl.HE_BAO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(heBaoData),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "完成核保任务响应体为空");
     }
 
     /**
      * 获取认证token
      * @param tokenData token请求数据
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return token响应
      */
-    public JSONObject getTokenUrl(Map<String, Object> tokenData, String redisValue) {
+    public JSONObject getTokenUrl(Map<String, Object> tokenData, String token) {
         Objects.requireNonNull(tokenData, "tokenData不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
-
-        String token = getToken(redisValue);
+        Objects.requireNonNull(token, "redisValue不能为空");
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.GET_AUTH_TOKEN,
+                RequestUrl.GET_AUTH_TOKEN.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 JSONObject.toJSONString(tokenData),
                 JSONObject.class,
                 getHeaders(token)
         );
-
         return Objects.requireNonNull(responseEntity.getBody(), "获取认证token响应体为空");
     }
 
@@ -676,17 +609,16 @@ public class GsCrawlerRequestComponent {
     public ResponseDTO getShareInfo(JSONObject tokenResponse, String redisValue) {
         Objects.requireNonNull(tokenResponse, "tokenResponse不能为空");
         Objects.requireNonNull(redisValue, "redisValue不能为空");
-
         MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
         JSONObject data = tokenResponse.getJSONObject("data");
         Objects.requireNonNull(data, "tokenResponse中的data不能为空");
         formData.set("id", data.getString("id"));
-
-        HttpHeaders headers = getHeaders(getToken(redisValue));
+        //String token = getToken(redisValue);
+        HttpHeaders headers = getHeaders("token");
         headers.add("Content-Type", "application/x-www-form-urlencoded");
 
         ResponseEntity<ResponseDTO> responseEntity = requestComponent.form(
-                GsConstants.GET_SHARE_INFO,
+                RequestUrl.GET_SHARE_INFO.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 formData,
                 ResponseDTO.class,
                 headers
@@ -694,7 +626,6 @@ public class GsCrawlerRequestComponent {
 
         ResponseDTO body = responseEntity.getBody();
         Objects.requireNonNull(body, "获取分享信息响应体为空");
-
         // 特殊状态校验
         if (!"SUCCESS".equals(body.getStatus()) && !"查看成功".equals(body.getMsg())) {
             throw new RuntimeException("获取分享信息失败:" + body.getMsg());
@@ -721,7 +652,7 @@ public class GsCrawlerRequestComponent {
         removeData.put("userLoginType", "1");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.REMOVE_ORDER_URL,
+                RequestUrl.REMOVE_ORDER_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(removeData),
                 JSONObject.class,
                 getHeaders(token)
@@ -749,18 +680,15 @@ public class GsCrawlerRequestComponent {
         data.put("queryWord", "");
         data.put("businessOffice", jsonObject.getString("businessOffice"));
         data.put("authority", "2");
-
-        // 修复原代码bug:请求体应该传data而不是jsonObject
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.GET_FROMCAR_PRODUCTS_URL,
+                RequestUrl.GET_FROMCAR_PRODUCTS_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 JSONObject.toJSONString(data),
                 JSONObject.class,
-                getHeaders(getToken(redisValue))
+                getHeaders("token")
         );
 
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取非车险信息");
-        log.info("获取非车险信息成功,响应:{}", JSONObject.toJSONString(body));
     }
 
     /**
@@ -778,9 +706,8 @@ public class GsCrawlerRequestComponent {
         JSONObject data = new JSONObject();
         data.put("orderId", orderNo);
         data.put("userLoginCode", bindInfo.getString("userCode"));
-
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.SALES_FCBE_LONG_INFO_URL,
+                RequestUrl.SALES_FCBE_LONG_INFO_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(data),
                 JSONObject.class,
                 getHeaders(token)
@@ -788,7 +715,6 @@ public class GsCrawlerRequestComponent {
 
         JSONObject body = responseEntity.getBody();
         checkJsonResponseStatus(body, "获取非车险归属信息");
-
         // 空值保护
         return body.getJSONObject("data") != null ? body.getJSONObject("data") : new JSONObject();
     }
@@ -796,21 +722,20 @@ public class GsCrawlerRequestComponent {
     /**
      * 获取订单详情
      * @param id 订单ID
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return 订单详情
      */
-    public JSONObject getOrderDetail(String id, String redisValue) {
+    public JSONObject getOrderDetail(String id, String token) {
         Objects.requireNonNull(id, "id不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+        Objects.requireNonNull(token, "redisValue不能为空");
 
         MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
         formData.set("id", id);
-
-        HttpHeaders headers = getHeaders(getToken(redisValue));
+        HttpHeaders headers = getHeaders(token);
         headers.add("Content-Type", "application/x-www-form-urlencoded");
 
         ResponseEntity<JSONObject> responseEntity = requestComponent.form(
-                GsConstants.GET_ORDER_DETAIL_URL,
+                RequestUrl.GET_ORDER_DETAIL_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
                 formData,
                 JSONObject.class,
                 headers
@@ -822,16 +747,15 @@ public class GsCrawlerRequestComponent {
     /**
      * 获取MES订单列表
      * @param doMesOrdersRequest 请求参数
-     * @param redisValue redis存储的JSON字符串
+     * @param token redis存储的JSON字符串
      * @return 订单列表
      */
-    public JSONObject doMesOrders(DoMesOrdersRequest doMesOrdersRequest, String redisValue) {
+    public JSONObject doMesOrders(DoMesOrdersRequest doMesOrdersRequest, String token) {
         Objects.requireNonNull(doMesOrdersRequest, "doMesOrdersRequest不能为空");
-        Objects.requireNonNull(redisValue, "redisValue不能为空");
+        Objects.requireNonNull(token, "redisValue不能为空");
 
-        String token = getToken(redisValue);
         ResponseEntity<JSONObject> responseEntity = requestComponent.post(
-                GsConstants.DO_MES_ORDERS_URL,
+                RequestUrl.DO_MES_ORDERS_URL.getRequestUrl(guoShouCrawlerProperties.getQuoteUrl()),
                 JSONObject.toJSONString(doMesOrdersRequest),
                 JSONObject.class,
                 getHeaders(token)
@@ -845,4 +769,113 @@ public class GsCrawlerRequestComponent {
     }
 
 
+    public JSONObject encryptionConvert(MultiValueMap<String, String> formData, String token) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("Connection", "keep-alive");
+        headers.set("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.ENCRYPTIONCONVERT_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                formData,
+                JSONObject.class,
+                headers
+        );
+        JSONObject body = responseEntity.getBody();
+        return body;
+    }
+
+    public JSONObject employeeLogin(MultiValueMap<String, String> data2, String token) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("Connection", "keep-alive");
+        headers.set("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.EMPLOYEELOGIN_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data2,
+                JSONObject.class,
+                headers
+        );
+
+        return responseEntity.getBody();
+    }
+
+    public JSONObject fromCarModelCheck(JSONObject data3, String token) {
+
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.FROMCARMODELCHECK_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data3,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        return responseEntity.getBody();
+    }
+
+    public JSONObject getUnderwritingById( MultiValueMap<String, String> data4, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.GET_UNDERWRITING_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data4,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        log.info("===============",JSONObject.toJSONString(responseEntity));
+        return responseEntity.getBody();
+    }
+
+    public JSONObject underwritingPre(JSONObject nextData, String token,String bid) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("bid",bid);
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.UNDERWRITING_PRE_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                nextData,
+                JSONObject.class,
+                headers
+
+        );
+
+        return responseEntity.getBody();
+    }
+
+    public JSONObject getProductInfoById(MultiValueMap<String, String> data3, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.GET_PRODUCT_INFO_BY_ID_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data3,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        log.info("===============",JSONObject.toJSONString(responseEntity));
+        return responseEntity.getBody();
+    }
+
+    public JSONObject getIndividualVo(MultiValueMap<String, String> data4, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.form(
+                RequestUrl.GET_INDIVIDUAL_VO_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data4,
+                JSONObject.class,
+                getHeaders(token)
+        );
+        log.info("===============",JSONObject.toJSONString(responseEntity));
+        return responseEntity.getBody();
+    }
+
+    public JSONObject findAgentRate(JSONObject data7, String token) {
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.FINDAGENTRATE_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data7,
+                JSONObject.class,
+                getHeaders(token)
+
+        );
+        return responseEntity.getBody();
+    }
+
+    public JSONObject underwritingVariablePremiumVariablePremium(JSONObject data8vo, String token) {
+        HttpHeaders headers = getHeaders(token);
+        headers.add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        ResponseEntity<JSONObject> responseEntity = requestComponent.post(
+                RequestUrl.UNDERWRITINGVARIABLE_PREMIUMVARIABLE_PREMIUM_URL.getRequestUrl(guoShouCrawlerProperties.getBaseUrl()),
+                data8vo,
+                JSONObject.class,
+                headers
+
+        );
+        return responseEntity.getBody();
+    }
 }

+ 159 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/component/enums/RequestUrl.java

@@ -0,0 +1,159 @@
+package com.jzg.quotation.guoshou.crawler.component.enums;
+
+import com.jzg.quotation.commons.standard.CrawlerRequestUrlStandard;
+import lombok.AllArgsConstructor;
+
+
+@AllArgsConstructor
+public enum RequestUrl implements CrawlerRequestUrlStandard {
+
+    // 绑定信息查询
+    BIND_INFO_URL("/mesci/sales/SalesManagerBind/getBindInfo", "获取绑定信息"),
+
+    // 根据车牌号查询订单ID
+    ORDER_ID_URL("/mesci/order/MesOrderInfos/searchBylicensePlateNo", "根据车牌号查询订单信息"),
+
+    // 车辆信息查询
+    CAR_INFO_URL("/mesci/car/MesCarInfo/getVinModePage", "获取VIN车型分页信息"),
+
+    // 密码校验
+    CHECK_PASSWORD_URL("/createver/userService/user/check/password", "校验用户密码"),
+
+    // 用户信息查询
+    USER_INFO_URL("/createver/userService/user/info", "获取用户信息"),
+
+    // 我的门店
+    MY_STORE_URL("/createver/customerService/customer-service/myStore", "获取我的门店信息"),
+
+    // 获取Token
+    GET_TOKEN_URL("/MesBaseUrl/getToken", "获取接口令牌"),
+
+    // 获取登录信息
+    GET_LOGIN_INFO_URL("/mesci/sales/SalesManager/getLoginInfo", "获取登录信息"),
+
+    // JLLX车辆信息
+    JLLX_CAR_INFO_URL("/mesci/car/MesCarInfo/getJllxVinModePage", "获取JLLX VIN车型分页信息"),
+
+    // 提交投保信息
+    SUBMIT_INS_URL("/mesci/order/MesOrderInfos/submitInsuranceInformation", "提交投保信息"),
+
+    // 保费计算
+    CALCULATE_URL("/mesci/order/MesOrderInfos/doCalculate", "执行保费计算"),
+
+    // 查询投保信息
+    QUERY_INS_URL("/mesci/order/MesOrderInfos/getInsuranceInformation", "获取投保信息"),
+
+    // 加密转换
+    ENCRYPTION_CONVERT_URL("/ncisp/gatewayncisp/ncisp/ncisp/login/encryptionConvert", "加密转换"),
+
+    // 车辆确认信息
+    CAR_CONFIRM_URL("/mesci/order/MesCarInfo/getCarConfirmInfoForFrontByOrderId", "根据订单ID获取车辆确认信息"),
+
+    // 更新车辆信息
+    UPDATE_CAR_INFO_URL("/mesci/order/MesOrderInfos/updateCarInfo", "更新车辆信息"),
+
+    // 获取平台车辆信息
+    GET_PLAT_CAR_INFO_URL("/mesci/order/MesOrderInfos/getPlatCarInfo", "获取平台车辆信息"),
+
+    // 计算初始化
+    CALCULATION_INITIALIZATION_URL("/mesci/order/MesOrderInfos/calculationInitialization", "保费计算初始化"),
+
+    // 事故记录
+    DO_ACCIDENT_RECORD("/mesci/order/MesOrderInfos/doAccidentRecord", "处理事故记录"),
+
+    // 自动生成
+    DO_AUTO_GENERATE("/mesci/order/MesOrderInfos/doAutoGenerate", "自动生成订单相关信息"),
+
+    // 订单详情
+    DO_MESORDER_DETAIL("/mesci/order/MesOrderInfos/doMesOrderDetail", "查询MES订单详情"),
+
+    // 获取上传结果
+    GET_UPLOAD_SUCCESS("/mesci/img/ImgRest/getUploadSuccess", "查询图片上传结果"),
+
+    // 查询日志
+    DO_QUERY_LOG("/mesci/order/MesOrderInfos/doQueryLog", "查询操作日志"),
+
+    // 校验所有图片
+    CHECK_IMAGES_ALL("/mesci/img/ImgRest/checkImagesAll", "校验所有图片"),
+
+    // 图片上传
+    UPLOAD_URL("/mesci/img/ImgRest/uploadImages", "上传图片"),
+
+    // 合保完成任务
+    HE_BAO_URL("/mesci/order/MesOrderInfos/doCompleteTask", "执行合保完成任务"),
+
+    // 获取授权Token
+    GET_AUTH_TOKEN("/ncisp/gateway/elec/Insurance/getAuthToken", "获取授权令牌"),
+
+    // 获取分享信息
+    GET_SHARE_INFO("/ncisp/gateway/elec/Insurance/getShareInfo", "获取分享信息"),
+
+    // 创建订单/计算费用
+    CREAT_ORDER_URL("/mesci/order/MesOrderInfos/doCalcFee", "计算保费/创建订单"),
+
+    // 删除订单
+    REMOVE_ORDER_URL("/mesci/order/MesOrderInfos/removeOrder", "删除订单"),
+
+    // 获取车险产品
+    GET_FROMCAR_PRODUCTS_URL("/ncisp/gatewayncisp/ncisp/ncisp/manageProducts/getFromCarProducts", "获取车险产品列表"),
+
+    // 销售归属信息
+    SALES_FCBE_LONG_INFO_URL("/mesci/order/MesOrderInfos/salesFCBelongInfo", "查询销售FC归属信息"),
+
+    // 获取订单详情
+    GET_ORDER_DETAIL_URL("/ncisp/gateway/elec/Insurance/getOrderDetail", "获取订单详情"),
+
+    // 查询订单列表
+    DO_MES_ORDERS_URL("/mesci/order/MesOrderInfos/doMesOrders", "查询MES订单列表"),
+
+    // 获取承保方式
+    GET_UNDERWRITING_URL("/ncisp/gatewayncisp/ncisp/ncisp/manageProducts/getUnderwritingById", "查询MES订单列表"),
+
+
+    // 承保
+    UNDERWRITING_PRE_URL("/ncisp/gatewayncisp/ncisp/ncisp/order/underwritingPre", "查询MES订单列表"),
+
+    // 承保
+    ENCRYPTIONCONVERT_URL("/ncisp/gatewayncisp/ncisp/ncisp/login/encryptionConvert", "查询MES订单列表"),
+
+    // 承保
+    EMPLOYEELOGIN_URL("/ncisp/gatewayncisp/ncisp/ncisp/login/employeeLogin", "查询MES订单列表"),
+
+
+    // 承保
+    FROMCARMODELCHECK_URL("/ncisp/gatewayncisp/ncisp/ncisp/manageProducts/fromCarModelCheck", "查询MES订单列表"),
+
+
+    // 承保
+    GET_PRODUCT_INFO_BY_ID_URL("/ncisp/gatewayncisp/ncisp/ncisp/manageProducts/getProductInfoById", "查询MES订单列表"),
+
+    // 承保
+    GET_INDIVIDUAL_VO_URL("/ncisp/gatewayncisp/ncisp/ncisp/carOrderInfo/getIndividualVo", "查询MES订单列表"),
+
+
+    // 承保
+    FINDAGENTRATE_URL("/ncisp/gatewayncisp/ncisp/ncisp/manageProducts/FindAgentRate", "查询MES订单列表"),
+
+
+    // 承保
+    UNDERWRITINGVARIABLE_PREMIUMVARIABLE_PREMIUM_URL("/ncisp/gatewayncisp/ncisp/ncisp/order/underwritingVariablePremiumVariablePremium", "查询MES订单列表"),
+
+
+    ;
+
+
+    private final String uri;
+
+    private final String description;
+
+
+    @Override
+    public String getRequestDescription() {
+        return description;
+    }
+
+    @Override
+    public String uri() {
+        return uri;
+    }
+}

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

@@ -9,14 +9,14 @@ import lombok.Data;
 public class CreatOrderRequest {
 
 
-    public static JSONObject creatOrderRequest(PremiumCalculateResponse.DataDTO dataDTO, String syShow, String redisValue, UserInfoResponse.UserData loginInfo){
+    public static JSONObject creatOrderRequest(PremiumCalculateResponse.DataDTO dataDTO, String syShow,String userID, UserInfoResponse.UserData loginInfo){
         // 构建请求参数
         JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(dataDTO));
         data.put("syShow", syShow);
         data.put("businessNatureCode", "");
         data.put("businessOffice", loginInfo.getUserDepartment());
         data.put("structureId", loginInfo.getProvincialCom());
-        data.put("userCode", JSONObject.parseObject(redisValue).getString("userID"));
+        data.put("userCode",userID);
         data.put("reformFlag", "1");
         data.put("oriSysOperator", "EM2_user");
         data.put("oriSysOperatorKey", "RU0yZW0y");

+ 28 - 4
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/GuoShouCrawlerQuoteResultsVoBuild.java

@@ -2,12 +2,14 @@ package com.jzg.quotation.guoshou.crawler.entity.request;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
-import com.google.common.collect.Lists;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
+import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
+import com.jzg.commons.entity.quote.vo.RiskInfoVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.quotation.guoshou.crawler.entity.response.PremiumCalculateResponse;
 
+import java.util.List;
 import java.util.Map;
 
 public class GuoShouCrawlerQuoteResultsVoBuild {
@@ -17,9 +19,8 @@ public class GuoShouCrawlerQuoteResultsVoBuild {
         PremiumCalculateResponse.OrderVoDTO orderVo = premiumCalculateResponse.getData().getOrderVo();
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         quoteResultsVo.setOrdersNo(quoteVo.getOrder().getOrdersNo());
-        quoteResultsVo.setCiRiskInfoVo(quoteVo.getCiRiskInfoVo());
-        quoteResultsVo.setBiRiskInfoVo(quoteVo.getBiRiskInfoVo());
-        quoteResultsVo.setKindInfoVo(Lists.newArrayList());
+        quoteResultsVo.setCiRiskInfoVo(buildRiskInfoVo(premiumCalculateResponse,quoteVo.getCiRiskInfoVo()));
+        quoteResultsVo.setBiRiskInfoVo(quoteResultsVo.getBiRiskInfoVo());
         quoteResultsVo.setCiStartDate(orderVo.getJqStartDate());
         quoteResultsVo.setCiEndDate(orderVo.getJqEndDate());
         quoteResultsVo.setBiStartDate(orderVo.getSyStartDate());
@@ -31,6 +32,29 @@ public class GuoShouCrawlerQuoteResultsVoBuild {
         return quoteResultsVo;
     }
 
+    /**
+     * 构造交强商业时间信息
+     * @param premiumCalculateResponse 保司返回险种信息
+     */
+    private static RiskInfoVo buildRiskInfoVo(PremiumCalculateResponse premiumCalculateResponse,RiskInfoVo ciRiskInfoVo) {
+        ciRiskInfoVo.setStartDate(premiumCalculateResponse.getData().getOrderVo().getJqStartDate());
+        ciRiskInfoVo.setEndDate(premiumCalculateResponse.getData().getOrderVo().getJqEndDate());
+        return ciRiskInfoVo;
+
+    }
+
+
+
+    /**
+     * 构造商业险险种信息
+     *
+     * @param kindInfoVo 商业险险种信息
+     * @param DataDTO dataDTO   保司返回商业险险种信息
+     */
+    private static void buildKindInfo(List<KindInfoVo> kindInfoVo,PremiumCalculateResponse.DataDTO dataDTO) {
+
+    }
+
     private static QuoteResultsVo.ScoreVo getScoreVo(PremiumCalculateResponse premiumCalculateResponse,Map<String, String> accidentResult){
         PremiumCalculateResponse.OrderVoDTO orderVo = premiumCalculateResponse.getData().getOrderVo();
         QuoteResultsVo.ScoreVo scoreVo = new QuoteResultsVo.ScoreVo();

+ 4 - 4
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/InsuranceApplicationEntity.java

@@ -2,6 +2,7 @@ package com.jzg.quotation.guoshou.crawler.entity.request;
 
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.commons.util.StringUtils;
+import com.jzg.quotation.guoshou.crawler.entity.response.RedisResultDTO;
 import com.jzg.quotation.guoshou.crawler.entity.response.UserInfoResponse;
 import lombok.Data;
 
@@ -13,8 +14,7 @@ import lombok.Data;
 public class InsuranceApplicationEntity {
 
 
-    public InsuranceApplicationEntity(String redisValue, JSONObject bindInfo, UserInfoResponse.UserData loginInfo, String licenseNo, String userCode, String energyTypeCode) {
-        JSONObject jsonObject = JSONObject.parseObject(redisValue);
+    public InsuranceApplicationEntity(RedisResultDTO redisResultDTO, JSONObject bindInfo, UserInfoResponse.UserData loginInfo, String licenseNo, String userCode, String energyTypeCode) {
         this.businessOffice =loginInfo.getUserDepartment();
         this.businessOfficeName = loginInfo.getGroupType();
         this.structureId = loginInfo.getProvincialCom();
@@ -31,7 +31,7 @@ public class InsuranceApplicationEntity {
         this.licnesTypeName = "小型汽车号牌";
         this.positionCode = "";
         this.positionName = "";
-        this.loginUserCode = jsonObject.getString("userID");
+        this.loginUserCode = redisResultDTO.getUserID();
         this.lifeInsuranceUserCode = null;
         this.newCarFlag = "0";
         this.bindId = bindInfo.getString("id");
@@ -67,7 +67,7 @@ public class InsuranceApplicationEntity {
         this.oriSysOperator = loginInfo.getOriSysOperator();
         this.oriSysOperatorKey = loginInfo.getOriSysOperatorKey();
         this.bpUserCode = null;
-        this.gstcItem = jsonObject.getString("gstcItem");
+        this.gstcItem = redisResultDTO.getGstcItem();
         this.collectionSourcesName = null;
         this.collectionSourcesCode = null;
         this.customerPhone = "";

+ 19 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/ProductUnderwriteRequest.java

@@ -0,0 +1,19 @@
+package com.jzg.quotation.guoshou.crawler.entity.request;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor  // 无参构造
+@AllArgsConstructor // 全参构造
+public class ProductUnderwriteRequest {
+    private String productId;
+    private String managerId;
+    private String businessNatureCode;
+    private String preId;
+    private String isPreUnderwriting;
+    private String systemSource;
+    private String comCode;
+
+}

+ 5 - 4
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/request/SubmitInsuranceInformationRequest.java

@@ -215,7 +215,7 @@ public class SubmitInsuranceInformationRequest {
         mesOrderVo.setDocSalePracticeNo("");
         mesOrderVo.setDocSalesPhone("");
         mesOrderVo.setIfFalse("2");
-        mesOrderVo.setAgreeCustomerShareFlag("0");
+        mesOrderVo.setAgreeCustomerShareFlag(null);
         mesOrderVo.setAgreementFixedFlag("0");
         mesOrderVo.setApplicantToCarowner("1");
         mesOrderVo.setPublicinsurantToApplicant("1");
@@ -248,7 +248,7 @@ public class SubmitInsuranceInformationRequest {
         carVoFront.setBrandCode(vehicleModelDetail.getBrandCode());
         carVoFront.setBrandName(vehicleModelDetail.getBrandName());
         carVoFront.setRbCode(vehicleModelDetail.getRbCode());
-        carVoFront.setVehiclecode(vehicleModelDetail.getStandardName());
+        carVoFront.setVehiclecode(vehicleModelDetail.getPlatModelCode());
         carVoFront.setVehiclestyledesc(vehicleModelDetail.getStandardName());
         carVoFront.setExhaustscale(vehicleModelDetail.getDisplacement());
         carVoFront.setPassengersNumber(vehicleModelDetail.getSeat());
@@ -306,7 +306,7 @@ public class SubmitInsuranceInformationRequest {
         carVoFront.setChgownerflag(carInfoVo.isTransfer() ? "1" : "0");
         carVoFront.setEngineNo(RsaUtils.encrypt(carInfoVo.getEngineNo()));
         carVoFront.setEnrollDate(carInfoVo.getRegisterDate());
-        carVoFront.setBuyDate(carInfoVo.getIssueDate());
+        carVoFront.setBuyDate(carInfoVo.getRegisterDate());
         carVoFront.setForeignCarFlag("0");
         carVoFront.setFrameNo(RsaUtils.encrypt(carInfoVo.getVinNo()));
         carVoFront.setLicenseNo(RsaUtils.encrypt(carInfoVo.getLicenseNo()));
@@ -886,6 +886,7 @@ public class SubmitInsuranceInformationRequest {
         @JsonProperty("carUserCodeName")
         private String carUserCodeName;
 
+//        发证日期
         @JsonProperty("certificateDate")
         private String certificateDate;
 
@@ -900,7 +901,7 @@ public class SubmitInsuranceInformationRequest {
 
         @JsonProperty("engineNo")
         private String engineNo;
-
+//初登日期
         @JsonProperty("enrollDate")
         private String enrollDate;
 

+ 701 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/ApiResponse.java

@@ -0,0 +1,701 @@
+package com.jzg.quotation.guoshou.crawler.entity.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 接口根响应实体
+ */
+@Data
+public class ApiResponse {
+    /**
+     * 响应状态码
+     */
+    private Integer status;
+
+    /**
+     * 响应消息
+     */
+    private String msg;
+
+    /**
+     * 响应信息
+     */
+    private String message;
+
+    /**
+     * 响应数据主体
+     */
+    private StoreData data;
+
+    /**
+     * 模型
+     */
+    private Object model;
+
+    /**
+     * 校验码
+     */
+    private String parityCode;
+
+
+    /**
+     * 门店数据实体
+     */
+    @Data
+    public static class StoreData {
+        /**
+         * 评价分页对象
+         */
+        private Object evaluateDTOPage;
+
+        /**
+         * 门店列表
+         */
+        private Object storeVOList;
+
+        /**
+         * 门店ID
+         */
+        private String storeId;
+
+        /**
+         * 门店名称
+         */
+        private String storeName;
+
+        /**
+         * 浏览量
+         */
+        private Integer pageView;
+
+        /**
+         * 门店状态
+         */
+        private Object storeStatus;
+
+        /**
+         * 销售额
+         */
+        private Integer sales;
+
+        /**
+         * 订单数量
+         */
+        private Integer orderNum;
+
+        /**
+         * 业务用户信息
+         */
+        private Object businessUserDTO;
+
+        /**
+         * 门店管理员用户ID
+         */
+        private String storeKeeperUserId;
+
+        /**
+         * 门店管理员用户编码
+         */
+        private String storeKeeperUserCode;
+
+        /**
+         * 业务用户列表
+         */
+        private Object businessUserDTOList;
+
+        /**
+         * 手机号
+         */
+        private Object phone;
+
+        /**
+         * 产品数量
+         */
+        private Integer productNum;
+
+        /**
+         * 评论数量
+         */
+        private Integer commentNum;
+
+        /**
+         * 关注数量
+         */
+        private Integer followNum;
+
+        /**
+         * 标签列表
+         */
+        private Object tagDTOs;
+
+        /**
+         * 门店描述
+         */
+        private String desc;
+
+        /**
+         * 图片路径
+         */
+        private Object picPath;
+
+        /**
+         * 音频路径
+         */
+        private Object audioPath;
+
+        /**
+         * 视频路径
+         */
+        private Object videoPath;
+
+        /**
+         * 文件路径
+         */
+        private Object filePath;
+
+        /**
+         * 是否推荐
+         */
+        private Boolean recommend;
+
+        /**
+         * 产品类型ID
+         */
+        private Object productTypeId;
+
+        /**
+         * 产品ID集合
+         */
+        private Object productIds;
+
+        /**
+         * 海报列表
+         */
+        private List<Object> postersDTOS;
+
+        /**
+         * 单个产品信息
+         */
+        private Object productDTO;
+
+        /**
+         * 产品列表
+         */
+        private Object productDTOS;
+
+        /**
+         * 产品链接
+         */
+        private Object productUrl;
+
+        /**
+         * 产品海报链接
+         */
+        private Object productPostUrl;
+
+        /**
+         * 城市名称
+         */
+        private String cityName;
+
+        /**
+         * 保险产品列表
+         */
+        private List<InsuranceProduct> ncispProducts;
+
+        /**
+         * 评分
+         */
+        private Double score;
+
+        /**
+         * 头像链接
+         */
+        private String headUrl;
+
+        /**
+         * 是否用户
+         */
+        private String isUser;
+
+        /**
+         * 门店海报
+         */
+        private String storePoster;
+
+        /**
+         * 门店内容
+         */
+        private String storeContent;
+
+        /**
+         * 门店海报ID
+         */
+        private String storePosterId;
+
+        /**
+         * 门店允许数量
+         */
+        private Integer storeAllowNum;
+
+        /**
+         * 评价数量
+         */
+        private Integer evaluateNum;
+
+        /**
+         * 手机号码
+         */
+        private String mobile;
+
+        /**
+         * 投标ID
+         */
+        private String bid;
+
+        /**
+         * 首页横幅
+         */
+        private Object homeBanner;
+
+        /**
+         * 收藏类型
+         */
+        private Object collectType;
+
+        /**
+         * 跳转链接
+         */
+        private String jumpLink;
+    }
+
+
+    /**
+     * 保险产品实体
+     */
+    @Data
+    public static class InsuranceProduct {
+        /**
+         * 期限类型数量
+         */
+        private Object periodTypeNum;
+
+        /**
+         * 期限
+         */
+        private Object periods;
+
+        /**
+         * 最小期限
+         */
+        private Object minPeriod;
+
+        /**
+         * 最大期限
+         */
+        private Object maxPeriod;
+
+        /**
+         * 保险数量
+         */
+        private Object insuranceNum;
+
+        /**
+         * 描述链接列表
+         */
+        private Object descirbUrlList;
+
+        /**
+         * 产品模型ID
+         */
+        private String productModelId;
+
+        /**
+         * 产品模型路径
+         */
+        private Object productModelPath;
+
+        /**
+         * 特别约定
+         */
+        private Object specialAgreement;
+
+        /**
+         * 特别约定状态
+         */
+        private Object specialAgreementStatus;
+
+        /**
+         * 产品编码
+         */
+        private Object productCode;
+
+        /**
+         * 机构ID
+         */
+        private Object officeId;
+
+        /**
+         * 产品名称
+         */
+        private String productName;
+
+        /**
+         * 产品描述
+         */
+        private String productDescribe;
+
+        /**
+         * 产品介绍
+         */
+        private String productIntroduce;
+
+        /**
+         * 产品声明标题
+         */
+        private Object productStatementTitle;
+
+        /**
+         * 产品声明内容
+         */
+        private Object productStatementContent;
+
+        /**
+         * 是否有声明
+         */
+        private Object hasStatement;
+
+        /**
+         * 配额项目编号
+         */
+        private String quotaProjectNo;
+
+        /**
+         * 产品描述链接
+         */
+        private Object productDescirbUrl;
+
+        /**
+         * 产品横幅链接
+         */
+        private String productBannerUrl;
+
+        /**
+         * 产品海报链接
+         */
+        private String productPosterUrl;
+
+        /**
+         * 期限
+         */
+        private Object period;
+
+        /**
+         * 期限类型
+         */
+        private String periodType;
+
+        /**
+         * 总金额
+         */
+        private Object totalAmount;
+
+        /**
+         * 总保费
+         */
+        private String totalPremium;
+
+        /**
+         * 比例保费
+         */
+        private Object ratioPremium;
+
+        /**
+         * 原始保费
+         */
+        private Object originalPremium;
+
+        /**
+         * 审核状态
+         */
+        private Object examineStatus;
+
+        /**
+         * 代理费率审核状态
+         */
+        private Object agentRateExamineStatus;
+
+        /**
+         * 审核拒绝原因
+         */
+        private Object examineRefuseReason;
+
+        /**
+         * 使用状态
+         */
+        private String usingStatus;
+
+        /**
+         * 所属类型
+         */
+        private Object belongToType;
+
+        /**
+         * 版本状态
+         */
+        private Object versionStatus;
+
+        /**
+         * 版本号
+         */
+        private Object versionNo;
+
+        /**
+         * 分类编码
+         */
+        private String classificationCode;
+
+        /**
+         * 保险类型ID
+         */
+        private String insuranceTypeId;
+
+        /**
+         * 保险类型名称
+         */
+        private Object insuranceTypeName;
+
+        /**
+         * 代理费率
+         */
+        private Object agentRate;
+
+        /**
+         * 全渠道
+         */
+        private Object allChannel;
+
+        /**
+         * 投保人与被保人相同
+         */
+        private Object sameHolderAndInsured;
+
+        /**
+         * 今日活动数量
+         */
+        private Object todayActNum;
+
+        /**
+         * 固定被保人关系
+         */
+        private Object fixedInsuredPersonRelation;
+
+        /**
+         * 被保人最小年龄
+         */
+        private Object insuredPersonAgeMin;
+
+        /**
+         * 被保人最大年龄
+         */
+        private Object insuredPersonAgeMax;
+
+        /**
+         * 投保人最小年龄
+         */
+        private Object policyHolderAgeMin;
+
+        /**
+         * 投保人最大年龄
+         */
+        private Object policyHolderAgeMax;
+
+        /**
+         * 投保人年龄限制
+         */
+        private Object policyHolderAgeLimit;
+
+        /**
+         * 被保人年龄限制
+         */
+        private Object insuredPersonAgeLimit;
+
+        /**
+         * 关系列表
+         */
+        private Object relationList;
+
+        /**
+         * 消息模板ID
+         */
+        private Object messageTemplateId;
+
+        /**
+         * 最早生效时间
+         */
+        private Object earliestEffectiveTime;
+
+        /**
+         * 是否可变保费
+         */
+        private String isVariablePremium;
+
+        /**
+         * 投保人类型
+         */
+        private Object policyHolderType;
+
+        /**
+         * 被保人类型
+         */
+        private Object insuredPersonType;
+
+        /**
+         * 投保人最小年龄单位
+         */
+        private Object policyHolderAgeMinUnit;
+
+        /**
+         * 被保人最小年龄单位
+         */
+        private Object insuredPersonAgeMinUnit;
+
+        /**
+         * 立即生效
+         */
+        private Object immediateEffect;
+
+        /**
+         * 立即生效数量
+         */
+        private Object immediateEffectNum;
+
+        /**
+         * 立即生效最大数量
+         */
+        private Object immediateEffectMaxNum;
+
+        /**
+         * 立即生效最晚时间
+         */
+        private Object immediateEffectLatestTime;
+
+        /**
+         * 查看费用
+         */
+        private Object seeFee;
+
+        /**
+         * 是否赠送保险
+         */
+        private Object isGiveInsurance;
+
+        /**
+         * 权限
+         */
+        private Object authority;
+
+        /**
+         * 限制被保人数
+         */
+        private Object limitInsuredNum;
+
+        /**
+         * 电子开关
+         */
+        private Object elecSwitch;
+
+        /**
+         * 电子功能开关
+         */
+        private Object elecFunSwitch;
+
+        /**
+         * 生活备注
+         */
+        private Object lifeNote;
+
+        /**
+         * 销售区域编码
+         */
+        private Object salesAreaCode;
+
+        /**
+         * 销售区域名称
+         */
+        private Object salesAreaName;
+
+        /**
+         * 部门编码
+         */
+        private Object deptCode;
+
+        /**
+         * 部门名称
+         */
+        private Object deptName;
+
+        /**
+         * 分类名称
+         */
+        private Object classificationName;
+
+        /**
+         * 产品ID
+         */
+        private String id;
+
+        /**
+         * 创建人
+         */
+        private Object createBy;
+
+        /**
+         * 创建时间
+         */
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+        private Date createDate;
+
+        /**
+         * 更新人
+         */
+        private Object updateBy;
+
+        /**
+         * 更新时间
+         */
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+        private Date updateDate;
+
+        /**
+         * 备注
+         */
+        private Object remarks;
+
+        /**
+         * 状态
+         */
+        private Object status;
+
+        /**
+         * 新标识
+         */
+        private Object newFlag;
+
+        /**
+         * 销量
+         */
+        private String salesVolume;
+
+        /**
+         * 类型
+         */
+        private String type;
+    }
+
+
+}

+ 349 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/GetUserInfoResponse.java

@@ -0,0 +1,349 @@
+package com.jzg.quotation.guoshou.crawler.entity.response;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class GetUserInfoResponse {
+
+
+    @JsonProperty("status")
+    private Integer status;
+
+    @JsonProperty("msg")
+    private String msg;
+
+    @JsonProperty("message")
+    private String message;
+
+    @JsonProperty("data")
+    private UserData data;
+
+    @JsonProperty("model")
+    private Object model;
+
+    @JsonProperty("parityCode")
+    private String parityCode;
+
+    /**
+     * data 节点嵌套实体
+     */
+    @Data
+    public static class UserData {
+
+        @JsonProperty("userCode")
+        private String userCode;
+
+        @JsonProperty("managerId")
+        private String managerId;
+
+        @JsonProperty("channels")
+        private Object channels;
+
+        @JsonProperty("mesChannel")
+        private Object mesChannel;
+
+        @JsonProperty("ncispChannel")
+        private NcispChannel ncispChannel;
+
+        @JsonProperty("provinceBid")
+        private String provinceBid;
+
+        @JsonProperty("bid")
+        private String bid;
+
+        @JsonProperty("bidName")
+        private String bidName;
+
+        @JsonProperty("deptId")
+        private String deptId;
+
+        @JsonProperty("deptName")
+        private String deptName;
+
+        @JsonProperty("depttype")
+        private String depttype;
+
+        @JsonProperty("mobile")
+        private String mobile;
+
+        @JsonProperty("pid")
+        private String pid;
+
+        @JsonProperty("practfno")
+        private String practfno;
+
+        @JsonProperty("psnname")
+        private String psnname;
+
+        @JsonProperty("tid")
+        private String tid;
+
+        @JsonProperty("teamName")
+        private String teamName;
+
+        @JsonProperty("downgradeFlag")
+        private Object downgradeFlag;
+
+        @JsonProperty("controlDownloads")
+        private Integer controlDownloads;
+
+        @JsonProperty("status")
+        private Integer status;
+
+        @JsonProperty("tags")
+        private Object tags;
+
+        @JsonProperty("occupation")
+        private Object occupation;
+
+        @JsonProperty("roles")
+        private Object roles;
+
+        @JsonProperty("levelDTO")
+        private LevelDTO levelDTO;
+
+        @JsonProperty("currentRole")
+        private CurrentRole currentRole;
+
+        @JsonProperty("phone")
+        private String phone;
+
+        @JsonProperty("nickname")
+        private String nickname;
+
+        @JsonProperty("realName")
+        private String realName;
+
+        @JsonProperty("email")
+        private String email;
+
+        @JsonProperty("age")
+        private Integer age;
+
+        @JsonProperty("idCard")
+        private String idCard;
+
+        @JsonProperty("sex")
+        private Integer sex;
+
+        @JsonProperty("headImg")
+        private String headImg;
+
+        @JsonProperty("height")
+        private Object height;
+
+        @JsonProperty("birthday")
+        private Long birthday;
+
+        @JsonProperty("address")
+        private String address;
+
+        @JsonProperty("lng")
+        private Object lng;
+
+        @JsonProperty("lat")
+        private Object lat;
+
+        @JsonProperty("provinceId")
+        private String provinceId;
+
+        @JsonProperty("provinceName")
+        private String provinceName;
+
+        @JsonProperty("cityId")
+        private String cityId;
+
+        @JsonProperty("cityName")
+        private String cityName;
+
+        @JsonProperty("countyId")
+        private String countyId;
+
+        @JsonProperty("countyName")
+        private String countyName;
+
+        @JsonProperty("userId")
+        private String userId;
+
+        @JsonProperty("openId")
+        private String openId;
+
+        @JsonProperty("contactNumber")
+        private String contactNumber;
+
+        @JsonProperty("studyTime")
+        private Integer studyTime;
+
+        @JsonProperty("score")
+        private BigDecimal score;
+
+        @JsonProperty("fiscalUserCode")
+        private String fiscalUserCode;
+
+        @JsonProperty("fiscalUserCodeUsedFlag")
+        private String fiscalUserCodeUsedFlag;
+
+        @JsonProperty("pre")
+        private Boolean pre;
+
+        @JsonProperty("password")
+        private String password;
+
+        @JsonProperty("downFlag")
+        private Integer downFlag;
+
+        @JsonProperty("frozenIdCard")
+        private String frozenIdCard;
+
+        @JsonProperty("createDate")
+        private Long createDate;
+
+        @JsonProperty("tenantId")
+        private String tenantId;
+
+        @JsonProperty("enUserCode")
+        private String enUserCode;
+
+        @JsonProperty("anxinAesUserCode")
+        private String anxinAesUserCode;
+    }
+
+    /**
+     * ncispChannel 嵌套实体
+     */
+    @Data
+    public static class NcispChannel {
+
+        @JsonProperty("id")
+        private String id;
+
+        @JsonProperty("userBusinessId")
+        private String userBusinessId;
+
+        @JsonProperty("userCode")
+        private String userCode;
+
+        @JsonProperty("mechanismCode")
+        private String mechanismCode;
+
+        @JsonProperty("managerId")
+        private String managerId;
+
+        @JsonProperty("channelType")
+        private String channelType;
+
+        @JsonProperty("channelName")
+        private String channelName;
+
+        @JsonProperty("userResourceCode")
+        private String userResourceCode;
+
+        @JsonProperty("userResource")
+        private String userResource;
+
+        @JsonProperty("userAgentCode")
+        private String userAgentCode;
+
+        @JsonProperty("userAgentId")
+        private String userAgentId;
+
+        @JsonProperty("userAgentName")
+        private String userAgentName;
+
+        @JsonProperty("interactionCommissionerCode")
+        private String interactionCommissionerCode;
+
+        @JsonProperty("interactionCommissionerName")
+        private String interactionCommissionerName;
+
+        @JsonProperty("handlerCode")
+        private String handlerCode;
+
+        @JsonProperty("handlerName")
+        private String handlerName;
+
+        @JsonProperty("identificationCode")
+        private String identificationCode;
+
+        @JsonProperty("qfdepttype")
+        private String qfdepttype;
+
+        @JsonProperty("registeredAddressOfAgenc")
+        private String registeredAddressOfAgenc;
+
+        @JsonProperty("permitNo")
+        private String permitNo;
+
+        @JsonProperty("qlfyctfNo")
+        private String qlfyctfNo;
+
+        @JsonProperty("saleschlcode")
+        private String saleschlcode;
+
+        @JsonProperty("agreementNo")
+        private String agreementNo;
+
+        @JsonProperty("businessType")
+        private String businessType;
+    }
+
+    /**
+     * levelDTO 嵌套实体
+     */
+    @Data
+    public static class LevelDTO {
+
+        @JsonProperty("id")
+        private String id;
+
+        @JsonProperty("grade")
+        private Integer grade;
+
+        @JsonProperty("levelNumber")
+        private Integer levelNumber;
+
+        @JsonProperty("growthNum")
+        private Integer growthNum;
+
+        @JsonProperty("days")
+        private Object days;
+
+        @JsonProperty("message")
+        private String message;
+
+        @JsonProperty("extras")
+        private Object extras;
+
+        @JsonProperty("type")
+        private String type;
+
+        @JsonProperty("upgradeTime")
+        private Long upgradeTime;
+
+        @JsonProperty("cycle")
+        private Boolean cycle;
+    }
+
+    /**
+     * currentRole 嵌套实体
+     */
+    @Data
+    public static class CurrentRole {
+
+        @JsonProperty("roleId")
+        private String roleId;
+
+        @JsonProperty("name")
+        private String name;
+
+        @JsonProperty("permissions")
+        private Object permissions;
+    }
+
+
+
+}

+ 143 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/LoginInfoResponse.java

@@ -0,0 +1,143 @@
+package com.jzg.quotation.guoshou.crawler.entity.response;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.List;
+
+
+@Data
+public class LoginInfoResponse {
+
+    // 响应消息
+    @JsonProperty("msg")
+    private String msg;
+
+    // 响应数据
+    @JsonProperty("data")
+    private UserData data;
+
+    // 响应状态码
+    @JsonProperty("status")
+    private String status;
+
+
+    @Data
+    public static class UserData {
+
+        @JsonProperty("managerId")
+        private String managerId;
+
+        @JsonProperty("userCode")
+        private String userCode;
+
+        @JsonProperty("userName")
+        private String userName;
+
+        @JsonProperty("userLevel")
+        private String userLevel;
+
+        @JsonProperty("userDepartment")
+        private String userDepartment;
+
+        @JsonProperty("userResourceCode")
+        private String userResourceCode;
+
+        @JsonProperty("userResource")
+        private String userResource;
+
+        @JsonProperty("userAgentCode")
+        private String userAgentCode;
+
+        @JsonProperty("userAgentName")
+        private String userAgentName;
+
+        @JsonProperty("channelType")
+        private String channelType;
+
+        @JsonProperty("channelName")
+        private String channelName;
+
+        @JsonProperty("groupCode")
+        private String groupCode;
+
+        @JsonProperty("groupType")
+        private String groupType;
+
+        @JsonProperty("resourceAgentStatus")
+        private String resourceAgentStatus;
+
+        @JsonProperty("provincialCom")
+        private String provincialCom;
+
+        @JsonProperty("bussMappingList")
+        private List<BussMapping> bussMappingList;
+
+        @JsonProperty("qfdepttype")
+        private String qfdepttype;
+
+        @JsonProperty("permitNo")
+        private String permitNo;
+
+        @JsonProperty("qlfyctfNo")
+        private String qlfyctfNo;
+
+        @JsonProperty("isHaveBind")
+        private String isHaveBind;
+
+        @JsonProperty("bindId")
+        private String bindId;
+
+        @JsonProperty("handerUserResourceCode")
+        private String handerUserResourceCode;
+
+        @JsonProperty("coreSystemSource")
+        private String coreSystemSource;
+
+        @JsonProperty("oriSysOperator")
+        private String oriSysOperator;
+
+        @JsonProperty("oriSysOperatorKey")
+        private String oriSysOperatorKey;
+
+        @JsonProperty("isTSuccess")
+        private String isTSuccess;
+
+        @JsonProperty("practfno")
+        private String practfno;
+
+        @JsonProperty("initialSystemSource")
+        private String initialSystemSource;
+
+        @JsonProperty("businessnatureStr")
+        private String businessnatureStr;
+
+        @JsonProperty("recommendGarageFlag")
+        private String recommendGarageFlag;
+
+        @JsonProperty("aesCode")
+        private String aesCode;
+
+        @JsonProperty("appliPendPaymentFlag")
+        private String appliPendPaymentFlag;
+
+        @JsonProperty("syShow")
+        private String syShow;
+
+        @JsonProperty("userLoginType")
+        private String userLoginType;
+    }
+
+    @Data
+    public static class BussMapping {
+
+        @JsonProperty("businessnature")
+        private String businessnature;
+
+        @JsonProperty("bussname")
+        private String bussname;
+
+    }
+
+
+}

+ 67 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/RedisResultDTO.java

@@ -0,0 +1,67 @@
+package com.jzg.quotation.guoshou.crawler.entity.response;
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class RedisResultDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 令牌
+     */
+    private String token;
+
+    /**
+     * 用户编码
+     */
+    private String userCode;
+
+    /**
+     * 业务ID/标识
+     */
+    private String bid;
+
+    /**
+     * 解码后的商品/项目信息
+     */
+    private String gstcItem;
+
+    /**
+     * 业务部门/办公部门
+     */
+    private String businessOffice;
+
+    /**
+     * 用户ID
+     */
+    private String userID;
+
+    /**
+     * H5跳转地址
+     */
+    private String H5URL;
+
+    /**
+     * 视图令牌
+     */
+    private String viewtoken;
+
+
+    public RedisResultDTO build(String token, String userCode, String bid, String gstcItem,
+                                String businessOffice, String userID, String H5URL, String viewtoken) {
+        this.token = token;
+        this.userCode = userCode;
+        this.bid = bid;
+        this.gstcItem = gstcItem;
+        this.businessOffice = businessOffice;
+        this.userID = userID;
+        this.H5URL = H5URL;
+        this.viewtoken = viewtoken;
+        return this;
+    }
+}
+

+ 3 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/entity/response/UserInfoResponse.java

@@ -158,6 +158,9 @@ public class UserInfoResponse {
          * 用户登录类型
          */
         private String userLoginType;
+
+        private RedisResultDTO redisResultDTO;
+
     }
 
     /**

+ 33 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/properties/GuoShouCrawlerProperties.java

@@ -0,0 +1,33 @@
+package com.jzg.quotation.guoshou.crawler.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 国寿配置
+ */
+
+@Data
+@Component
+@ConfigurationProperties(prefix = "guoshou.crawler")
+public class GuoShouCrawlerProperties {
+
+    /**
+     * 请求路劲
+     */
+    private String baseUrl;
+
+
+    /**
+     * 请求路劲
+     */
+    private String quoteUrl;
+
+    /**
+     * 请求路劲
+     */
+    private String tokenUrl;
+
+}

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

@@ -6,6 +6,7 @@ import com.alibaba.fastjson.TypeReference;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
+import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.quote.vo.*;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
@@ -19,6 +20,7 @@ import com.jzg.quotation.commons.entity.DetectLoginRequest;
 import com.jzg.quotation.commons.entity.GetCaptchaRequest;
 import com.jzg.quotation.commons.entity.GetCaptchaResponse;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
+import com.jzg.quotation.commons.utils.TimeProcessing;
 import com.jzg.quotation.guoshou.crawler.component.GsCrawlerLoginComponent;
 import com.jzg.quotation.guoshou.crawler.component.GsCrawlerRequestComponent;
 import com.jzg.quotation.guoshou.crawler.constant.GsConstants;
@@ -27,7 +29,7 @@ import com.jzg.quotation.guoshou.crawler.entity.response.*;
 import com.jzg.quotation.guoshou.crawler.service.GuoshouCrawlerRequest;
 import com.jzg.quotation.guoshou.crawler.util.DateUtils;
 import com.jzg.quotation.guoshou.crawler.util.FirstMatchUtils;
-import com.jzg.quotation.guoshou.crawler.util.QrCodeReader;
+import com.jzg.quotation.guoshou.crawler.util.ModularDataProcessor;
 import com.jzg.quotation.guoshou.crawler.util.RsaUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -38,14 +40,14 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.text.PDFTextStripper;
 import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDate;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -63,6 +65,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
 
     private final GsCrawlerRequestComponent gsCrawlerRequestComponent;
     private final GsCrawlerLoginComponent gsCrawlerLoginComponent;
+    private final ModularDataProcessor dataProcessor;
     private final StringRedisTemplate redisTemplate;
     private final RsaUtils rsaUtils;
     private final OrgClient orgClient;
@@ -91,7 +94,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             configInfo.put("username", username);
             configInfo.put("password", password);
             attributionInformationVo.setConfigInfo(configInfo);
-            return getLoginInfo(attributionInformationVo) != null;
+            return gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo) != null;
         }
         return true;
     }
@@ -101,23 +104,28 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     public QuoteResultsVo quote(QuoteVo quoteVo) throws Exception {
         OrderBase order = quoteVo.getOrder();
         AttributionInformationVo attributionInformationVo = order.getAttributionInformationVo();
-        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
         // 查询loginInfo
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
-        String token = JSONObject.parseObject(redisValue).getString("token");
-        String userID = JSONObject.parseObject(redisValue).getString("userID");
-        JSONObject bindInfo = getBindInfo(redisValue, loginInfo);
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        RedisResultDTO redisResultDTO = loginInfo.getRedisResultDTO();
+        String token = redisResultDTO.getToken();
+        String userID = redisResultDTO.getUserID();
+        JSONObject bindInfo = getBindInfo(token, loginInfo);
         if (bindInfo.isEmpty()) {
             log.error("未匹配到归属信息,username:{}, gsName:{}", "140123198503130219", "腾晟保险代理有限公司山西分公司");
             throw new RuntimeException("请输入正确的归属信息");
         }
         log.info("绑定信息查询成功,userAgentName:{}", bindInfo.getString("userAgentName"));
         //  调用订单号接口
-        InsuranceApplicationEntity insuranceApplicationEntity = new InsuranceApplicationEntity(redisValue, bindInfo, loginInfo, rsaUtils.encrypt(carInfoVo.getLicenseNo()),
-                rsaUtils.encrypt(JSONObject.parseObject(redisValue).getString("userID")), carInfoVo.getEnergyTypeCode());
-        String orderNo = gsCrawlerRequestComponent.queryOrderNo(insuranceApplicationEntity, redisValue);
+        InsuranceApplicationEntity insuranceApplicationEntity = new InsuranceApplicationEntity(redisResultDTO, bindInfo, loginInfo, rsaUtils.encrypt(carInfoVo.getLicenseNo()),
+                rsaUtils.encrypt(redisResultDTO.getUserID()), carInfoVo.getEnergyTypeCode());
+        String orderNo = gsCrawlerRequestComponent.queryOrderNo(insuranceApplicationEntity, token);
         log.info("获取订单号成功,orderId:{}", orderNo);
+
+        //  获取销售归属信息
+        JSONObject jsonObject = gsCrawlerRequestComponent.salesFCBelongInfo(token, orderNo, bindInfo);
+        String businessNatureCode = jsonObject.getString("businessNatureCode");
+
         // 获取保险信息
         InsuranceInformationRequest informationRequest = new InsuranceInformationRequest(rsaUtils.encrypt(bindInfo.getString("userAgentCode")), orderNo, "");
         CarInsuranceQueryResponse.CarInsuranceData insuranceInformation = gsCrawlerRequestComponent.getInsuranceInformation(informationRequest, token);
@@ -126,15 +134,21 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         //查询车型
         List<GsCrawlerCarQueryResponse.VehicleModelDetail> vehicleModelDetails = gsCrawlerRequestComponent.carQuery(carQueryRequest, token);
         GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail = CarModelsFilterUtils.to(vehicleModelDetails, carInfoVo);
+
         if (vehicleModelDetail == null) {
             log.error("未匹配到车辆信息,vin:{}, seatCount:{}", carInfoVo.getVinNo());
             throw new RuntimeException("暂未查询到车型");
         }
-        JSONObject jsonObject = gsCrawlerRequestComponent.salesFCBelongInfo(token, orderNo, bindInfo);
-        String businessNatureCode = jsonObject.getString("businessNatureCode");
+
         log.info("车辆信息查询成功,standardName:{}, seat:{}", vehicleModelDetail.getStandardName(), vehicleModelDetail.getSeat());
+        //   查询获取承保方式
+//        ProductUnderwriteRequest request = new ProductUnderwriteRequest("","",businessNatureCode,"","","","");
+//        gsCrawlerRequestComponent.getUnderwritingById(token,request);
+
+
         //  封装submit参数
         SubmitInsuranceInformationRequest submitInsuranceInformationRequest = new SubmitInsuranceInformationRequest(orderNo, quoteVo, vehicleModelDetail, loginInfo, bindInfo, insuranceInformation, userID, orgClient, businessNatureCode);
+        log.info("submit提交参数:{}{}", JSONObject.toJSONString(submitInsuranceInformationRequest));
         SubmitResponse submitResponse = gsCrawlerRequestComponent.submitInsuranceInformationRequest(submitInsuranceInformationRequest, token);
         if ("500".equals(submitResponse.getStatus())) {
             throw new RuntimeException("提交保险信息失败" + submitResponse.getMsg());
@@ -156,7 +170,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         }
         // 加密转换查询
         //String encrypt_userCode = gsCrawlerRequestComponent.getEncryptionConvert(userID, token);
-        return calculation(orderNo, redisValue, quoteVo, insuranceInformation, loginInfo, vehicleModelDetail, bindInfo, businessNatureCode);
+        return calculation(orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo, vehicleModelDetail, bindInfo, businessNatureCode,jsonObject);
     }
 
     @Override
@@ -164,9 +178,8 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         AttributionInformationVo attributionInformationVo = underwritingVo.getOrder().getAttributionInformationVo();
         String ordersNo = underwritingVo.getOrder().getOrdersNo();
         JSONObject quoteInfo = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + ordersNo));
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
-        JSONObject res = gsCrawlerRequestComponent.doCompleteTask(new OrderEntity(quoteInfo), redisValue);
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
+        JSONObject res = gsCrawlerRequestComponent.doCompleteTask(new OrderEntity(quoteInfo), loginInfo.getRedisResultDTO().getToken());
         log.info("核保结果:{}", res);
         UnderwritingResultsVo underwritingResultsVo = new UnderwritingResultsVo();
         if (!"核保通过".equals(res.getString("msg"))) {
@@ -180,7 +193,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             underwritingResultsVo.setCompanyOrderNo(quoteInfo.getString("orderId"));
             underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
             underwritingResultsVo.setUnderwritingResult(res.getString("msg"));
-            underwritingResultsVo.setPaymentLink(getPayUrl(quoteInfo, redisValue));
+            underwritingResultsVo.setPaymentLink(getPayUrl(quoteInfo, loginInfo.getRedisResultDTO()));
         } else {
             underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
         }
@@ -227,32 +240,31 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
 
     @Override
     public PaymentLinkResultsVo getPaymentLink(PaymentLinkVo paymentLinkVo) throws Exception {
+        InsOrders insOrders = paymentLinkVo.getInsOrders();
         AttributionInformationVo attributionInformationVo = paymentLinkVo.getOrder().getAttributionInformationVo();
-        String ordersNo = paymentLinkVo.getOrder().getOrdersNo();
-        JSONObject quoteInfo = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + ordersNo));
-        getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         PaymentLinkResultsVo paymentLinkResultsVo = new PaymentLinkResultsVo();
-        paymentLinkResultsVo.setPaymentLink(getPayUrl(quoteInfo, redisValue));
+        //paymentLinkResultsVo.setPaymentLink(getPayUrl(quoteInfo, redisValue));
         return paymentLinkResultsVo;
     }
 
 
-    public String getPayUrl(JSONObject quoteInfo, String redisValue) {
+    public String getPayUrl(JSONObject quoteInfo,RedisResultDTO redisResultDTO) {
         // 核保通过   获取订单详情
-        Map<String, Object> detailData = new HashMap<>();
-        detailData.put("orderNo", quoteInfo.getString("orderId"));
-        detailData.put("structureId", JSONObject.parseObject(redisValue).getString("structureId"));
-        detailData.put("userCode", JSONObject.parseObject(redisValue).getString("username"));
-        detailData.put("userLoginType", "1");
-        detailData.put("sellCode", null);
-        detailData.put("systemSource", "gstc");
-        JSONObject doMesOrderDetailRes = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quoteInfo);
-        // 提取支付链接
-        String payUrl = JSONObject.parseObject(doMesOrderDetailRes.getString("data")).getString("payUrl");
-        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(payUrl), redisValue);
-        ResponseDTO shareInfo = gsCrawlerRequestComponent.getShareInfo(tokenResponse, redisValue);
-        return QrCodeReader.parseQrCodeUrl(shareInfo.getData().getUrl());
+//        Map<String, Object> detailData = new HashMap<>();
+//        detailData.put("orderNo", quoteInfo.getString("orderId"));
+//        detailData.put("structureId", JSONObject.parseObject(redisValue).getString("structureId"));
+//        detailData.put("userCode", JSONObject.parseObject(redisValue).getString("username"));
+//        detailData.put("userLoginType", "1");
+//        detailData.put("sellCode", null);
+//        detailData.put("systemSource", "gstc");
+//        JSONObject doMesOrderDetailRes = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quoteInfo);
+//        // 提取支付链接
+//        String payUrl = JSONObject.parseObject(doMesOrderDetailRes.getString("data")).getString("payUrl");
+//        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(payUrl), redisValue);
+//        ResponseDTO shareInfo = gsCrawlerRequestComponent.getShareInfo(tokenResponse, redisValue);
+  //      return QrCodeReader.parseQrCodeUrl(shareInfo.getData().getUrl());
+        return null;
     }
 
 
@@ -263,17 +275,16 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         String value = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo());
         JSONObject quote = JSONObject.parseObject(value);
         // 查询loginInfo
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         // 获取归属信息
-        JSONObject bindInfo = getBindInfo(redisValue, loginInfo);
+        JSONObject bindInfo = getBindInfo(loginInfo.getRedisResultDTO().getToken(), loginInfo);
         // 1. 自动生成订单
         GenerateDataRequest generateDataRequest = new GenerateDataRequest(quote);
-        gsCrawlerRequestComponent.doAutoGenerate(generateDataRequest, redisValue);
+        gsCrawlerRequestComponent.doAutoGenerate(generateDataRequest, loginInfo.getRedisResultDTO().getToken());
         // 2. 获取订单详情
-        JSONObject doMesOrderDetail = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quote);
+        JSONObject doMesOrderDetail = gsCrawlerRequestComponent.doMesOrderDetail(loginInfo.getRedisResultDTO().getToken(), quote);
         // 3. 获取上传状态
-        gsCrawlerRequestComponent.getUploadSuccess(redisValue, quote);
+        gsCrawlerRequestComponent.getUploadSuccess(loginInfo.getRedisResultDTO().getToken(), quote);
         // 4. 查询日志
         JSONObject logData = new JSONObject();
         logData.put("orderNo", quote.getString("orderId"));
@@ -284,7 +295,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         logData.put("oriSysOperatorKey", "RU0yZW0y");
         logData.put("bancassuranceFlag", 0);
         logData.put("checkOrganizationFlag", "0");
-        QueryLogResponse queryLogResponse = gsCrawlerRequestComponent.doQueryLog(redisValue, logData);
+        QueryLogResponse queryLogResponse = gsCrawlerRequestComponent.doQueryLog(loginInfo.getRedisResultDTO().getToken(), logData);
         String JQ_Policy = "";
         String SY_Policy = "";
         String JYX_Policy = "";
@@ -296,7 +307,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
                 logData.put("oriSysOperator", "E11_user");
                 logData.put("oriSysOperatorKey", "RTExZTEx");
                 logData.put("vinUseChangeStatusFlag", "1");
-                queryLogResponse = gsCrawlerRequestComponent.doQueryLog(redisValue, logData);
+                queryLogResponse = gsCrawlerRequestComponent.doQueryLog(loginInfo.getRedisResultDTO().getToken(), logData);
             }
             QueryLogResponse.DataDTO responseData = queryLogResponse.getData();
             // 解析投保单号
@@ -312,13 +323,13 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             redisTemplate.opsForValue().set(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo() + ":SY_Policy:", SY_Policy, GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
             redisTemplate.opsForValue().set(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo() + ":JYX_Policy:", JYX_Policy, GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
             // 再次获取订单详情
-            gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quote);
+            gsCrawlerRequestComponent.doMesOrderDetail(loginInfo.getRedisResultDTO().getToken(), quote);
         } else {
-            log.info("查询QueryLog日志{}", queryLogResponse.getMsg());
+            log.info("查询QueryLog日志{}", JSONObject.toJSONString(queryLogResponse));
             throw new RuntimeException("获取报价日志失败{}:" + queryLogResponse.getMsg());
         }
 
-        JSONObject upload = upload(insuranceUploadImageVo.getImageVoList(), JQ_Policy, SY_Policy, JYX_Policy, loginInfo, bindInfo, quote, redisValue);
+        JSONObject upload = upload(insuranceUploadImageVo.getImageVoList(), JQ_Policy, SY_Policy, JYX_Policy, loginInfo, bindInfo, quote, loginInfo.getRedisResultDTO().getToken());
         if (!"200".equals(upload.getString("code"))) {
             throw new RuntimeException("上传失败" + upload.getString("message"));
         } else {
@@ -336,18 +347,17 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         AttributionInformationVo attributionInformationVo = downloadPolicyVo.getOrder().getAttributionInformationVo();
         OrderBase orderBase = downloadPolicyVo.getOrder();
         JSONObject quote = JSONObject.parseObject(redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + orderBase.getOrdersNo()));
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
-        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         // 1. 获取订单列表
         DoMesOrdersRequest doMesOrdersRequest = new DoMesOrdersRequest(loginInfo.getAesCode(), "");
-        JSONObject mesOrders = gsCrawlerRequestComponent.doMesOrders(doMesOrdersRequest, redisValue);
+        JSONObject mesOrders = gsCrawlerRequestComponent.doMesOrders(doMesOrdersRequest, loginInfo.getRedisResultDTO().getToken());
         JSONObject order = JSONObject.parseObject(JSONObject.toJSONString(mesOrders.getJSONObject("data").getJSONArray("data").get(0)));
         quote.put("orderId", order.getString("orderNo"));
         //  获取订单详情
-        JSONObject jsonObject = gsCrawlerRequestComponent.doMesOrderDetail(redisValue, quote);
-        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(JSONObject.toJSONString(jsonObject)), redisValue);
+        JSONObject jsonObject = gsCrawlerRequestComponent.doMesOrderDetail(loginInfo.getRedisResultDTO().getToken(), quote);
+        JSONObject tokenResponse = gsCrawlerRequestComponent.getTokenUrl(getTokenData(JSONObject.toJSONString(jsonObject)), loginInfo.getRedisResultDTO().getToken());
         String id = tokenResponse.getJSONObject("data").getString("id");
-        JSONObject orderDetail = gsCrawlerRequestComponent.getOrderDetail(id, redisValue);
+        JSONObject orderDetail = gsCrawlerRequestComponent.getOrderDetail(id, loginInfo.getRedisResultDTO().getToken());
         JSONArray dzbdList = orderDetail.getJSONObject("data").getJSONArray("list");
         // 遍历保单列表,赋值对应URL
         String syxUrl = "";
@@ -426,7 +436,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     @Override
     public OrderStatusResultVo queryOrderState(OrderStatusVo orderStatusVo) throws Exception {
         AttributionInformationVo attributionInformationVo = orderStatusVo.getOrder().getAttributionInformationVo();
-        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
+        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
         String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + attributionInformationVo.getConfigInfo().get("username"));
         // 1. 获取订单列表
         DoMesOrdersRequest doMesOrdersRequest = new DoMesOrdersRequest(loginInfo.getAesCode(), rsaUtils.encrypt(orderStatusVo.getCarInfo().getLicenseNo()));
@@ -492,36 +502,8 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         return resultVo;
     }
 
-    public String getRedisKey(AttributionInformationVo attributionInformationVo) {
-        String username = attributionInformationVo.getConfigInfo().get("username");
-        String value = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + username);
-        if (StringUtils.isEmpty(value)) {
-            gsCrawlerLoginComponent.login(attributionInformationVo);
-            value = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY + username);
-            if (StringUtils.isEmpty(value)) {
-                getRedisKey(attributionInformationVo);
-            }
-        }
-        return value;
-    }
 
 
-    public UserInfoResponse.UserData getLoginInfo(AttributionInformationVo attributionInformationVo) {
-        String username = attributionInformationVo.getConfigInfo().get("username");
-        String redisValue = getRedisKey(attributionInformationVo);
-        UserInfoResponse loginInfo = gsCrawlerRequestComponent.getLoginInfo(redisValue);
-        if (loginInfo == null || !"200".equals(loginInfo.getStatus())) {
-            log.warn("登录信息接口响应异常,重新获取用户信息,username:{}", loginInfo.getMsg());
-            redisTemplate.delete(GsConstants.GS_REDIS_LOGIN_KEY + username);
-            redisValue = getRedisKey(attributionInformationVo);
-            loginInfo = gsCrawlerRequestComponent.getLoginInfo(redisValue);
-            if (loginInfo == null || !"200".equals(loginInfo.getStatus())) {
-                getLoginInfo(attributionInformationVo);
-            }
-        }
-        return loginInfo.getData();
-    }
-
 
     @Override
     public void qutoationCrawler(InsuranceUploadImageVo insuranceUploadImageVo) {
@@ -529,9 +511,9 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     }
 
 
-    public JSONObject getBindInfo(String redisValue, UserInfoResponse.UserData loginInfo) {
+    public JSONObject getBindInfo(String token, UserInfoResponse.UserData loginInfo) {
         // 获取绑定信息
-        List<JSONObject> bindInfoData = gsCrawlerRequestComponent.getBindInfo(redisValue, loginInfo.getUserCode());
+        List<JSONObject> bindInfoData = gsCrawlerRequestComponent.getBindInfo(token, loginInfo.getUserCode());
         if (CollectionUtil.isEmpty(bindInfoData)) {
             log.error("绑定信息为空,username:{}");
             throw new RuntimeException("未查询到归属信息");
@@ -555,11 +537,11 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
         return bindInfo;
     }
 
-    public QuoteResultsVo calculation(String orderNo, String redisValue, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
-                                      GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode) {
+    public QuoteResultsVo calculation(String orderNo,RedisResultDTO redisResultDTO, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
+                                      GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode,JSONObject jsonObject) {
         try {
-            String token = JSONObject.parseObject(redisValue).getString("token");
-            String userID = JSONObject.parseObject(redisValue).getString("userID");
+            String token = redisResultDTO.getToken();
+            String userID = redisResultDTO.getUserID();
             CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
             CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
             RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
@@ -640,10 +622,12 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             List<InsuranceInitResponse.ClauseInfo> clauseInfoList = insuranceInitData.getClauseInfoList();
             // TODO 配置险种参数
             configClauseInfo(clauseInfoList, quoteVo);
+
             DoCalculateRequest doCalculateRequest = new DoCalculateRequest(desensitizationJson, orderVo, clauseInfoList, syShow, loginInfo, bindInfo);
             PremiumCalculateResponse premiumCalculateResponse = gsCrawlerRequestComponent.doCalculate(doCalculateRequest, token);
-            return repeat(premiumCalculateResponse, orderNo, redisValue, quoteVo, insuranceInformation, loginInfo,
-                    vehicleModelDetail, bindInfo, businessNatureCode, token, syShow);
+            log.info("报价返回信息========:{}{}", JSONObject.toJSONString(premiumCalculateResponse));
+            return repeat(premiumCalculateResponse, orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo,
+                    vehicleModelDetail, bindInfo, businessNatureCode, token, syShow,userID,jsonObject);
 
 
         } catch (Exception e) {
@@ -653,33 +637,491 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     }
 
 
+    public void get_fcxdata(QuoteVo quoteVo,String token,String userID,String businessNatureCode,UserInfoResponse.UserData loginInfo,String orderNo,String seat,JSONObject jsonObject){
+        List<AccidentalDrivingVo> accidentalDrivings = quoteVo.getAccidentalDrivings();
+        if (CollectionUtil.isNotEmpty(accidentalDrivings)){
+            for (AccidentalDrivingVo accidentalDriving : accidentalDrivings) {
+                // 1
+                MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+                formData.add("convert", userID);
+                JSONObject encryptionConvert = gsCrawlerRequestComponent.encryptionConvert(formData,token);
+                String encrypt_userCode = encryptionConvert.getString("data");
+                // 2
+                MultiValueMap<String, String> data2 = new LinkedMultiValueMap<>();
+                data2.add("userCode", encrypt_userCode);
+                data2.add("loginUserType", "1");
+                data2.add("isApp", "1");
+                JSONObject employeeLogin = gsCrawlerRequestComponent.employeeLogin(data2,token);
+
+                JSONObject empData = employeeLogin.getJSONObject("data");
+                String managerId = empData.getString("id");
+                String saleAgreementNo = empData.getString("saleAgreementNo");
+                String userName = empData.getString("userName");
+                String branchOfficeName = empData.getString("branchOfficeName");
+                //3
+                MultiValueMap<String, String> data3 = new LinkedMultiValueMap<>();
+                data3.add("productId",accidentalDriving.getProductCode() );
+                data3.add("managerId", managerId);
+                data3.add("businessNatureCode",businessNatureCode);
+                data3.add("comCode", loginInfo.getUserDepartment());
+                JSONObject productInfo = gsCrawlerRequestComponent.getProductInfoById(data3,token);
+
+                //4
+                MultiValueMap<String, String> data4 = new LinkedMultiValueMap<>();
+                data4.add("thisId",orderNo );
+
+                JSONObject individualVo = gsCrawlerRequestComponent.getIndividualVo(data4,token);
+
+
+                JSONObject data5 = new JSONObject();
+                data5.put("productId",accidentalDriving.getProductCode() );
+                data5.put("carUserNatureCode", "8A");
+                data5.put("passengersNumber",seat);
+                data5.put("carKindCode","A0");
+                JSONObject fromCarModelCheck = gsCrawlerRequestComponent.fromCarModelCheck(data5,token);
+
+
+                MultiValueMap<String, String> data6 = new LinkedMultiValueMap<>();
+                data6.add("productId",accidentalDriving.getProductCode() );
+                data6.add("managerId", managerId);
+                data6.add("businessNatureCode",businessNatureCode);
+                data6.add("comCode", loginInfo.getUserDepartment());
+                JSONObject underwritingById = gsCrawlerRequestComponent.getUnderwritingById(data6,token);
+                JSONObject next_data = underwritingById.getJSONObject("data");
+                // -------------------- 5. underwritingPre --------------------
+                next_data.put("carOrderId", orderNo);
+                next_data.put("systemSource", "fromCar");
+                next_data.put("comCode",loginInfo.getUserDepartment());
+                JSONObject underwritingPre = gsCrawlerRequestComponent.underwritingPre(next_data,token,loginInfo.getRedisResultDTO().getBid());
+                String preId = underwritingPre.getJSONObject("data").getString("preId");
+                String salesman = jsonObject.getString("salesman");
+                String saleAgreementNo1 = jsonObject.getString("saleAgreementNo");
+                String businessNatureName = jsonObject.getString("businessNatureName");
+                String channelType = jsonObject.getString("channelType");
+
+
+                JSONObject data7 = new JSONObject();
+                data7.put("productId",accidentalDriving.getProductCode() );
+                data7.put("managerId", managerId);
+                data7.put("businessNatureCode",businessNatureCode);
+                data7.put("salesman",salesman);
+                JSONObject findAgentRate = gsCrawlerRequestComponent.findAgentRate(data7,token);
+
+
+                JSONObject data7vo = gsCrawlerRequestComponent.getIndividualVo(data4,token);
+
+
+                MultiValueMap<String, String> data8 = new LinkedMultiValueMap<>();
+                data8.add("productId",accidentalDriving.getProductCode() );
+                data8.add("managerId", managerId);
+                data8.add("businessNatureCode",businessNatureCode);
+                data8.add("comCode", loginInfo.getUserDepartment());
+
+                data8.add("preId", preId);
+                data8.add("isPreUnderwriting","1");
+                data8.add("systemSource", "fromCar");
+                JSONObject data8vo = gsCrawlerRequestComponent.getUnderwritingById(data8,token);
+                JSONObject voString = data8vo.getJSONObject("data");
+
+                // 获取模块化列表(JSONArray)
+                JSONArray second_data = voString.getJSONArray("modularList");
+                if (second_data == null || second_data.isEmpty()) {
+                    return;
+                }
+
+
+                dataProcessor.processModularData(second_data,accidentalDriving.getProductCode(),quoteVo,seat, jsonObject,loginInfo,branchOfficeName,voString);
+
+
+                JSONObject underwritingVariablePremiumVariablePremium = gsCrawlerRequestComponent.underwritingVariablePremiumVariablePremium(voString,token);
+                System.out.println("==================");
+
+            }
+
+
+        }
+
+    }
+
+
+
+
+    public void processModularData(JSONArray modularList, String productId,QuoteVo quoteVo, String seat,JSONObject jsonObject,UserInfoResponse.UserData loginInfo,String branchOfficeName,JSONObject data8vo) {
+
+        // 白名单产品ID
+        List<String> validProductIds = List.of(
+                "fd2dc8abe5f94eacbc8efd3bf62a8581",
+                "39f47efbd6004899b4fa7c80bfdba801",
+                "54b7cce17316444aade70427d8abea0a",
+                "7e1108d1db2c428d8cf35e3e6896bb15",
+                "fc9cd193ce444508b355b5d5522ffc00",
+                "71d3c2271fe5404d82c78fb07d116cf0",
+                "77bcfb9bff014a93bfca0ed792c30258",
+                "new-2d0bc85a46c799ff4ad0c8521348",
+                "f65730fe001a4c998aabc1d2e7258a96"
+        );
+
+        if (!validProductIds.contains(productId)) {
+            return;
+        }
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();
+        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();
+        for (int i = 0; i < modularList.size(); i++) {
+            JSONObject modular = modularList.getJSONObject(i);
+            Integer sortNo = modular.getInteger("sortNo");
+            if (sortNo == null) {
+                continue;
+            }
+            JSONArray infoList = modular.getJSONArray("ncispUnderwritingInfoList");
+            if (infoList == null) {
+                continue;
+            }
+            JSONArray newInfoList = new JSONArray();
+            // ====================== sortNo = 0 ======================
+            if (sortNo == 0) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    String type = item.getString("type");
+
+                    if ("1".equals(type)) {
+                        switch (fieldName) {
+                            case "customerName":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encryptedName = RsaUtils.encrypt(policyHolderInfo.getName());
+                                item.put("fieldValue", encryptedName);
+                                item.put("fieldValueName", encryptedName);
+                                break;
+                            case "mobile":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encryptedPhone = RsaUtils.encrypt(policyHolderInfo.getMobile());
+                                item.put("fieldValue", encryptedPhone);
+                                item.put("fieldValueName", encryptedPhone);
+                                break;
+                            case "identifyType":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", "idCard");
+                                item.put("fieldValueName", "居民身份证");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                break;
+                            case "identifyNumber":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encryptedIdNo = RsaUtils.encrypt(policyHolderInfo.getIdentifyNumber());
+                                item.put("fieldValue", encryptedIdNo);
+                                item.put("fieldValueName", encryptedIdNo);
+                                break;
+                            case "age":
+                                item.put("display", "none");
+                                break;
+                            case "sex":
+                                String sexVal = item.getString("fieldValueName");
+                                if ("2".equals(sexVal)) {
+                                    item.put("fieldValueName", "女");
+                                } else {
+                                    item.put("fieldValueName", "男");
+                                }
+                                item.put("fieldValue", "1");
+                                item.put("display", "none");
+                                break;
+                            case "identifyEffectiveStartDate":
+                                String today = LocalDate.now().toString();
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "0");
+                                item.put("display", "block");
+                                item.put("minDate", "1900-01-01");
+                                item.put("maxDate", today);
+                                break;
+                            case "identifyEffectiveTerm":
+                                item.put("fieldType", "-1");
+                                item.put("fieldValue", "100");
+                                item.put("mustFill", "0");
+                                item.put("display", "block");
+                                break;
+                            case "citizenship":
+                                item.put("display", "block");
+                                break;
+                            case "provinceCode":
+                                item.put("readonly", "1");
+                                item.put("fieldDescribe", "省市地区");
+                                item.put("fieldValue", policyHolderInfo.getProvinceCode());
+                                item.put("fieldValueName", policyHolderInfo.getProvince());
+                                item.put("areaCodeList", List.of(policyHolderInfo.getProvinceCode(),
+                                        policyHolderInfo.getCityCode(),
+                                        policyHolderInfo.getCountyCode()
+                                ));
+                                item.put("remarks", policyHolderInfo.getProvince());
+                                item.put("display", "block");
+                                break;
+                            case "cityCode":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", policyHolderInfo.getCityCode());
+                                item.put("fieldValueName", policyHolderInfo.getCity());
+                                item.put("remarks", policyHolderInfo.getCity());
+                                item.put("display", "none");
+                                break;
+                            case "districtCode":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", policyHolderInfo.getCountyCode());
+                                item.put("fieldValueName", policyHolderInfo.getCounty());
+                                item.put("remarks",  policyHolderInfo.getCounty());
+                                item.put("display", "none");
+                                break;
+                            case "email":
+                                if (item.get("type") == null) {
+                                    item.put("display", "block");
+                                }
+                                break;
+                        }
+                    }
+                    newInfoList.add(item);
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+
+            // ====================== sortNo = 100 ======================
+            else if (sortNo == 100) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    String type = item.getString("type");
+
+                    if ("1".equals(type)) {
+                        switch (fieldName) {
+                            case "relationToApplicantCode":
+                                item.put("fieldValue", "1");
+                                item.put("fieldValueName", "本人");
+                                item.put("display", "block");
+                                break;
+                            case "customerName":
+                                item.put("display", "none");
+                                String bbEncName = RsaUtils.encrypt(insuredPersonInfo.getName());
+                                item.put("fieldValue", bbEncName);
+                                item.put("fieldValueName", bbEncName);
+                                break;
+                            case "mobile":
+                                item.put("display", "none");
+                                String bbEncPhone = RsaUtils.encrypt(insuredPersonInfo.getMobile());
+                                item.put("fieldValue", bbEncPhone);
+                                item.put("fieldValueName", bbEncPhone);
+                                break;
+                            case "identifyType":
+                                item.put("display", "none");
+                                item.put("fieldValueName", "居民身份证");
+                                break;
+                            case "identifyNumber":
+                                item.put("display", "none");
+                                String bbEncIdNo = RsaUtils.encrypt(insuredPersonInfo.getIdentifyNumber());
+                                item.put("fieldValue", bbEncIdNo);
+                                item.put("fieldValueName", bbEncIdNo);
+                                break;
+                            case "sex":
+                                String sexVal = item.getString("fieldValueName");
+                                item.put("fieldValueName", "2".equals(sexVal) ? "女" : "男");
+                                item.put("display", "none");
+                                break;
+                            case "citizenship":
+                            case "age":
+                                item.put("display", "none");
+                                break;
+                            case "identifyEffectiveStartDate":
+                                String today = LocalDate.now().toString();
+                                item.put("minDate", "1900-01-01");
+                                item.put("maxDate", today);
+                                item.put("display", "none");
+                                item.put("mustFill", "0");
+                                break;
+                            case "identifyEffectiveTerm":
+                                item.put("display", "none");
+                                item.put("mustFill", "0");
+                                break;
+                            case "provinceCode":
+                                item.put("fieldValue", insuredPersonInfo.getProvinceCode());
+                                item.put("fieldValueName", insuredPersonInfo.getProvince());
+                                item.put("fieldDescribe", "省市地区");
+                                item.put("remarks", insuredPersonInfo.getProvince());
+                                item.put("areaCodeList", List.of(
+                                        insuredPersonInfo.getProvinceCode(),
+                                        insuredPersonInfo.getCityCode(),
+                                        insuredPersonInfo.getCountyCode()
+                                ));
+                                item.put("display", "none");
+                                break;
+                            case "cityCode":
+                                item.put("fieldValue", insuredPersonInfo.getCityCode());
+                                item.put("fieldValueName", insuredPersonInfo.getCity());
+                                item.put("remarks", insuredPersonInfo.getCity());
+                                item.put("display", "none");
+                                break;
+                            case "districtCode":
+                                item.put("fieldValue", insuredPersonInfo.getCountyCode());
+                                item.put("fieldValueName", insuredPersonInfo.getCounty());
+                                item.put("remarks",  insuredPersonInfo.getCounty());
+                                item.put("display", "none");
+                                break;
+                        }
+                    }
+                    newInfoList.add(item);
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+
+            // ====================== sortNo = 200 ======================
+            else if (sortNo == 200) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+
+                    if (item.get("type") == null) {
+                        switch (fieldName) {
+                            case "licensePlateNo":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encLicense = RsaUtils.encrypt(carInfoVo.getLicenseNo());
+                                item.put("fieldValue", encLicense);
+                                item.put("fieldValueName", encLicense);
+                                break;
+                            case "engineNumber":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encEngine = RsaUtils.encrypt(carInfoVo.getEngineNo());
+                                item.put("fieldValue", encEngine);
+                                item.put("fieldValueName", encEngine);
+                                break;
+                            case "frameNo":
+                                item.put("fieldType", "-1");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                String encVin = RsaUtils.encrypt(carInfoVo.getVinNo());
+                                item.put("fieldValue", encVin);
+                                item.put("fieldValueName", encVin);
+                                break;
+                            case "passengersNumber":
+                                item.put("readonly", "1");
+                                String seatNum = carInfoVo.getSeatCount();
+                                item.put("fieldValue", seatNum);
+                                item.put("fieldValueName", seatNum + "座");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                break;
+                            case "carUserNatureCode":
+                                item.put("readonly", "1");
+                                item.put("fieldValue", "8A");
+                                item.put("fieldValueName", "家庭自用");
+                                item.put("mustFill", "2");
+                                item.put("display", "block");
+                                break;
+                        }
+                    }
+                    newInfoList.add(item);
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+
+            // ====================== sortNo = 300 / 600 ======================
+            else if (sortNo == 300 || sortNo == 600) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    if (item.get("type") == null && "passengersNumber".equals(fieldName)) {
+                        item.put("fieldValue", String.valueOf(seat));
+                        item.put("fieldValueName", seat + "座");
+                        newInfoList.add(item);
+                    }
+                }
+            }
+
+            // ====================== sortNo = 9999 ======================
+            else if (sortNo == 9999) {
+                for (int j = 0; j < infoList.size(); j++) {
+                    JSONObject item = infoList.getJSONObject(j);
+                    String fieldName = item.getString("backEndTranslationNameYl");
+                    if (item.get("type") == null && "mark1".equals(fieldName)) {
+                        item.put("display", "block");
+                        newInfoList.add(item);
+                    }
+                }
+                modular.put("selected", true);
+                modular.put("ncispUnderwritingInfoList", newInfoList);
+            }
+        }
+
+
+    }
+
+
+
+    public static MultiValueMap<String, String> jsonToMultiValueMap(JSONObject json) {
+        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
+
+        if (json == null || json.isEmpty()) {
+            return map;
+        }
+
+        // 遍历所有 key
+        for (String key : json.keySet()) {
+            Object value = json.get(key);
+            // 转成字符串(null 转空串)
+            String strValue = value == null ? "" : String.valueOf(value);
+            map.add(key, strValue);
+        }
+
+        return map;
+    }
+
+
     /**
      * 重复报价处理(处理重复投保问题)
      *
      * @param premiumCalculateResponse 报价响应
      * @return 最终报价结果
      */
-    public QuoteResultsVo repeat(PremiumCalculateResponse premiumCalculateResponse, String orderNo, String redisValue, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
-                                 GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode, String token, String syShow) {
+    public QuoteResultsVo repeat(PremiumCalculateResponse premiumCalculateResponse, String orderNo,RedisResultDTO redisResultDTO, QuoteVo quoteVo, CarInsuranceQueryResponse.CarInsuranceData insuranceInformation, UserInfoResponse.UserData loginInfo,
+                                 GsCrawlerCarQueryResponse.VehicleModelDetail vehicleModelDetail, JSONObject bindInfo, String businessNatureCode, String token, String syShow,String userID,JSONObject jsonObject) {
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         // 2. 处理商业险重复投保
         String jqRepeatinfo = "";
         String syRepeatinfo = "";
         String msg = premiumCalculateResponse.getMsg();
-        String doubleMsg = premiumCalculateResponse.getData().getDoubleMsg();
-        if (msg.contains("商业险") && msg.contains("重复投保")) {
-            String sy = DateUtils.getTime(doubleMsg);
-            log.info("商业险重复投保,更新开始日期,newChesunStartDate:{}", sy);
-            // 重新报价
-            return calculation(orderNo, redisValue, quoteVo, insuranceInformation, loginInfo,
-                    vehicleModelDetail, bindInfo, businessNatureCode);
-
+        if (msg.contains("商业险") && msg.contains("重复投保") && msg.contains("保险期间:")) {
+            if (msg.contains("<br")) {
+                String sy = DateUtils.getTime(msg);
+                log.info("商业险重复投保,更新开始日期,newChesunStartDate:{}", sy);
+                RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
+                biRiskInfoVo.setStartDate("");
+                biRiskInfoVo.setEndDate("");
+                // 重新报价
+                return calculation(orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo,
+                        vehicleModelDetail, bindInfo, businessNatureCode,jsonObject);
+            }else {
+                quoteResultsVo.setErrorMessage(msg);
+                quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+            }
         } // 3. 处理交强险重复投保
-        else if (msg.contains("交强险") && msg.contains("重复投保")) {
-            String jq = DateUtils.getTime(doubleMsg);
-            quoteVo.getCiRiskInfoVo().setStartDate(jq);
-            return calculation(orderNo, redisValue, quoteVo, insuranceInformation, loginInfo,
-                    vehicleModelDetail, bindInfo, businessNatureCode);
+        else if (msg.contains("交强险") && msg.contains("重复投保") && msg.contains("终保日期")) {
+            if (msg.contains("保单号") && msg.contains("起保日期") && msg.contains("终保日期")) {
+                String startTime = extractDuplicateEndTime(msg);
+                String endTime = TimeProcessing.minusOneSecondAfterYear(startTime);
+                quoteVo.getCiRiskInfoVo().setStartDate(startTime);
+                quoteVo.getCiRiskInfoVo().setEndDate(endTime);
+                return calculation(orderNo, redisResultDTO, quoteVo, insuranceInformation, loginInfo,
+                        vehicleModelDetail, bindInfo, businessNatureCode,jsonObject);
+            }else {
+                quoteResultsVo.setErrorMessage(msg);
+                quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+            }
         } // 4. 报价失败处理
         else if (!"200".equals(premiumCalculateResponse.getStatus())) {
             String info = "";
@@ -695,9 +1137,26 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             quoteResultsVo.setErrorMessage(errorMsg);
             quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
         } else if ("200".equals(premiumCalculateResponse.getStatus())) {
-            FeeCalculateResponse.DataDTO dataDTO = gsCrawlerRequestComponent.creatOrder(token, CreatOrderRequest.creatOrderRequest(premiumCalculateResponse.getData(), syShow, redisValue, loginInfo));
+
+            get_fcxdata( quoteVo, token, userID, businessNatureCode, loginInfo, orderNo,vehicleModelDetail.getSeat(),jsonObject);
+
+
+            FeeCalculateResponse.DataDTO dataDTO = gsCrawlerRequestComponent.creatOrder(token, CreatOrderRequest.creatOrderRequest(premiumCalculateResponse.getData(), syShow,redisResultDTO.getUserID(), loginInfo));
             Object businessCalcFeeVo = dataDTO.getBusinessCalcFeeVo();
-            String sy_discountRate = "";
+
+            return processCalcSuccessResult(premiumCalculateResponse, quoteVo, token);
+        } else {
+            quoteResultsVo.setErrorMessage("报价失败");
+            quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+        }
+        return quoteResultsVo;
+    }
+
+
+    /*
+
+
+   String sy_discountRate = "";
             String discountRate = "";
             if (businessCalcFeeVo != null) {
                 sy_discountRate = JSONObject.parseObject(JSONObject.toJSONString(businessCalcFeeVo)).getString("'discountRate'");
@@ -713,8 +1172,8 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             saveRedis.put("username", loginInfo.getUserCode());
             saveRedis.put("businessOffice", loginInfo.getUserDepartment());
             saveRedis.put("structureId", loginInfo.getProvincialCom());
-            saveRedis.put("userCode", JSONObject.parseObject(redisValue).getString("userID"));
-            saveRedis.put("token", JSONObject.parseObject(redisValue).getString("token"));
+            saveRedis.put("userCode", redisResultDTO.getUserID());
+            saveRedis.put("token",redisResultDTO.getToken());
             saveRedis.put("license", quoteVo.getCarInfoVo().getLicenseNo());
             saveRedis.put("zhanghao_info", loginInfo.getProvincialCom());
             saveRedis.put("gs_info", JSONObject.toJSONString(bindInfo));
@@ -728,6 +1187,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             if ("200".equals(premiumCalculateResponse.getStatus())) {
                 PremiumCalculateResponse.OrderVoDTO resOrderVo = premiumCalculateResponse.getData().getOrderVo();
                 tranNo = resOrderVo.getTransactionNo();
+
                 orderId = resOrderVo.getOrderNo();
             }
             saveRedis.put("orderId", orderId);
@@ -735,14 +1195,23 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             saveRedis.put("bj_res", JSONObject.toJSONString(premiumCalculateResponse));
             saveRedis.put("bjresdata", JSON.toJSONString(premiumCalculateResponse.getData()));
             redisTemplate.opsForValue().set(GsConstants.GS_REDIS_QUOTE_KEY + quoteVo.getOrder().getOrdersNo(), JSONObject.toJSONString(saveRedis), GsConstants.REDIS_EXPIRE_SECONDS, TimeUnit.SECONDS);
-            return processCalcSuccessResult(premiumCalculateResponse, quoteVo, token);
-        } else {
-            quoteResultsVo.setErrorMessage("报价失败");
-            quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
+
+    * */
+
+
+    // 截取重复投保终保日期
+    private static final Pattern DUPLICATE_END_TIME_PATTERN = Pattern.compile("终保日期 (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})");
+    private String extractDuplicateEndTime(String returnMessage) {
+        Matcher matcher = DUPLICATE_END_TIME_PATTERN.matcher(returnMessage);
+        if (matcher.find()) {
+            String shortEndTime = matcher.group(1);
+            return shortEndTime + ":00";
         }
-        return quoteResultsVo;
+        return null;
     }
 
+
+
     /**
      * 处理报价成功结果
      *
@@ -1008,7 +1477,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     /**
      * 图片上传
      */
-    public JSONObject upload(List<InsuranceImageVo> imageVoList, String JQ_Policy, String SY_Policy, String JYX_Policy, UserInfoResponse.UserData loginInfo, JSONObject bindInfo, JSONObject quoteInfo, String redisValue) {
+    public JSONObject upload(List<InsuranceImageVo> imageVoList, String JQ_Policy, String SY_Policy, String JYX_Policy, UserInfoResponse.UserData loginInfo, JSONObject bindInfo, JSONObject quoteInfo, String token) {
         String ryMessage = null; // 人员照片错误
         String rybMessage = null; // 人员照片背面错误
         String clMessage = null; // 行驶证照片错误
@@ -1018,7 +1487,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
             InsuranceImageVo.ImageDTO imageDTO = insuranceImageVo.getImageBase64List().get(0);
             // 构建图片请求参数
             ImageUploadRequest uploadRequest = new ImageUploadRequest(imageDTO, quoteInfo, loginInfo, JQ_Policy, SY_Policy, imageType);
-            CheckImageResponse checkImage = gsCrawlerRequestComponent.doCheckImage(redisValue, uploadRequest);
+            CheckImageResponse checkImage = gsCrawlerRequestComponent.doCheckImage(token, uploadRequest);
             if (!"200".equals(checkImage.getStatus()) && !"201".equals(checkImage.getStatus())) {
                 log.error("图片上传失败:{}", checkImage.getMsg());
                 String imageMsg = checkImage.getMsg();
@@ -1043,7 +1512,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
                 continue;
             }
             UploadImagesRequest imageBusinessRequest = new UploadImagesRequest(loginInfo, JQ_Policy, SY_Policy, imageType, checkImage.getData(), quoteInfo, imageDTO.getImageBase64Str());
-            gsCrawlerRequestComponent.uploadImages(imageBusinessRequest, redisValue);
+            gsCrawlerRequestComponent.uploadImages(imageBusinessRequest, token);
         }
 
         // 构建返回结果
@@ -1093,7 +1562,7 @@ public class GuoshouCrawlerRequestImpl implements GuoshouCrawlerRequest {
     public void revocation(String orderNo) {
 //        String userName = "";
 //        // 查询loginInfo
-//        UserInfoResponse.UserData loginInfo = getLoginInfo(attributionInformationVo);
+//        UserInfoResponse.UserData loginInfo = gsCrawlerLoginComponent.getLoginInfo(attributionInformationVo);
 //        String redisValue = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_LOGIN_KEY+ attributionInformationVo.getConfigInfo().get("username"));
 //        String quote = redisTemplate.opsForValue().get(GsConstants.GS_REDIS_QUOTE_KEY + orderNo);
 //        String token = JSONObject.parseObject(redisValue).getString("token");

+ 452 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/util/ModularDataProcessor.java

@@ -0,0 +1,452 @@
+package com.jzg.quotation.guoshou.crawler.util;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.jzg.commons.entity.quote.vo.CarInfoVo;
+import com.jzg.commons.entity.quote.vo.CustomerInfoVo;
+import com.jzg.commons.entity.quote.vo.QuoteVo;
+import com.jzg.commons.entity.quote.vo.RiskInfoVo;
+import com.jzg.quotation.guoshou.crawler.entity.response.UserInfoResponse;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 模块化数据处理器 - 优化版
+ * 功能:根据产品白名单处理核保信息模块,填充、加密、显隐控制字段
+ * 保留所有JSON null字段
+ */
+
+@Component
+public class ModularDataProcessor {
+
+    // ====================== 常量定义 ======================
+    /** 白名单产品ID */
+    private static final List<String> VALID_PRODUCT_IDS = List.of(
+            "fd2dc8abe5f94eacbc8efd3bf62a8581",
+            "39f47efbd6004899b4fa7c80bfdba801",
+            "54b7cce17316444aade70427d8abea0a",
+            "7e1108d1db2c428d8cf35e3e6896bb15",
+            "fc9cd193ce444508b355b5d5522ffc00",
+            "71d3c2271fe5404d82c78fb07d116cf0",
+            "77bcfb9bff014a93bfca0ed792c30258",
+            "new-2d0bc85a46c799ff4ad0c8521348",
+            "f65730fe001a4c998aabc1d2e7258a96"
+    );
+
+    private static final String TYPE_1 = "1";
+    private static final String DISPLAY_BLOCK = "block";
+    private static final String DISPLAY_NONE = "none";
+    private static final String MUST_FILL_0 = "0";
+    private static final String MUST_FILL_2 = "2";
+    private static final String FIELD_TYPE_NEGATIVE_1 = "-1";
+    private static final String READONLY_1 = "1";
+
+    public void processModularData(JSONArray modularList, String productId, QuoteVo quoteVo,
+                                   String seat, JSONObject jsonObject, UserInfoResponse.UserData loginInfo,
+                                   String branchOfficeName, JSONObject data8vo) {
+        // 非白名单产品直接返回
+        if (!VALID_PRODUCT_IDS.contains(productId)) {
+            return;
+        }
+
+        // 提取基础信息(空值安全)
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        CustomerInfoVo policyHolder = quoteVo.getPolicyHolderInfo();
+        CustomerInfoVo insuredPerson = quoteVo.getInsuredPersonInfo();
+
+        // 遍历模块列表
+        for (int i = 0; i < modularList.size(); i++) {
+            JSONObject modular = modularList.getJSONObject(i);
+            if (modular == null) {
+                continue;
+            }
+
+            Integer sortNo = modular.getInteger("sortNo");
+            JSONArray infoList = modular.getJSONArray("ncispUnderwritingInfoList");
+            if (sortNo == null || infoList == null) {
+                continue;
+            }
+
+            // 根据sortNo处理对应模块
+            JSONArray newInfoList = switch (sortNo) {
+                case 0 -> handleSortNoZero(infoList, policyHolder);
+                case 100 -> handleSortNoHundred(infoList, insuredPerson);
+                case 200 -> handleSortNoTwoHundred(infoList, carInfoVo);
+                case 300, 600 -> handleSortNoThreeHundredOrSixHundred(infoList, seat);
+                case 9999 -> handleSortNoMax(infoList);
+                default -> new JSONArray();
+            };
+
+            // 模块统一设置(保留原有逻辑)
+            if (List.of(0, 100, 200, 9999).contains(sortNo)) {
+                modular.put("selected", true);
+            }
+            // 保留所有null字段,强制覆盖
+            modular.put("ncispUnderwritingInfoList", newInfoList);
+        }
+
+        overwriteData(data8vo, productId, jsonObject, loginInfo, branchOfficeName, quoteVo);
+
+    }
+
+    // ====================== 模块处理方法(拆分后职责单一) ======================
+
+    /**
+     * 处理 sortNo = 0 投保人信息模块
+     */
+    private JSONArray handleSortNoZero(JSONArray infoList, CustomerInfoVo policyHolder) {
+        JSONArray newList = new JSONArray();
+        String today = LocalDate.now().toString();
+
+        for (int i = 0; i < infoList.size(); i++) {
+            JSONObject item = infoList.getJSONObject(i);
+            if (item == null) {
+                newList.add(null); // 保留null
+                continue;
+            }
+
+            String fieldName = item.getString("backEndTranslationNameYl");
+            String type = item.getString("type");
+
+            if (TYPE_1.equals(type)) {
+                switch (fieldName) {
+                    case "customerName" -> setEncryptedField(item, policyHolder.getName());
+                    case "mobile" -> setEncryptedField(item, policyHolder.getMobile());
+                    case "identifyType" -> {
+                        item.put("readonly", READONLY_1);
+                        item.put("fieldValue", "idCard");
+                        item.put("fieldValueName", "居民身份证");
+                        item.put("mustFill", MUST_FILL_2);
+                        item.put("display", DISPLAY_BLOCK);
+                    }
+                    case "identifyNumber" -> setEncryptedField(item, policyHolder.getIdentifyNumber());
+                    case "age" -> item.put("display", DISPLAY_NONE);
+                    case "sex" -> {
+                        String sexVal = item.getString("fieldValueName");
+                        item.put("fieldValueName", "2".equals(sexVal) ? "女" : "男");
+                        item.put("fieldValue", "1");
+                        item.put("display", DISPLAY_NONE);
+                    }
+                    case "identifyEffectiveStartDate" -> {
+                        item.put("fieldType", FIELD_TYPE_NEGATIVE_1);
+                        item.put("mustFill", MUST_FILL_0);
+                        item.put("display", DISPLAY_BLOCK);
+                        item.put("minDate", "1900-01-01");
+                        item.put("maxDate", today);
+                    }
+                    case "identifyEffectiveTerm" -> {
+                        item.put("fieldType", FIELD_TYPE_NEGATIVE_1);
+                        item.put("fieldValue", "100");
+                        item.put("mustFill", MUST_FILL_0);
+                        item.put("display", DISPLAY_BLOCK);
+                    }
+                    case "citizenship" -> item.put("display", DISPLAY_BLOCK);
+                    case "provinceCode" -> {
+                        item.put("readonly", READONLY_1);
+                        item.put("fieldDescribe", "省市地区");
+                        item.put("fieldValue", policyHolder.getProvinceCode());
+                        item.put("fieldValueName", policyHolder.getProvince());
+                        item.put("areaCodeList", List.of(
+                                policyHolder.getProvinceCode(),
+                                policyHolder.getCityCode(),
+                                policyHolder.getCountyCode()
+                        ));
+                        item.put("remarks", policyHolder.getProvince());
+                        item.put("display", DISPLAY_BLOCK);
+                    }
+                    case "cityCode" -> {
+                        item.put("readonly", READONLY_1);
+                        item.put("fieldValue", policyHolder.getCityCode());
+                        item.put("fieldValueName", policyHolder.getCity());
+                        item.put("remarks", policyHolder.getCity());
+                        item.put("display", DISPLAY_NONE);
+                    }
+                    case "districtCode" -> {
+                        item.put("readonly", READONLY_1);
+                        item.put("fieldValue", policyHolder.getCountyCode());
+                        item.put("fieldValueName", policyHolder.getCounty());
+                        item.put("remarks", policyHolder.getCounty());
+                        item.put("display", DISPLAY_NONE);
+                    }
+                    case "email" -> {
+                        if (item.get("type") == null) {
+                            item.put("display", DISPLAY_BLOCK);
+                        }
+                    }
+                }
+            }
+            newList.add(item); // 保留所有字段,包括null
+        }
+        return newList;
+    }
+
+    /**
+     * 处理 sortNo = 100 被保人信息模块
+     */
+    private JSONArray handleSortNoHundred(JSONArray infoList, CustomerInfoVo insuredPerson) {
+        JSONArray newList = new JSONArray();
+        String today = LocalDate.now().toString();
+
+        for (int i = 0; i < infoList.size(); i++) {
+            JSONObject item = infoList.getJSONObject(i);
+            if (item == null) {
+                newList.add(null);
+                continue;
+            }
+
+            String fieldName = item.getString("backEndTranslationNameYl");
+            String type = item.getString("type");
+
+            if (TYPE_1.equals(type)) {
+                switch (fieldName) {
+                    case "relationToApplicantCode" -> {
+                        item.put("fieldValue", "1");
+                        item.put("fieldValueName", "本人");
+                        item.put("display", DISPLAY_BLOCK);
+                    }
+                    case "customerName" -> {
+                        item.put("display", DISPLAY_NONE);
+                        setEncryptedFieldValueOnly(item, insuredPerson.getName());
+                    }
+                    case "mobile" -> {
+                        item.put("display", DISPLAY_NONE);
+                        setEncryptedFieldValueOnly(item, insuredPerson.getMobile());
+                    }
+                    case "identifyType" -> {
+                        item.put("display", DISPLAY_NONE);
+                        item.put("fieldValueName", "居民身份证");
+                    }
+                    case "identifyNumber" -> {
+                        item.put("display", DISPLAY_NONE);
+                        setEncryptedFieldValueOnly(item, insuredPerson.getIdentifyNumber());
+                    }
+                    case "sex" -> {
+                        String sexVal = item.getString("fieldValueName");
+                        item.put("fieldValueName", "2".equals(sexVal) ? "女" : "男");
+                        item.put("display", DISPLAY_NONE);
+                    }
+                    case "citizenship", "age" -> item.put("display", DISPLAY_NONE);
+                    case "identifyEffectiveStartDate" -> {
+                        item.put("minDate", "1900-01-01");
+                        item.put("maxDate", today);
+                        item.put("display", DISPLAY_NONE);
+                        item.put("mustFill", MUST_FILL_0);
+                    }
+                    case "identifyEffectiveTerm" -> {
+                        item.put("display", DISPLAY_NONE);
+                        item.put("mustFill", MUST_FILL_0);
+                    }
+                    case "provinceCode" -> {
+                        item.put("fieldValue", insuredPerson.getProvinceCode());
+                        item.put("fieldValueName", insuredPerson.getProvince());
+                        item.put("fieldDescribe", "省市地区");
+                        item.put("remarks", insuredPerson.getProvince());
+                        item.put("areaCodeList", List.of(
+                                insuredPerson.getProvinceCode(),
+                                insuredPerson.getCityCode(),
+                                insuredPerson.getCountyCode()
+                        ));
+                        item.put("display", DISPLAY_NONE);
+                    }
+                    case "cityCode" -> {
+                        item.put("fieldValue", insuredPerson.getCityCode());
+                        item.put("fieldValueName", insuredPerson.getCity());
+                        item.put("remarks", insuredPerson.getCity());
+                        item.put("display", DISPLAY_NONE);
+                    }
+                    case "districtCode" -> {
+                        item.put("fieldValue", insuredPerson.getCountyCode());
+                        item.put("fieldValueName", insuredPerson.getCounty());
+                        item.put("remarks", insuredPerson.getCounty());
+                        item.put("display", DISPLAY_NONE);
+                    }
+                }
+            }
+            newList.add(item);
+        }
+        return newList;
+    }
+
+    /**
+     * 处理 sortNo = 200 车辆信息模块
+     */
+    private JSONArray handleSortNoTwoHundred(JSONArray infoList, CarInfoVo carInfoVo) {
+        JSONArray newList = new JSONArray();
+
+        for (int i = 0; i < infoList.size(); i++) {
+            JSONObject item = infoList.getJSONObject(i);
+            if (item == null) {
+                newList.add(null);
+                continue;
+            }
+
+            String fieldName = item.getString("backEndTranslationNameYl");
+            if (item.get("type") == null) {
+                switch (fieldName) {
+                    case "licensePlateNo" -> setEncryptedField(item, carInfoVo.getLicenseNo());
+                    case "engineNumber" -> setEncryptedField(item, carInfoVo.getEngineNo());
+                    case "frameNo" -> setEncryptedField(item, carInfoVo.getVinNo());
+                    case "passengersNumber" -> {
+                        item.put("readonly", READONLY_1);
+                        String seatNum = carInfoVo.getSeatCount();
+                        item.put("fieldValue", seatNum);
+                        item.put("fieldValueName", seatNum + "座");
+                        item.put("mustFill", MUST_FILL_2);
+                        item.put("display", DISPLAY_BLOCK);
+                    }
+                    case "carUserNatureCode" -> {
+                        item.put("readonly", READONLY_1);
+                        item.put("fieldValue", "8A");
+                        item.put("fieldValueName", "家庭自用");
+                        item.put("mustFill", MUST_FILL_2);
+                        item.put("display", DISPLAY_BLOCK);
+                    }
+                }
+            }
+            newList.add(item);
+        }
+        return newList;
+    }
+
+    /**
+     * 处理 sortNo = 300 / 600 座位数模块
+     */
+    private JSONArray handleSortNoThreeHundredOrSixHundred(JSONArray infoList, String seat) {
+        JSONArray newList = new JSONArray();
+        for (int i = 0; i < infoList.size(); i++) {
+            JSONObject item = infoList.getJSONObject(i);
+            if (item == null) {
+                newList.add(null);
+                continue;
+            }
+
+            String fieldName = item.getString("backEndTranslationNameYl");
+            if (item.get("type") == null && "passengersNumber".equals(fieldName)) {
+                item.put("fieldValue", String.valueOf(seat));
+                item.put("fieldValueName", seat + "座");
+                newList.add(item);
+            }
+        }
+        return newList;
+    }
+
+    /**
+     * 处理 sortNo = 9999 备注模块
+     */
+    private JSONArray handleSortNoMax(JSONArray infoList) {
+        JSONArray newList = new JSONArray();
+        for (int i = 0; i < infoList.size(); i++) {
+            JSONObject item = infoList.getJSONObject(i);
+            if (item == null) {
+                newList.add(null);
+                continue;
+            }
+
+            String fieldName = item.getString("backEndTranslationNameYl");
+            if (item.get("type") == null && "mark1".equals(fieldName)) {
+                item.put("display", DISPLAY_BLOCK);
+                newList.add(item);
+            }
+        }
+        return newList;
+    }
+
+    // ====================== 通用工具方法(复用逻辑) ======================
+
+    /**
+     * 设置加密字段(通用投保人/车辆)
+     */
+    private void setEncryptedField(JSONObject item, String rawValue) {
+        item.put("fieldType", FIELD_TYPE_NEGATIVE_1);
+        item.put("mustFill", MUST_FILL_2);
+        item.put("display", DISPLAY_BLOCK);
+        String encrypted = RsaUtils.encrypt(rawValue);
+        item.put("fieldValue", encrypted);
+        item.put("fieldValueName", encrypted);
+    }
+
+    /**
+     * 仅加密赋值,不修改显示/必填属性(被保人专用)
+     */
+    private void setEncryptedFieldValueOnly(JSONObject item, String rawValue) {
+        String encrypted = RsaUtils.encrypt(rawValue);
+        item.put("fieldValue", encrypted);
+        item.put("fieldValueName", encrypted);
+    }
+
+
+
+
+    public void overwriteData(com.alibaba.fastjson2.JSONObject secondData, String productId, com.alibaba.fastjson2.JSONObject jsonObject, UserInfoResponse.UserData loginInfo, String branchOfficeName, QuoteVo quoteVo){
+        if ("fd2dc8abe5f94eacbc8efd3bf62a8581".equals(productId)
+                || "39f47efbd6004899b4fa7c80bfdba801".equals(productId)
+                || "54b7cce17316444aade70427d8abea0a".equals(productId)
+                || "7e1108d1db2c428d8cf35e3e6896bb15".equals(productId)
+                || "fc9cd193ce444508b355b5d5522ffc00".equals(productId)
+                || "71d3c2271fe5404d82c78fb07d116cf0".equals(productId)
+                || "77bcfb9bff014a93bfca0ed792c30258".equals(productId)
+                || "new-2d0bc85a46c799ff4ad0c8521348".equals(productId)
+                || "f65730fe001a4c998aabc1d2e7258a96".equals(productId)) {
+            secondData.put("salesmanCode",loginInfo.getUserCode());
+            secondData.put("channelType", loginInfo.getChannelType());
+            secondData.put("lockType", "0");
+            secondData.put("recommendGarageFlag", "0");
+            secondData.put("remarks", "");
+            secondData.put("selectGroupId", null);
+            secondData.put("fromCarSystemSource", "gstc");
+            secondData.put("orderSource", "0");
+            secondData.put("policyHolderTypeOption", null);
+            secondData.put("policyHolderType", "1");
+            secondData.put("insuredPersonType", "1");
+            secondData.put("insuredPersonTypeOption", null);
+            secondData.put("saleAgreementNo", jsonObject.getString("saleAgreementNo"));
+            secondData.put("businessNatureName", jsonObject.getString("businessNatureName"));
+            secondData.put("salesman", jsonObject.getString("salesman"));
+
+
+            secondData.put("comCode", loginInfo.getUserDepartment());
+
+            secondData.put("systemSource", "fromCar");
+
+            secondData.put("saleAgreementName", jsonObject.getString("userAgentName"));
+
+            secondData.put("businessOfficeName", branchOfficeName);
+            secondData.put("makeCom", loginInfo.getUserDepartment());
+            secondData.put("policeConfirmedFlag", "0");
+
+            // 三目运算 + 时间方法(完全对应Python)
+            RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
+            RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
+            String startDate;
+            String endDate;
+            if (Objects.nonNull(biRiskInfoVo)) {
+                startDate = biRiskInfoVo.getStartDate();
+                endDate = biRiskInfoVo.getEndDate();
+            } else {
+                startDate = ciRiskInfoVo.getStartDate();
+                endDate = ciRiskInfoVo.getEndDate();
+            }
+            secondData.put("startDate", startDate);
+            secondData.put("period", "");
+            secondData.put("recordClerkCode",loginInfo.getUserCode());
+            secondData.put("agreeCusFlag", "0");
+            secondData.put("endDate", endDate);
+
+            // 空值字段
+            secondData.put("docSalePracticeNo", (Object) null);
+            secondData.put("docSalesName", (Object) null);
+            secondData.put("docSalesPhone", (Object) null);
+            secondData.put("recommendGarageName", (Object) null);
+            secondData.put("recommendGarageCode", (Object) null);
+
+            secondData.put("businessNatureCode",jsonObject.getString("businessNatureCode"));
+            secondData.put("remarks",quoteVo.getCarInfoVo().getLicenseNo()); // 覆盖remarks
+        }
+    }
+
+
+
+}

+ 54 - 0
tenant/insurance/quotation-guoshou/src/main/java/com/jzg/quotation/guoshou/crawler/util/RsaUtils.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.guoshou.crawler.util;
 
+import com.alibaba.fastjson2.JSONObject;
 import lombok.extern.slf4j.Slf4j;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.slf4j.Logger;
@@ -7,6 +8,8 @@ import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
 import javax.crypto.Cipher;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.security.KeyFactory;
 import java.security.PrivateKey;
 import java.security.PublicKey;
@@ -14,6 +17,7 @@ import java.security.Security;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Base64;
+import java.util.Map;
 
 /**
  * RSA加密工具类(对应原Python RSA.js逻辑)
@@ -33,6 +37,12 @@ public class RsaUtils {
    // @Value("${business.rsa-public-key}")
     private static String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwGbMAecQuqsZ2hQELuqSHI+R8R0NcM9SNqw245OB/vDed4Z65z97YlrjG7+bE2CPs6TLNezYey/PqdeuUfbIaG6ou+FATs5y+MZQMEMpgJBMGvjivn0cNN5yICMM/G2ZdS66Hx5U1iK6yzsDi5o3rNpXsNzN36xLhSCVaZ96y1QIDAQAB";
 
+    private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwGbMAecQuqsZ2hQELuqSHI+R8" +
+            "R0NcM9SNqw245OB/vDed4Z65z97YlrjG7+bE2CPs6TLNezYey/PqdeuUfbIaG6ou" +
+            "+FATs5y+MZQMEMpgJBMGvjivn0cNN5yICMM/G2ZdS66Hx5U1iK6yzsDi5o3rNpXs" +
+            "NzN36xLhSCVaZ96y1QIDAQAB";
+
+
     static {
         // 加载BouncyCastleProvider
         Security.addProvider(new BouncyCastleProvider());
@@ -109,4 +119,48 @@ public class RsaUtils {
             throw new RuntimeException("RSA解密异常", e);
         }
     }
+
+
+    /**
+     * RSA分段加密(117字节分段)+ Base64
+     */
+    public static String generateSecretParameter(Map<String, Object> data) throws Exception {
+        // 加入时间戳
+        data.put("timestamp", System.currentTimeMillis());
+        // 紧凑JSON
+        String plainText = JSONObject.toJSONString(data);
+        // URL编码(等价JS encodeURIComponent)
+        String encoded = URLEncoder.encode(plainText, StandardCharsets.UTF_8.name()).replace("+", "%20");
+
+        // 加载公钥
+        byte[] keyBytes = Base64.getDecoder().decode(PUBLIC_KEY);
+        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory factory = KeyFactory.getInstance("RSA", "BC");
+        PublicKey publicKey = factory.generatePublic(spec);
+
+        // 分段加密(117字节)
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
+        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        byte[] encodedBytes = encoded.getBytes(StandardCharsets.UTF_8);
+        int chunkSize = 117;
+        byte[] result = new byte[0];
+
+        for (int i = 0; i < encodedBytes.length; i += chunkSize) {
+            int end = Math.min(i + chunkSize, encodedBytes.length);
+            byte[] chunk = new byte[end - i];
+            System.arraycopy(encodedBytes, i, chunk, 0, chunk.length);
+            byte[] encrypted = cipher.doFinal(chunk);
+
+            // 拼接结果
+            byte[] temp = new byte[result.length + encrypted.length];
+            System.arraycopy(result, 0, temp, 0, result.length);
+            System.arraycopy(encrypted, 0, temp, result.length, encrypted.length);
+            result = temp;
+        }
+
+        return Base64.getEncoder().encodeToString(result);
+    }
+
+
+
 }

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

@@ -3722,7 +3722,7 @@ public class RenBaoNewCrawlerRequestBuilder {
         }
         // 驾意险处理
         List<Map<String, Object>> unionRMsgVoList = data.getUnionRMsgVoList();
-        if(!unionRMsgVoList.isEmpty()){
+        if(unionRMsgVoList != null && !unionRMsgVoList.isEmpty()){
             List<Map<String, Object>> newPrpCunion =new ArrayList<>();
             for(Map<String, Object> map :unionRMsgVoList){
                 Map m = new HashMap<>();

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

@@ -899,7 +899,7 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
                 costs.setBiPremium(biPremium.toString());
             }
             List<Map<String, Object>> unionRMsgVoList = quoteResponse.getData().getUnionRMsgVoList();
-            if(!unionRMsgVoList.isEmpty()){
+            if(unionRMsgVoList != null && !unionRMsgVoList.isEmpty()){
                 if (unionRMsgVoList != null) {
                     for (Map<String, Object> underwriting : unionRMsgVoList) {
                         Object val = underwriting.get("uPremiums");
@@ -1939,7 +1939,7 @@ public class RenBaoNewCrawlerRequestImpl implements RenBaoNewCrawlerRequest {
     private LoginInfoBO getLoginInfo(AttributionInformationVo attributionInfo) {
         RenBaoNewCrawlerConfigureParameters parameters = ConfigureParametersConversion
                 .conversionEntity(RenBaoNewCrawlerConfigureParameters.class, attributionInfo.getConfigInfo());
-        String jwt = requestComponent.getJwtToken(parameters.getUserCode());
+        String jwt = requestComponent.getJwtToken(attributionInfo.getUsername());
         if(jwt.isEmpty()){
             jwt = attributionInfo.getPassword();
         }

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

@@ -570,9 +570,24 @@ public class OrderOperationLogAspect {
             pamentTrack.setResult("调用接口获取订单支付码并生成掌柜支付码");
             traceService.save(pamentTrack);
         }else{
-            UnderwritingResultsVo res = JSON.parseObject(JSON.toJSONString(extracted.get("data"))).toJavaObject(UnderwritingResultsVo.class);
             track.setStatus(QuoteNumberConstant.QuoteResult.FAIL.getCode());
-            track.setResult(res.getUnderwritingResult());
+            // 优先从 data 中的 UnderwritingResultsVo 获取核保失败原因
+            String failResult = null;
+            Object dataObj = extracted.get("data");
+            if (dataObj != null) {
+                UnderwritingResultsVo res = JSON.parseObject(JSON.toJSONString(dataObj)).toJavaObject(UnderwritingResultsVo.class);
+                if (res != null) {
+                    failResult = res.getUnderwritingResult();
+                    logger.info("---核保失败,订单号:{},失败原因:{}", orderId, failResult);
+                }
+            }
+            // data 为空或 underwritingResult 为空时,兜底取 HttpResult 的 msg
+            if (failResult == null) {
+                Object msgObj = extracted.get("msg");
+                failResult = msgObj != null ? msgObj.toString() : "核保失败";
+                logger.info("----核保失败,订单号:{},失败原因:{}", orderId, failResult);
+            }
+            track.setResult(failResult);
             InsOrderStatusEnum orderStatusEnum = InsOrderStatusEnum.matchKey(insOrders.getOrderStatus());
             track.setChangeAfter(orderStatusEnum.getDesc());
             traceService.save(track);

+ 5 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/api/constant/TransCode.java

@@ -57,4 +57,9 @@ public class TransCode {
      * 获取非车方案
      */
     public static final String BASE_CODE_SCHEME = "BaseCodeScheme";
+
+    /**
+     * 获取审核意见
+     */
+    public static final String SEARCHCOMMONVIEWTRACE = "SEARCHCOMMONVIEWTRACE";
 }

+ 24 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/build/ZmCrawlerQuoteResultVoBuild.java

@@ -196,6 +196,30 @@ public final class ZmCrawlerQuoteResultVoBuild {
                         .fluentPut("scoreName", "商业不浮动原因")
                         .fluentPut("scoreKey","SyRateFloatFlag")
                         .fluentPut("score", ZmCrawlerFloatFlag.getNoAdjustReasonDesc(noAjustReasonCode)));
+                Double c27AdjustRate = adjustList.stream()
+                        .filter(adjust -> adjust.getAdjustCode().equals("C27"))
+                        .map(ZmCrawlerQuotedPriceResponse.BussinessMainDTO.ContractDTO.AdjustDTO::getAdjustRate)
+                        .findFirst()
+                        .orElse(null);
+                scoreJson.add(new JSONObject()
+                        .fluentPut("scoreName", "无赔款优待系数")
+                        .fluentPut("scoreKey","c27AdjustRate")
+                        .fluentPut("score", c27AdjustRate));
+                Double c29AdjustRate = adjustList.stream()
+                        .filter(adjust -> adjust.getAdjustCode().equals("C29"))
+                        .map(ZmCrawlerQuotedPriceResponse.BussinessMainDTO.ContractDTO.AdjustDTO::getAdjustRate)
+                        .findFirst()
+                        .orElse(null);
+                scoreJson.add(new JSONObject()
+                        .fluentPut("scoreName", "自主定价系数")
+                        .fluentPut("scoreKey","c29AdjustRate")
+                        .fluentPut("score", c29AdjustRate));
+                if (contractDTO.getApmServiceFeeBean() != null) {
+                    scoreJson.add(new JSONObject()
+                            .fluentPut("scoreName", "总系数")
+                            .fluentPut("scoreKey","finalRate")
+                            .fluentPut("score", contractDTO.getApmServiceFeeBean().getFinalRate()));
+                }
             } else {
                 scoreJson.add(new JSONObject()
                         .fluentPut("scoreName", "商业不浮动原因")

+ 9 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/component/ZmCrawlerRequestComponent.java

@@ -878,6 +878,15 @@ public class ZmCrawlerRequestComponent {
         return response;
     }
 
+    public ZmCrawlerSearchCommonViewTraceResponse searchCommonViewTrace(ZmCrawlerSearchCommonViewTraceRequest searchCommonViewTraceRequest) {
+        InsuranceLog.infoLog(InsuranceEnum.ZMBX.getPinyin(), "\n\t---------> {} \n\t---------> URl: {} \n\t---------> 请求参数:{}",
+                "爬虫查看审核意见",RequestUrl.SEARCHCOMMONVIEWTRACE.getRequestUrl(zmCrawlerProperties.getBaseUrl()),JSON.toJSONString(searchCommonViewTraceRequest));
+        Mono<ZmCrawlerSearchCommonViewTraceResponse> responseMono = requestComponent.postGbk(RequestUrl.SEARCHCOMMONVIEWTRACE.getRequestUrl(zmCrawlerProperties.getBaseUrl()),
+                Base64Tool.encode(JSONObject.toJSONString(searchCommonViewTraceRequest)), ZmCrawlerSearchCommonViewTraceResponse.class,new HttpHeaders(),"查看审核意见");
+        ZmCrawlerSearchCommonViewTraceResponse response = responseMono.block();
+        return response;
+    }
+
     /**
      * 检查支付
      * @param checkPaymentRequest

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

@@ -31,6 +31,8 @@ public enum RequestUrl implements CrawlerRequestUrlStandard {
 
     SUBMIT("/prpall/Submit.do", "提交核保"),
 
+    SEARCHCOMMONVIEWTRACE("/common/SearchCommonViewTrace.do", "查询审核意见"),
+
     CHECK_PAYMENT("/prpall/CheckPaymentProcess.do", "检查支付"),
     FIND_ZF_TASK("/common/FINDZFTASK.do", "查询是否存在支付数据"),
     ORDER_APPLY("/prpall/OrderApply.do", "获取支付参数"),

+ 32 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/entity/Request/ZmCrawlerSearchCommonViewTraceRequest.java

@@ -0,0 +1,32 @@
+package com.jzg.quotation.zhongmei.crawler.entity.Request;
+
+import com.jzg.quotation.zhongmei.api.constant.TransCode;
+import com.jzg.quotation.zhongmei.api.entity.BaseRequestHead;
+import com.jzg.quotation.zhongmei.api.entity.request.BaseRequest;
+import com.jzg.quotation.zhongmei.crawler.entity.ZmCrawlerConfigureParameters;
+import com.jzg.quotation.zhongmei.crawler.entity.po.ZmCrawlerOrder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author quchen
+ * @date 2026/8/5 15:15
+ */
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ZmCrawlerSearchCommonViewTraceRequest extends BaseRequest {
+    @Override
+    public void setHead(BaseRequestHead head) {
+        super.setHead(head);
+        super.getHead().setTransCode(TransCode.SEARCHCOMMONVIEWTRACE);
+    }
+    private String businessNo;
+
+    private String userCode;
+
+    public ZmCrawlerSearchCommonViewTraceRequest(ZmCrawlerOrder zmCrawlerOrder, ZmCrawlerConfigureParameters parameters) {
+        this.businessNo = zmCrawlerOrder.getBussinessNo();
+        this.userCode = parameters.getComCode();
+    }
+}

+ 41 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/entity/Response/ZmCrawlerSearchCommonViewTraceResponse.java

@@ -0,0 +1,41 @@
+package com.jzg.quotation.zhongmei.crawler.entity.Response;
+
+import com.jzg.quotation.zhongmei.api.entity.response.BaseResponse;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author quchen
+ * @date 2026/8/5 15:19
+ */
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ZmCrawlerSearchCommonViewTraceResponse extends BaseResponse {
+    private List<TraceDTO> commonViewTraceBean;
+
+    @Data
+    public static class TraceDTO implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+        private String commonViewTrace;
+
+        private String dealerCode;
+
+        private String id;
+
+        private String power;
+
+        private String powerStatus;
+
+        private String submitStartTime;
+
+        private String submitEndTime;
+
+
+    }
+}

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

@@ -553,6 +553,23 @@ public class ZhongMeiCrawlerRequestImpl implements ZhongMeiCrawlerRequest {
             // 核保失败
             if ("2".equals(status)) {
                 orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.AUDIT_FAIL);
+                ZmCrawlerSearchCommonViewTraceRequest searchCommonViewTraceRequest = new ZmCrawlerSearchCommonViewTraceRequest(zmCrawlerOrder, parameters);
+                searchCommonViewTraceRequest.setHead(requestHead);
+                ZmCrawlerSearchCommonViewTraceResponse searchCommonViewTraceResponse = zmCrawlerRequestComponent.searchCommonViewTrace(searchCommonViewTraceRequest);
+                String reason = "";
+                if ("0".equals(searchCommonViewTraceResponse.getHead().getReturnCode())) {
+                    List<ZmCrawlerSearchCommonViewTraceResponse.TraceDTO> beanList = searchCommonViewTraceResponse.getCommonViewTraceBean();
+                    if (beanList != null) {
+                        reason = beanList.stream()
+                                .filter(bean -> "下发修改".equals(bean.getPowerStatus()))
+                                .map(ZmCrawlerSearchCommonViewTraceResponse.TraceDTO::getCommonViewTrace)
+                                .filter(Objects::nonNull)
+                                .findFirst()
+                                .orElse("");
+                    }
+                }
+                orderStatusResultVo.setOrderStatusStr(reason);
+                orderStatusResultVo.setErrorMsg(reason);
             }
             // 双核审核成功
             if ("1".equals(status) || "3".equals(status)) {

+ 3 - 3
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostServiceImpl.java

@@ -164,9 +164,9 @@ public class PtlAgreementCostServiceImpl extends ServiceImpl<PtlAgreementCostMap
     @Transactional(rollbackFor = Exception.class)
     public HttpResult<String> update(PtlAgreementCostEnd ptlAgreementCostEnd) {
         log.info("协议费用修改。ptlAgreementCostEnd=[{}]", JSONUtil.toJsonStr(ptlAgreementCostEnd));
-        if (ListUtils.hasDuplicates(ptlAgreementCostEnd.getRuleConditions())){
-            return HttpResult.error("已存在相同且有效的费用规则,请检查");
-        }
+//        if (ListUtils.hasDuplicates(ptlAgreementCostEnd.getRuleConditions())){
+//            return HttpResult.error("已存在相同且有效的费用规则,请检查");
+//        }
         // 校验ptlAgreementCostTypeList 数据  exportKeepPointRatio 不能大于 export
         if (!CollectionUtils.isEmpty(ptlAgreementCostEnd.getPtlAgreementCostTypeList())) {
             for (PtlAgreementCostEnd.PtlAgreementCostTypeDto ptlAgreementCostTypeDto : ptlAgreementCostEnd.getPtlAgreementCostTypeList()) {

+ 16 - 2
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementDispatchServiceImpl.java

@@ -118,7 +118,8 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
     public PtlAgreementDispatchVo getAgreementDispatch(PtlAgreementDispatchQuery ptlAgreementDispatchQuery) {
         log.info("获取协议调度. ptlAgreementDispatchQuery=[{}]", JSONUtil.toJsonStr(ptlAgreementDispatchQuery));
         List<PtlAgreementDispatch> ptlAgreementDispatches = baseMapper.selectList(new LambdaQueryWrapper<PtlAgreementDispatch>()
-                .eq(PtlAgreementDispatch::getCompanyId, ptlAgreementDispatchQuery.getCompanyId()));
+                .eq(PtlAgreementDispatch::getCompanyId, ptlAgreementDispatchQuery.getCompanyId())
+                .orderByAsc(PtlAgreementDispatch::getCreateTime));
         PtlAgreementDispatchVo dispatchVos = new PtlAgreementDispatchVo();
         List<String> dispatchIds = ptlAgreementDispatches.stream().map(PtlAgreementDispatch::getId).collect(Collectors.toList());
         if (!dispatchIds.isEmpty()) {
@@ -144,8 +145,19 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
             int index = 1;
             // add by lipf, 对协议配置中的字典序号进行转义 2026年5月20日16:43:34
             List<PtlAgreementUndwrtRulesDictLabal> ptlAgreementUndwrtRulesDictLabals = baseMapper.queryAllDictLabal();
+            ptlAgreementUndwrtRulesDictLabals.forEach(x -> {
+                if(x.getDictId() == 182 || x.getDictId() == 4 || x.getDictId() == 5){
+                    x.setIdStr(x.getCode());
+                }else{
+                    x.setIdStr(String.valueOf(x.getId()));
+                }
+            });
             Map<String, String> dictLabalId2Name = ptlAgreementUndwrtRulesDictLabals.stream()
-                    .collect(Collectors.toMap(PtlAgreementUndwrtRulesDictLabal::getIdStr, PtlAgreementUndwrtRulesDictLabal::getName));
+                    .collect(Collectors.toMap(
+                            dict -> dict.getDictId() == 182 ? dict.getCode() : dict.getIdStr(),
+                            PtlAgreementUndwrtRulesDictLabal::getName,
+                            (existing, replacement) -> existing
+                    ));
             Map<String, PtlAreaLicense> areaLicenseMap = ptlAreaLicenseService.queryAllAreaLicenseMap();
 
             Map<String,String> operatorMap = new HashMap<>();
@@ -192,12 +204,14 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
 
                         attrlink.setMaxName(maxName);
                     }
+                    System.out.printf(attrlink.getAttrCode()+"\n");
                     PtlAgreementUndwrtRulesAttr undwrtRuleAttrByAttrCode = ptlAgreementUndwrtRulesAttrService.getUndwrtRuleAttrByAttrCode(attrlink.getAttrCode());
                     if(undwrtRuleAttrByAttrCode != null){
                         attrlink.setAttrCodeName(undwrtRuleAttrByAttrCode.getAttrName());
                         if(undwrtRuleAttrByAttrCode.getDictId() != null){
                             attrlink.setAttrCodeName(undwrtRuleAttrByAttrCode.getAttrName());
                             List<PtlAgreementUndwrtRulesDictLabal> dictLabelsByTypeCode = ptlAgreementUndwrtRulesDictLabalService.getDictLabelsByTypeCode(undwrtRuleAttrByAttrCode.getDictId());
+
                             PtlAgreementUndwrtRulesDictLabal ptlAgreementUndwrtRulesDictLabal = dictLabelsByTypeCode.stream().filter(x -> x.getCode().equals(attrlink.getMin())).findFirst().orElse(null);
                             if(ptlAgreementUndwrtRulesDictLabal != null){
                                 if(attrlink.getAttrDesc() == null){

+ 12 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementUndwrtRulesAttrServiceImpl.java

@@ -119,6 +119,18 @@ public class PtlAgreementUndwrtRulesAttrServiceImpl extends ServiceImpl<PtlAgree
             Map<Integer, List<PtlAgreementUndwrtRulesDictLabal>> dictMap = undwrtRulesDictList.stream()
                     .collect(Collectors.groupingBy(PtlAgreementUndwrtRulesDictLabal::getDictId));
             initializeAttributes(list, dictMap);
+            list.forEach(item -> {
+                if (item.getAttrType().equals("checkbox")) {
+                    item.getDictLabal().forEach(x->{
+                        x.setIdStr(x.getCode());
+                    });
+                } else {
+                    item.getDictLabal().forEach(x->{
+                        x.setIdStr(String.valueOf(x.getId()));
+                    });
+                }
+
+            });
             return list;
         } catch (Exception e) {
             // 处理异常

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

@@ -480,7 +480,12 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
         }
 
         //根据基本规则 能源、车辆类型、使用性质获取方案
-        List<PtlScheme> ptlSchemes = ptlSchemeMapper.selectList(new LambdaQueryWrapper<PtlScheme>().eq(PtlScheme::getEnergyType, schemeRuleFilterVo.getCarInfo().getEnergyTypeCode().equals("0") ? "0" : "1").like(PtlScheme::getCarnature, schemeRuleFilterVo.getCarInfo().getCarNatureCode()).like(PtlScheme::getVehicleType, schemeRuleFilterVo.getCarInfo().getCarKindCode()).eq(PtlScheme::getProductId, schemeRuleFilterVo.getProductId()).eq(PtlScheme::getIsDelete, 0));
+        List<PtlScheme> ptlSchemes = ptlSchemeMapper.selectList(new LambdaQueryWrapper<PtlScheme>()
+                .eq(PtlScheme::getEnergyType, schemeRuleFilterVo.getCarInfo().getEnergyTypeCode().equals("0") ? "0" : "1")
+                .like(PtlScheme::getCarnature, schemeRuleFilterVo.getCarInfo().getCarNatureCode())
+                .like(PtlScheme::getVehicleType, schemeRuleFilterVo.getCarInfo().getCarKindCode())
+                .eq(PtlScheme::getProductId, schemeRuleFilterVo.getProductId())
+                .eq(PtlScheme::getIsDelete, 0));
         log.info("根据车辆信息匹配保险方案:匹配到[{}]个方案。 energyType(能源类型)=[{}],carNatureCode(使用性质)=[{}],carKindCode(车辆性质)=[{}], productId(产品id)=[{}]", CollUtil.size(ptlSchemes), schemeRuleFilterVo.getCarInfo().getEnergyTypeCode(), schemeRuleFilterVo.getCarInfo().getCarNatureCode(), schemeRuleFilterVo.getCarInfo().getCarKindCode(), schemeRuleFilterVo.getProductId());
 
         // 查找规则