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

Merge remote-tracking branch 'refs/remotes/origin/master' into dev_jzg_lipf_v20260622

lipf 3 недель назад
Родитель
Сommit
970e80971c
36 измененных файлов с 1148 добавлено и 801 удалено
  1. 3 0
      authentication/src/main/java/com/jzg/config/JzgAuthenticationProvider.java
  2. 1 1
      authentication/src/main/java/com/jzg/mapper/SysUserJzgInfoMapper.java
  3. 3 2
      commons/src/main/java/com/jzg/commons/entity/dto/PtlAgreementCostAdd.java
  4. 20 0
      commons/src/main/java/com/jzg/commons/entity/po/InsFeeOrdersSummary.java
  5. 4 3
      commons/src/main/java/com/jzg/commons/entity/po/PtlNewCarJudgeRules.java
  6. 1 0
      commons/src/main/java/com/jzg/quotation/summary/constants/QuoteNumberConstant.java
  7. 8 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/OrgClient.java
  8. 311 514
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/FactorMatch.java
  9. 27 16
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/AuditVerificationAspect.java
  10. 139 59
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java
  11. 13 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeOrderController.java
  12. 7 2
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsFeeOrdersMapper.java
  13. 8 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeOrdersService.java
  14. 20 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeOrdersServiceImpl.java
  15. 173 94
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java
  16. 8 2
      tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeOrdersMapper.xml
  17. 8 29
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/build/ZhongAnCrawlerQuoteResultsVoBuild.java
  18. 3 3
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/request/ZhongAnCrawlerQuoteRequest.java
  19. 108 0
      tenant/organization/src/main/java/com/jzg/organization/aop/OrderOperationLogAspect.java
  20. 10 0
      tenant/organization/src/main/java/com/jzg/organization/client/summary/QuoteClient.java
  21. 23 30
      tenant/organization/src/main/java/com/jzg/organization/component/BuildDescUtils.java
  22. 2 18
      tenant/organization/src/main/java/com/jzg/organization/controller/NewCarJudgeRulesController.java
  23. 7 0
      tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java
  24. 8 0
      tenant/organization/src/main/java/com/jzg/organization/controller/SysOrganizationController.java
  25. 8 0
      tenant/organization/src/main/java/com/jzg/organization/controller/UserController.java
  26. 9 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserJzgInfoMapper.java
  27. 4 0
      tenant/organization/src/main/java/com/jzg/organization/service/SysOrganizationService.java
  28. 1 0
      tenant/organization/src/main/java/com/jzg/organization/service/SysUserService.java
  29. 1 1
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java
  30. 9 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysOrganizationServiceImpl.java
  31. 12 7
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserAccountServiceImpl.java
  32. 6 1
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserJzgInfoBankCardServiceImpl.java
  33. 111 18
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java
  34. 3 1
      tenant/organization/src/main/resources/application.yml
  35. 1 0
      tenant/organization/src/main/resources/mapper/PtlAgreementCostMapper.xml
  36. 68 0
      tenant/organization/src/main/resources/mapper/SysUserJzgInfoMapper.xml

+ 3 - 0
authentication/src/main/java/com/jzg/config/JzgAuthenticationProvider.java

@@ -419,6 +419,9 @@ public class JzgAuthenticationProvider implements AuthenticationProvider {
                     .filter(x -> Objects.equals(x.getSystemCode(), system))
                     .findFirst()
                     .orElse(null);
+            if(sysUserJzgInfo == null){
+                throw new SystemException("该用户信息不存在,请重新输入");
+            }
             // 租户系统才会校验这个, 后台管理系统,没有租户的概念
             if(this.isTenantLogin(system)){
                 if (sysUserJzgInfo.cannotLogin()) {

+ 1 - 1
authentication/src/main/java/com/jzg/mapper/SysUserJzgInfoMapper.java

@@ -19,7 +19,7 @@ public interface SysUserJzgInfoMapper extends BaseMapper<SysUserJzgInfo> {
      * 一个用户可能存在多个身份,用逗号分隔返回
      *
      * @param userId sys_user_jzg_info 表中的 userid(即 sys_user.id)
-     * @author lipf
+     * @author liub
      * @date 2026/8/29
      */
     @Select("SELECT GROUP_CONCAT(DISTINCT s.type_attr SEPARATOR ',') FROM sys_user_jzg_info_salesman s " +

+ 3 - 2
commons/src/main/java/com/jzg/commons/entity/dto/PtlAgreementCostAdd.java

@@ -9,6 +9,7 @@ import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 
@@ -31,12 +32,12 @@ public class PtlAgreementCostAdd {
     @Schema(description = "生效时间")
     @NotNull(message = "生效时间不能为空")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private Date effectiveTime;
+    private LocalDateTime effectiveTime;
 
     @Schema(description = "失效时间")
     @NotNull(message = "失效时间不能为空")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private Date failureTime;
+    private LocalDateTime failureTime;
 
     @Schema(description = "审核方式0-自动审核;1-手动审核")
     @NotBlank(message = "审核方式不能为空")

+ 20 - 0
commons/src/main/java/com/jzg/commons/entity/po/InsFeeOrdersSummary.java

@@ -0,0 +1,20 @@
+package com.jzg.commons.entity.po;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class InsFeeOrdersSummary implements Serializable {
+    @Serial
+    private static final long serialVersionUID = -2218119163153717246L;
+
+    @Schema(description = "成交的订单总数")
+    private Long orderCount;
+
+    @Schema(description = "订单成交的总保费")
+    private BigDecimal totalPremium;
+}

+ 4 - 3
commons/src/main/java/com/jzg/commons/entity/po/PtlNewCarJudgeRules.java

@@ -3,12 +3,11 @@ package com.jzg.commons.entity.po;
 
 import com.alibaba.excel.annotation.ExcelIgnore;
 import com.baomidou.mybatisplus.annotation.*;
-import com.jzg.commons.core.base.BaseModel;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
-import java.util.Date;
 
 
 /**
@@ -38,7 +37,9 @@ public class PtlNewCarJudgeRules{
 
     private String isEffective;
 
-    private Date saveDate;
+    @Schema(description = "插入时间")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime saveDate;
 
     @ExcelIgnore
     @Schema(description = "是否删除")

+ 1 - 0
commons/src/main/java/com/jzg/quotation/summary/constants/QuoteNumberConstant.java

@@ -96,6 +96,7 @@ public class QuoteNumberConstant {
         OPT_TYPE_15(15,"费用调整"),
         OPT_TYPE_16(16,"批量修改比例"),
         OPT_TYPE_17(17,"设置为疑问订单"),
+        OPT_TYPE_18(18,"导入批量修改比例"),
         ;
         private Integer code;
         private String desc;

+ 8 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/OrgClient.java

@@ -275,4 +275,12 @@ public interface OrgClient {
      */
     @GetMapping("/plt/areaLicense/getAreaLicenseCode")
     HttpResult<String> convertLicense2AreaNumber(@RequestParam("licenseNo") String licenseNo);
+
+    /**
+     * 根据人员id 查询是否为团队长
+     * @param id
+     */
+    @GetMapping("/sysOrganization/queryOrganizationByManagerId")
+    HttpResult<List<SysOrganization>> queryOrganizationByManagerId(@RequestParam("userId")String userId);
+
 }

+ 311 - 514
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/FactorMatch.java

@@ -15,7 +15,6 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 /**
@@ -25,157 +24,99 @@ public class FactorMatch {
 
     private static final Logger log = LoggerFactory.getLogger(FactorMatch.class);
 
-    private static final Map<String, String> plateFourCodeMap = new HashMap<>();
+    private static final Map<String, String> PLATE_FOUR_CODE_MAP = new HashMap<>();
 
     static {
-        plateFourCodeMap.put("1404", "晋D");     plateFourCodeMap.put("1408", "晋M");
-        plateFourCodeMap.put("1411", "晋J");     plateFourCodeMap.put("1403", "晋C");
-        plateFourCodeMap.put("1407", "晋K");     plateFourCodeMap.put("1410", "晋L");
-        plateFourCodeMap.put("1402", "晋B");     plateFourCodeMap.put("1406", "晋F");
-        plateFourCodeMap.put("1401", "晋A");     plateFourCodeMap.put("1405", "晋E");
-        plateFourCodeMap.put("1409", "晋H");     plateFourCodeMap.put("14", "晋");
-        plateFourCodeMap.put("31", "沪");        plateFourCodeMap.put("53", "云");
-        plateFourCodeMap.put("15", "蒙");        plateFourCodeMap.put("11", "京");
-        plateFourCodeMap.put("22", "吉");        plateFourCodeMap.put("51", "川");
-        plateFourCodeMap.put("12", "津");        plateFourCodeMap.put("64", "宁");
-        plateFourCodeMap.put("34", "皖");        plateFourCodeMap.put("37", "鲁");
-        plateFourCodeMap.put("44", "粤");        plateFourCodeMap.put("45", "桂");
-        plateFourCodeMap.put("65", "新");        plateFourCodeMap.put("32", "苏");
-        plateFourCodeMap.put("36", "赣");        plateFourCodeMap.put("13", "冀");
-        plateFourCodeMap.put("41", "豫");        plateFourCodeMap.put("33", "浙");
-        plateFourCodeMap.put("46", "琼");        plateFourCodeMap.put("42", "鄂");
-        plateFourCodeMap.put("43", "湘");        plateFourCodeMap.put("62", "甘");
-        plateFourCodeMap.put("35", "闽");        plateFourCodeMap.put("54", "藏");
-        plateFourCodeMap.put("52", "贵");        plateFourCodeMap.put("21", "辽");
-        plateFourCodeMap.put("50", "渝");        plateFourCodeMap.put("61", "陕");
-        plateFourCodeMap.put("63", "青");        plateFourCodeMap.put("23", "黑");
+        PLATE_FOUR_CODE_MAP.put("1404", "晋D");  PLATE_FOUR_CODE_MAP.put("1408", "晋M");
+        PLATE_FOUR_CODE_MAP.put("1411", "晋J");  PLATE_FOUR_CODE_MAP.put("1403", "晋C");
+        PLATE_FOUR_CODE_MAP.put("1407", "晋K");  PLATE_FOUR_CODE_MAP.put("1410", "晋L");
+        PLATE_FOUR_CODE_MAP.put("1402", "晋B");  PLATE_FOUR_CODE_MAP.put("1406", "晋F");
+        PLATE_FOUR_CODE_MAP.put("1401", "晋A");  PLATE_FOUR_CODE_MAP.put("1405", "晋E");
+        PLATE_FOUR_CODE_MAP.put("1409", "晋H");  PLATE_FOUR_CODE_MAP.put("14",   "晋");
+        PLATE_FOUR_CODE_MAP.put("31",   "沪");   PLATE_FOUR_CODE_MAP.put("53",   "云");
+        PLATE_FOUR_CODE_MAP.put("15",   "蒙");   PLATE_FOUR_CODE_MAP.put("11",   "京");
+        PLATE_FOUR_CODE_MAP.put("22",   "吉");   PLATE_FOUR_CODE_MAP.put("51",   "川");
+        PLATE_FOUR_CODE_MAP.put("12",   "津");   PLATE_FOUR_CODE_MAP.put("64",   "宁");
+        PLATE_FOUR_CODE_MAP.put("34",   "皖");   PLATE_FOUR_CODE_MAP.put("37",   "鲁");
+        PLATE_FOUR_CODE_MAP.put("44",   "粤");   PLATE_FOUR_CODE_MAP.put("45",   "桂");
+        PLATE_FOUR_CODE_MAP.put("65",   "新");   PLATE_FOUR_CODE_MAP.put("32",   "苏");
+        PLATE_FOUR_CODE_MAP.put("36",   "赣");   PLATE_FOUR_CODE_MAP.put("13",   "冀");
+        PLATE_FOUR_CODE_MAP.put("41",   "豫");   PLATE_FOUR_CODE_MAP.put("33",   "浙");
+        PLATE_FOUR_CODE_MAP.put("46",   "琼");   PLATE_FOUR_CODE_MAP.put("42",   "鄂");
+        PLATE_FOUR_CODE_MAP.put("43",   "湘");   PLATE_FOUR_CODE_MAP.put("62",   "甘");
+        PLATE_FOUR_CODE_MAP.put("35",   "闽");   PLATE_FOUR_CODE_MAP.put("54",   "藏");
+        PLATE_FOUR_CODE_MAP.put("52",   "贵");   PLATE_FOUR_CODE_MAP.put("21",   "辽");
+        PLATE_FOUR_CODE_MAP.put("50",   "渝");   PLATE_FOUR_CODE_MAP.put("61",   "陕");
+        PLATE_FOUR_CODE_MAP.put("63",   "青");   PLATE_FOUR_CODE_MAP.put("23",   "黑");
     }
 
+    // ============================================================
+    // 主入口
+    // ============================================================
     /**
-     * 因子比对
-     * @param ptlAgreementCostRuleList
-     * @param ruleAttrMappingVoList
-     * @param undwrtRulesAttrList
-     * @param logs
-     * @return
+     * 判断费用因子是否匹配
+     * @param ptlAgreementCostRuleList 协议规则列表
+     * @param ruleAttrMappingVoList 需要校验的规则属性映射列表
+     * @param undwrtRulesAttrList 协议费用因子元数据列表
+     * @param logs 日志
+     * @param undwrtRulesDictList 协议费用因子元数据字典列表
+     * @return 是否匹配
      */
-    public static boolean judgements(List<PtlAgreementCostRule> ptlAgreementCostRuleList, List<RuleAttrMappingVo> ruleAttrMappingVoList,
-                                     List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList, StringBuilder logs,  List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-        if (ptlAgreementCostRuleList == null || ptlAgreementCostRuleList.isEmpty()) {
+    public static boolean judgements(List<PtlAgreementCostRule> ptlAgreementCostRuleList,
+                                     List<RuleAttrMappingVo> ruleAttrMappingVoList,
+                                     List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList,
+                                     StringBuilder logs,
+                                     List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
+        if (CollUtil.isEmpty(ptlAgreementCostRuleList)) {
             return false;
         }
-        // 按batch分组:不同batch之间为OR关系,同batch内为AND关系
+        // 预建索引:避免内层循环反复 stream().filter() 造成 O(R*A) 扫描
+        Map<String, String> mappingIndex = buildMappingIndex(ruleAttrMappingVoList);
+        Map<String, PtlAgreementUndwrtRulesAttr> attrIndex = buildAttrIndex(undwrtRulesAttrList);
+        Map<Integer, Map<String, String>> dictIndex = buildDictIndex(undwrtRulesDictList);
+        Map<Integer, Map<String, String>> dictNameIndex = buildDictNameIndex(undwrtRulesDictList);
+
+        // 按 batch 分组:不同 batch 之间 OR,同 batch 内 AND
         Map<String, List<PtlAgreementCostRule>> batchMap = ptlAgreementCostRuleList.stream()
                 .collect(Collectors.groupingBy(rule -> rule.getBatch() != null ? rule.getBatch() : "default",
                         LinkedHashMap::new, Collectors.toList()));
 
         StringBuilder errorLogs = new StringBuilder();
         for (Map.Entry<String, List<PtlAgreementCostRule>> entry : batchMap.entrySet()) {
-            List<PtlAgreementCostRule> batchRules = entry.getValue();
             StringBuilder batchLogs = new StringBuilder();
-            boolean batchMatched = doJudgementsMatch(batchRules, ruleAttrMappingVoList, undwrtRulesAttrList,
-                    batchLogs, undwrtRulesDictList);
-            if (batchMatched) {
-                // OR关系:只要任一个batch匹配即通过
-                return true;
+            if (doJudgementsMatch(entry.getValue(), mappingIndex, attrIndex, dictIndex, dictNameIndex, batchLogs)) {
+                return true; // OR:任一 batch 匹配即通过
             }
             errorLogs.append(batchLogs);
         }
-        // 所有batch都未匹配,输出错误日志
         logs.append(errorLogs);
         return false;
     }
 
-    /**
-     * 判断一个batch内的规则是否全部匹配(AND关系)
-     */
-    private static boolean doJudgementsMatch(List<PtlAgreementCostRule> batchRules, List<RuleAttrMappingVo> ruleAttrMappingVoList,
-                                             List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList, StringBuilder logs,
-                                             List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-        for (PtlAgreementCostRule ptlAgreementProductCostsAttrLink : batchRules) {
-            //查找规则中的 传值属性
-            RuleAttrMappingVo ruleAttrMappingVo = ruleAttrMappingVoList.stream()
-                    .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                    .findFirst()
-                    .orElse(null);
-            //如果查找不到 传值属性 直接费用对比失败
-            if (ruleAttrMappingVo == null) {
-                List<PtlAgreementUndwrtRulesAttr> collect = undwrtRulesAttrList.stream()
-                        .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                        .toList();
-                if (!collect.isEmpty()) {
-                    logs.append("规则匹配失败:" + collect.get(0).getAttrName() + "\n");
-                }
-                return false;
-            }
-
-            //查找 费用因子规则
-            PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr = undwrtRulesAttrList.stream()
-                    .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                    .findFirst()
-                    .get();
+    // ============================================================
+    // 判断一个batch内的规则是否全部匹配(AND关系)
+    // ============================================================
 
-            boolean useFlag;
-            if(!Objects.isNull(ruleAttrMappingVo.getValue())) {
-                useFlag = attrEqual(ptlAgreementProductCostsAttrLink, ptlAgreementUndwrtRulesAttr, ruleAttrMappingVo.getValue(),
-                        false, undwrtRulesDictList);
-            }else{
-                useFlag = false;
+    private static boolean doJudgementsMatch(List<PtlAgreementCostRule> batchRules,
+                                             Map<String, String> mappingIndex,
+                                             Map<String, PtlAgreementUndwrtRulesAttr> attrIndex,
+                                             Map<Integer, Map<String, String>> dictIndex,
+                                             Map<Integer, Map<String, String>> dictNameIndex,
+                                             StringBuilder logs) {
+        for (PtlAgreementCostRule rule : batchRules) {
+            String value = mappingIndex.get(rule.getAttrCode());
+            if (value == null) {
+                // 找不到传值属性时的日志
+                appendMissingAttrLog(logs, attrIndex, rule.getAttrCode(), false);
+                return false;
             }
+            // 协议费用因子元数据
+            PtlAgreementUndwrtRulesAttr meta = attrIndex.get(rule.getAttrCode());
+            boolean useFlag = attrEqual(rule, meta, value, false, dictIndex, dictNameIndex);
 
             if (!useFlag) {
-                List<PtlAgreementUndwrtRulesAttr> collect = undwrtRulesAttrList.stream()
-                        .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                        .toList();
-
-                boolean isPlateAttr = "LicenseNo".equals(ptlAgreementProductCostsAttrLink.getAttrCode())
-                        || "LicenseArea".equals(ptlAgreementProductCostsAttrLink.getAttrCode());
-
-                // 检验的值
-                String ruleVal = ptlAgreementProductCostsAttrLink.getMin() != null
-                        ? ptlAgreementProductCostsAttrLink.getMin()
-                        : ptlAgreementProductCostsAttrLink.getMax();
-                if (isPlateAttr) {
-                    StringBuilder str = new StringBuilder();
-                    for (String s : ruleVal.split(",")) {
-                        str.append(plateFourCodeMap.getOrDefault(s, s)).append(",");
-                    }
-                    logs.append("检验的值:").append(str.toString()).append("\n");
-                } else {
-                    Integer dictId = collect.get(0).getDictId();
-                    Map<String, String> codeToNameMap = new HashMap<>();
-                    if (dictId != null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                        for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                            if (Objects.equals(label.getDictId(), dictId)) {
-                                codeToNameMap.put(label.getCode(), label.getName());
-                            }
-                        }
-                    }
-                    logs.append("检验的值:").append(displayRuleValue(ruleVal, codeToNameMap)).append("\n");
-                }
-
-                // 传入的值
-                String inVal = ruleAttrMappingVo.getValue();
-                if (isPlateAttr) {
-                    logs.append("传入的值:" + plateFourCodeMap.getOrDefault(inVal, inVal) + "\n");
-                } else {
-                    Integer dictId = collect.get(0).getDictId();
-                    Map<String, String> codeToNameMap = new HashMap<>();
-                    if (dictId != null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                        for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                            if (Objects.equals(label.getDictId(), dictId)) {
-                                codeToNameMap.put(label.getCode(), label.getName());
-                            }
-                        }
-                    }
-                    String name = codeToNameMap.getOrDefault(inVal, inVal);
-                    logs.append("传入的值:" + (codeToNameMap.isEmpty() ? inVal : name) + "\n");
-                }
-
-                if (CollUtil.isNotEmpty(collect)) {
-                    logs.append("规则匹配失败:" + collect.get(0).getAttrName() + "\n");
-                }
-
+                appendMismatchLog(logs, attrIndex, dictIndex, rule.getAttrCode(),
+                        rule, value, false);
                 return false;
             }
         }
@@ -183,22 +124,122 @@ public class FactorMatch {
     }
 
     // ============================================================
-    // 字典映射
+    // 索引预构建:把 stream().filter() 的 O(A) 一次性摊成 O(1) 查找
     // ============================================================
 
-    /**
-     * 展示"检验的值":规则里存的是 code(如 04),翻成 name(如 家庭自用)方便对账。
-     * 支持多选逗号分隔,逐个翻译;翻译不到的保留原 code。
-     */
+    /** attrCode -> value 预建索引 */
+    private static Map<String, String> buildMappingIndex(List<RuleAttrMappingVo> list) {
+        Map<String, String> map = new HashMap<>();
+        if (CollUtil.isNotEmpty(list)) {
+            for (RuleAttrMappingVo v : list) map.put(v.getAttrCode(), v.getValue());
+        }
+        return map;
+    }
+
+    /** attrCode -> meta 预建索引 */
+    private static Map<String, PtlAgreementUndwrtRulesAttr> buildAttrIndex(List<PtlAgreementUndwrtRulesAttr> list) {
+        Map<String, PtlAgreementUndwrtRulesAttr> map = new HashMap<>();
+        if (CollUtil.isNotEmpty(list)) {
+            for (PtlAgreementUndwrtRulesAttr a : list) map.put(a.getAttrCode(), a);
+        }
+        return map;
+    }
+
+    /** dictId -> (code -> name) 预建索引,供日志展示使用 */
+    private static Map<Integer, Map<String, String>> buildDictIndex(List<PtlAgreementUndwrtRulesDictLabal> dictList) {
+        Map<Integer, Map<String, String>> map = new HashMap<>();
+        if (CollUtil.isNotEmpty(dictList)) {
+            for (PtlAgreementUndwrtRulesDictLabal l : dictList) {
+                Integer dictId = l.getDictId();
+                if (dictId == null) continue;
+                map.computeIfAbsent(dictId, k -> new HashMap<>()).put(l.getCode(), l.getName());
+            }
+        }
+        return map;
+    }
+
+    /** dictId -> (name -> code) 预建索引,供 normalizeToCode 使用 */
+    private static Map<Integer, Map<String, String>> buildDictNameIndex(List<PtlAgreementUndwrtRulesDictLabal> dictList) {
+        Map<Integer, Map<String, String>> map = new HashMap<>();
+        if (CollUtil.isNotEmpty(dictList)) {
+            for (PtlAgreementUndwrtRulesDictLabal l : dictList) {
+                Integer dictId = l.getDictId();
+                if (dictId == null) continue;
+                map.computeIfAbsent(dictId, k -> new HashMap<>()).put(l.getName(), l.getCode());
+            }
+        }
+        return map;
+    }
+
+    // ============================================================
+    // 工具方法
+    // ============================================================
+
+    private static PtlAgreementCostRule toCostRule(PtlAgreementUndwrtRulesAttrLink link) {
+        PtlAgreementCostRule r = new PtlAgreementCostRule();
+        r.setMin(link.getMin());
+        r.setMax(link.getMax());
+        r.setOperator(link.getOperator());
+        r.setAttrCode(link.getAttrCode());
+        return r;
+    }
+
+    /** 找不到传值属性时的日志(基于预建索引) */
+    private static void appendMissingAttrLog(StringBuilder logs,
+                                             Map<String, PtlAgreementUndwrtRulesAttr> attrIndex,
+                                             String attrCode, boolean html) {
+        PtlAgreementUndwrtRulesAttr a = attrIndex.get(attrCode);
+        if (a != null) {
+            logs.append((html ? "<span style=\"color:red;\">" : ""))
+                    .append("规则匹配失败:").append(a.getAttrName())
+                    .append(html ? "</span>" : "").append("\n");
+        }
+    }
+
+    /** 匹配失败时的"检验的值 / 传入的值"日志(基于预建索引) */
+    private static void appendMismatchLog(StringBuilder logs,
+                                          Map<String, PtlAgreementUndwrtRulesAttr> attrIndex,
+                                          Map<Integer, Map<String, String>> dictIndex,
+                                          String attrCode,
+                                          PtlAgreementCostRule rule,
+                                          String inVal,
+                                          boolean html) {
+        PtlAgreementUndwrtRulesAttr meta = attrIndex.get(attrCode);
+        if (meta == null) return;
+
+        boolean isPlate = "LicenseNo".equals(attrCode) || "LicenseArea".equals(attrCode);
+        String ruleVal = rule.getMin() != null ? rule.getMin() : rule.getMax();
+        Map<String, String> codeToNameMap = meta.getDictId() == null ? null : dictIndex.get(meta.getDictId());
+
+        // 检验的值
+        if (isPlate) {
+            StringBuilder sb = new StringBuilder();
+            for (String s : ruleVal.split(",")) sb.append(PLATE_FOUR_CODE_MAP.getOrDefault(s, s)).append(",");
+            logs.append("检验的值:").append(sb).append("\n");
+        } else {
+            logs.append("检验的值:").append(displayRuleValue(ruleVal, codeToNameMap)).append("\n");
+        }
+
+        // 传入的值
+        if (isPlate) {
+            logs.append("传入的值:").append(PLATE_FOUR_CODE_MAP.getOrDefault(inVal, inVal)).append("\n");
+        } else {
+            logs.append("传入的值:").append(codeToNameMap == null || codeToNameMap.isEmpty() ? inVal : codeToNameMap.getOrDefault(inVal, inVal)).append("\n");
+        }
+
+        logs.append((html ? "<span style=\"color:red;\">" : "") + "规则匹配失败:" + meta.getAttrName()
+                + (html ? "</span>" : "") + "\n");
+    }
+
+    /** 规则值 code -> name 展示(如 04 -> 家庭自用(04)) */
     private static String displayRuleValue(String ruleVal, Map<String, String> codeToNameMap) {
         if (ruleVal == null) return "";
-        if (CollUtil.isEmpty(codeToNameMap)) return ruleVal;
-        String[] codes = Arrays.stream(ruleVal.split(","))
-                .map(String::trim).filter(s -> !s.isEmpty()).toArray(String[]::new);
-        if (codes.length == 0) return ruleVal;
+        if (codeToNameMap == null || codeToNameMap.isEmpty()) return ruleVal;
+        String[] codes = ruleVal.split(",");
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < codes.length; i++) {
-            String code = codes[i];
+            String code = codes[i].trim();
+            if (code.isEmpty()) continue;
             String name = codeToNameMap.getOrDefault(code, code);
             sb.append(name).append("(").append(code).append(")");
             if (i < codes.length - 1) sb.append(",");
@@ -206,422 +247,178 @@ public class FactorMatch {
         return sb.toString();
     }
 
-    public static boolean judgementsUnderwrite(List<PtlAgreementUndwrtRulesAttrLink> ptlAgreementCostRuleList, List<RuleAttrMappingVo> ruleAttrMappingVoList,
-                                     List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList, StringBuilder logs, List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-        boolean useFlag = true;
+    public static boolean judgementsUnderwrite(List<PtlAgreementUndwrtRulesAttrLink> ptlAgreementCostRuleList,
+                                               List<RuleAttrMappingVo> ruleAttrMappingVoList,
+                                               List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList,
+                                               StringBuilder logs,
+                                               List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
+        // 预建索引:避免内层循环反复 stream().filter() 造成 O(R*A) 扫描
+        Map<String, String> mappingIndex = buildMappingIndex(ruleAttrMappingVoList);
+        Map<String, PtlAgreementUndwrtRulesAttr> attrIndex = buildAttrIndex(undwrtRulesAttrList);
+        Map<Integer, Map<String, String>> dictIndex = buildDictIndex(undwrtRulesDictList);
+        Map<Integer, Map<String, String>> dictNameIndex = buildDictNameIndex(undwrtRulesDictList);
+
         boolean groupUseFlag = false;
-        for (PtlAgreementUndwrtRulesAttrLink ptlAgreementProductCostsAttrLink : ptlAgreementCostRuleList) {
-            //查找规则中的 传值属性
-            RuleAttrMappingVo ruleAttrMappingVo = ruleAttrMappingVoList.stream()
-                    .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                    .findFirst()
-                    .orElse(null);
-            //如果查找不到 传值属性 直接费用对比失败
-            if (ruleAttrMappingVo == null) {
-                log.info("承保规则校验-属性未找到: attrCode={}", ptlAgreementProductCostsAttrLink.getAttrCode());
-                log.info("承保规则校验-规则匹配失败: attrCode={}", ptlAgreementProductCostsAttrLink.getAttrCode());
-
-                List<PtlAgreementUndwrtRulesAttr> collect = undwrtRulesAttrList.stream()
-                        .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                        .toList();
-                if (!collect.isEmpty()) {
-                    logs.append("规则匹配失败:" + collect.get(0).getAttrName() + "\n");
-                }
+        for (PtlAgreementUndwrtRulesAttrLink link : ptlAgreementCostRuleList) {
+            String value = mappingIndex.get(link.getAttrCode());
+            if (value == null) {
+                log.info("承保规则校验-属性未找到: attrCode={}", link.getAttrCode());
+                appendMissingAttrLog(logs, attrIndex, link.getAttrCode(), true);
                 return false;
             }
 
+            PtlAgreementUndwrtRulesAttr meta = attrIndex.get(link.getAttrCode());
+            PtlAgreementCostRule costRule = toCostRule(link);
 
-            //查找 费用因子规则
-            PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr = undwrtRulesAttrList.stream()
-                    .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                    .findFirst()
-                    .get();
-
-            if(!Objects.isNull(ruleAttrMappingVo.getValue())) {
-                PtlAgreementCostRule ptlAgreementCostRule = new PtlAgreementCostRule();
-                ptlAgreementCostRule.setMin(ptlAgreementProductCostsAttrLink.getMin());
-                ptlAgreementCostRule.setMax(ptlAgreementProductCostsAttrLink.getMax());
-                ptlAgreementCostRule.setOperator(ptlAgreementProductCostsAttrLink.getOperator());
-                ptlAgreementCostRule.setAttrCode(ptlAgreementProductCostsAttrLink.getAttrCode());
-                useFlag = attrEqual(ptlAgreementCostRule, ptlAgreementUndwrtRulesAttr, ruleAttrMappingVo.getValue(),
-                        true, undwrtRulesDictList);
+            boolean useFlag;
+            if (StrUtil.isNotBlank(value)) {
+                useFlag = attrEqual(costRule, meta, value, true, dictIndex, dictNameIndex);
                 log.info("承保规则校验-单属性匹配: attrCode={}, attrType={}, 规则值(min={}, max={}, operator={}), 传入值={}, useFlag={}",
-                        ptlAgreementProductCostsAttrLink.getAttrCode(), ptlAgreementUndwrtRulesAttr.getAttrType(),
-                        ptlAgreementProductCostsAttrLink.getMin(), ptlAgreementProductCostsAttrLink.getMax(),
-                        ptlAgreementProductCostsAttrLink.getOperator(), ruleAttrMappingVo.getValue(), useFlag);
-            }else{
+                        link.getAttrCode(), meta == null ? null : meta.getAttrType(), link.getMin(), link.getMax(),
+                        link.getOperator(), value, useFlag);
+            } else {
                 useFlag = false;
-                log.info("承保规则校验-传入值为null: attrCode={}, useFlag=false", ptlAgreementProductCostsAttrLink.getAttrCode());
-            }
-
-            if(useFlag){
-                groupUseFlag = useFlag;
+                log.info("承保规则校验-传入值为null: attrCode={}, useFlag=false", link.getAttrCode());
             }
 
-            if (!useFlag) {
+            if (useFlag) {
+                groupUseFlag = true;
+            } else {
                 log.info("承保规则校验-条件命中! attrCode={}, 传入值={}, 规则min={}, max={}, operator={}",
-                        ptlAgreementProductCostsAttrLink.getAttrCode(), ruleAttrMappingVo.getValue(),
-                        ptlAgreementProductCostsAttrLink.getMin(), ptlAgreementProductCostsAttrLink.getMax(),
-                        ptlAgreementProductCostsAttrLink.getOperator());
-
-                List<PtlAgreementUndwrtRulesAttr> collect = undwrtRulesAttrList.stream()
-                        .filter(x -> x.getAttrCode().equals(ptlAgreementProductCostsAttrLink.getAttrCode()))
-                        .toList();
-                boolean isPlateAttr = "LicenseNo".equals(ptlAgreementProductCostsAttrLink.getAttrCode())
-                        || "LicenseArea".equals(ptlAgreementProductCostsAttrLink.getAttrCode());
-
-                // 检验的值
-                String ruleVal = ptlAgreementProductCostsAttrLink.getMin() != null
-                        ? ptlAgreementProductCostsAttrLink.getMin()
-                        : ptlAgreementProductCostsAttrLink.getMax();
-                if (isPlateAttr) {
-                    StringBuilder str = new StringBuilder();
-                    for (String s : ruleVal.split(",")) {
-                        str.append(plateFourCodeMap.getOrDefault(s, s)).append(",");
-                    }
-                    logs.append("检验的值:").append(str.toString()).append("\n");
-                } else {
-                    Integer dictId = collect.get(0).getDictId();
-                    Map<String, String> codeToNameMap = new HashMap<>();
-                    if (dictId != null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                        for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                            if (Objects.equals(label.getDictId(), dictId)) {
-                                codeToNameMap.put(label.getCode(), label.getName());
-                            }
-                        }
-                    }
-                    logs.append("检验的值:").append(displayRuleValue(ruleVal, codeToNameMap)).append("\n");
-                }
-
-                // 传入的值
-                String inVal = ruleAttrMappingVo.getValue();
-                if (isPlateAttr) {
-                    logs.append("传入的值:" + plateFourCodeMap.getOrDefault(inVal, inVal) + "\n");
-                } else {
-                    Integer dictId = collect.get(0).getDictId();
-                    Map<String, String> codeToNameMap = new HashMap<>();
-                    if (dictId != null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                        for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                            if (Objects.equals(label.getDictId(), dictId)) {
-                                codeToNameMap.put(label.getCode(), label.getName());
-                            }
-                        }
-                    }
-                    String name = codeToNameMap.getOrDefault(inVal, inVal);
-                    logs.append("传入的值:" + (codeToNameMap.isEmpty() ? inVal : name) + "\n");
-                }
-
-                if (CollUtil.isNotEmpty(collect)) {
-                    logs.append("<span style=\"color:red;\">规则匹配失败:" + collect.get(0).getAttrName() + "</span>\n");
-                }
+                        link.getAttrCode(), value, link.getMin(), link.getMax(), link.getOperator());
+                appendMismatchLog(logs, attrIndex, dictIndex, link.getAttrCode(),
+                        costRule, value, true);
             }
         }
-        log.info("承保规则校验-所有条件均未命中, 规则组通过, useFlag={}", useFlag);
+        log.info("承保规则校验-所有条件均未命中, 规则组通过, useFlag={}", groupUseFlag);
         return groupUseFlag;
     }
 
-    private static boolean attrEqual(PtlAgreementCostRule ptlAgreementCostRule,
-                              PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr, String value, boolean isUnderwrite,
-                              List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-
-        if (ptlAgreementUndwrtRulesAttr == null || ptlAgreementUndwrtRulesAttr.getAttrType() == null) {
-            // 没有元数据:无法得知 attrType,按"包含"语义做纯文本兜底比较
-            // (BrandandModel 等 inputTag 大多是 contains 语义,与原逻辑 inputTextEqual 默认分支一致)
-            log.warn("attrEqual 因子元数据缺失,按纯文本兜底比较, attrCode={}", ptlAgreementCostRule.getAttrCode());
-            if (ptlAgreementCostRule.getMin() == null || value == null) return false;
-            String finalNormalizedValue = value;
-            boolean contains = Arrays.stream(ptlAgreementCostRule.getMin().split(","))
-                    .anyMatch(o -> finalNormalizedValue.contains(o.trim()));
-            return isUnderwrite ? !contains : contains;
-        }
+    // ============================================================
+    // 比较分发(统一把传入 name 还原成 code)
+    // ============================================================
 
-        // 字典还原依据:参与比较的这条因子元数据 ptlAgreementUndwrtRulesAttr 自身挂的 dictId,
-        // 再到 undwrtRulesDictList 中按 name 找 code(如 "家庭自用" -> "04")。
-        Integer dictId = ptlAgreementUndwrtRulesAttr.getDictId();
-        // ===== 新增:把传入的 name 还原成 code 再参与比较 =====
-        // 只对依赖字典的 select/radio/checkbox 做还原;input/inputNumber/date 等保留原值
-        if (CollUtil.isNotEmpty(undwrtRulesDictList)
-                && dictId != null
-                && !ptlAgreementCostRule.getAttrCode().equals("LicenseArea") // 车牌归属地无字典,纯文本
-                && !ptlAgreementCostRule.getAttrCode().equals("LicenseNo")) {
-            String normalized = value;
-            for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                if (Objects.equals(label.getDictId(), dictId) && label.getName().equals(value)) {
-                    normalized = label.getCode();
-                    break;
-                }
-            }
-            value = normalized;
-        }
-        // ====================================================
-        boolean result = false;
-        if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("checkbox")) {
-            result = checkBoxEqual(ptlAgreementCostRule, value, dictId, undwrtRulesDictList);
-        } else if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("inputNumber")) {
-            result = inputNumberEqual(ptlAgreementCostRule, value);
-        } else if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("input") || ptlAgreementUndwrtRulesAttr.getAttrType().equals("inputTag")) {
-            //截取身份证号码
-            if (ptlAgreementCostRule.getAttrCode().equals("CarOwnersIDNumber") || ptlAgreementCostRule.getAttrCode().equals("ApplicantIDNumber") ||
-                    ptlAgreementCostRule.getAttrCode().equals("InsuredIDNumber")) {
-                value = value.substring(0, ptlAgreementCostRule.getMin().length());
-            }
-            result = inputTextEqual(ptlAgreementCostRule, value);
-        } else if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("select")) {
-            //截取车牌
-            if (ptlAgreementUndwrtRulesAttr.getAttrCode().equals("LicenseNo")) {
-                value = value.substring(0, 4);
-            }
-            //车龄走数值比较,不走字典
-            if (ptlAgreementUndwrtRulesAttr.getAttrCode().equals("VehicleAge")) {
-                result = inputNumberEqual(ptlAgreementCostRule, value);
-            // LicenseArea 是 select 但无 dictId,按 input 纯文本比较(不走字典还原)
-            } else if (ptlAgreementUndwrtRulesAttr.getAttrCode().equals("LicenseArea")) {
-                result = inputTextEqual(ptlAgreementCostRule, value);
-            } else {
-                result = selectEqual(ptlAgreementCostRule, value, dictId, undwrtRulesDictList);
-            }
-        } else if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("radio")) {
-            result = radioEqual(ptlAgreementCostRule, value, dictId, undwrtRulesDictList);
-        } else if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("datetime")){ // 时间
-            result = dateTimeEqual(ptlAgreementCostRule, value);
-        } else if (ptlAgreementUndwrtRulesAttr.getAttrType().equals("date")){
-            result = dateEqual(ptlAgreementCostRule, value);
+    private static boolean attrEqual(PtlAgreementCostRule rule,
+                                     PtlAgreementUndwrtRulesAttr meta,
+                                     String value,
+                                     boolean isUnderwrite,
+                                     Map<Integer, Map<String, String>> dictIndex,
+                                     Map<Integer, Map<String, String>> dictNameIndex) {
+        if (meta == null || meta.getAttrType() == null) {
+            log.warn("attrEqual 因子元数据缺失,按纯文本兜底比较, attrCode={}", rule.getAttrCode());
+            if ((rule.getMin() == null && rule.getMax() == null) || value == null) return false;
+            return Arrays.stream(rule.getMin().split(","))
+                    .anyMatch(o -> value.contains(o.trim())) == !isUnderwrite;
         }
-        // 判断是否是承保规则
-        if(isUnderwrite){
-            return !result;
-        }else {
-            return result;
+
+        // 统一还原:传入的是 name 就翻成 code(排除无字典的纯文本字段),O(1) 查表
+        final String cmpValue = normalizeToCode(value, meta, dictNameIndex);
+
+        boolean result;
+        switch (meta.getAttrType()) {
+            case "checkbox":    result = checkBoxEqual(rule, cmpValue); break;
+            case "inputNumber": result = inputNumberEqual(rule, cmpValue); break;
+            case "input":
+            case "inputTag":    result = inputTextEqual(rule, cmpValue); break;
+            case "select":      result = selectEqual(rule, cmpValue, meta); break;
+            case "radio":       result = radioEqual(rule, cmpValue); break;
+            case "datetime":    result = dateTimeEqual(rule, cmpValue); break;
+            case "date":        result = dateEqual(rule, cmpValue); break;
+            default:            result = false;
         }
+        return isUnderwrite ? !result : result;
     }
 
-
-    private static boolean checkBoxEqual(PtlAgreementCostRule ptlAgreementCostRule, String value, Integer dictId,
-                                  List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-        if (ptlAgreementCostRule.getMin() == null || value == null) {
-            return false;
-        }
-        // dictId 为空时(无字典):把 min 里的 code 翻成 name,再用实际 value(汉字)与 name 比较
-        String[] split = ptlAgreementCostRule.getMin().split(",");
-        for (String sp : split) {
-            String spTrim = sp.trim();
-            if (dictId == null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                    if (label.getCode().equals(spTrim) && value.trim().equals(label.getName())) {
-                        return true;
-                    }
-                }
-            }
-            if (spTrim.equals(value.trim())) {
-                return true;
-            }
-        }
-        return false;
+    /** 把传入值统一还原成 code(name -> code),基于预建索引 O(1) */
+    private static String normalizeToCode(String value,
+                                          PtlAgreementUndwrtRulesAttr meta,
+                                          Map<Integer, Map<String, String>> dictNameIndex) {
+        if (value == null || dictNameIndex.isEmpty()) return value;
+        Integer dictId = meta.getDictId();
+        if (dictId == null) return value;
+        String code = meta.getAttrCode();
+        if ("LicenseNo".equals(code) || "LicenseArea".equals(code)) return value; // 无字典从PLATE_FOUR_CODE_MAP获取还原
+        Map<String, String> nameToCode = dictNameIndex.get(dictId);
+        if (nameToCode == null || nameToCode.isEmpty()) return value;
+        return nameToCode.getOrDefault(value, value);
     }
 
-    private static boolean inputNumberEqual(PtlAgreementCostRule ptlAgreementCostRule, String value) {
-        double v = Double.parseDouble(value);
-        //统一处理数值
-        if ("1".equals(ptlAgreementCostRule.getOperator())) {
-            if (Double.parseDouble(ptlAgreementCostRule.getMin()) <= v &&
-                    Double.parseDouble(ptlAgreementCostRule.getMax()) >= v) {
-                return true;
-            }
-        } else if ("2".equals(ptlAgreementCostRule.getOperator())) {
-            if (Double.parseDouble(ptlAgreementCostRule.getMin()) > v) {
-                return true;
-            }
-        } else if ("3".equals(ptlAgreementCostRule.getOperator())) {
-            if (Double.parseDouble(ptlAgreementCostRule.getMin()) >= v) {
-                return true;
-            }
-        } else if ("4".equals(ptlAgreementCostRule.getOperator())) {
-            if (Double.parseDouble(ptlAgreementCostRule.getMax()) < v) {
-                return true;
-            }
-        } else if ("5".equals(ptlAgreementCostRule.getOperator())) {
-            if (Double.parseDouble(ptlAgreementCostRule.getMax()) <= v) {
-                return true;
-            }
-        }
-        return false;
+    private static boolean checkBoxEqual(PtlAgreementCostRule rule, String value) {
+        if (rule.getMin() == null || value == null) return false;
+        return Arrays.stream(rule.getMin().split(",")).anyMatch(o -> o.trim().equals(value.trim()));
     }
 
-    private static boolean inputTextEqual(PtlAgreementCostRule ptlAgreementCostRule, String value) {
-        //将值进行分割
-        String[] split = ptlAgreementCostRule.getMin().split(",");
-        AtomicBoolean returnBool = new AtomicBoolean(false);
-
-        List<String> equalsMap = new ArrayList<>();
-        //字符型评分
-        equalsMap.add("CharacterBasedRating");
-        //交强字符型评分
-        equalsMap.add("JqCharacterBasedRating");
-        //商业字符型评分
-        equalsMap.add("SyCharacterBasedRating");
-
-
-
-        //equest 等于判断
-        if(equalsMap.contains(ptlAgreementCostRule.getAttrCode())){
-            boolean b = Arrays.stream(split).anyMatch(value::equals);
-            returnBool.set(b);
-        }else if((ptlAgreementCostRule.getAttrCode().equals("BrandandModel") || ptlAgreementCostRule.getAttrCode().equals("CarOwnerName")
-                || ptlAgreementCostRule.getAttrCode().equals("CarOwnersAddress") || ptlAgreementCostRule.getAttrCode().equals("ApplicantAddress")
-                || ptlAgreementCostRule.getAttrCode().equals("InsuredAddress"))
-                && ptlAgreementCostRule.getOperator().equals("2")){
-            //处理品牌型号  不包含的情况
-            boolean anyMatch = Arrays.stream(split)
-                    .anyMatch(value::contains);
-            returnBool.set(!anyMatch);
-        }else {
-            boolean anyMatch = Arrays.stream(split)
-                    .anyMatch(value::contains);
-            returnBool.set(anyMatch);
-        }
-        return returnBool.get();
+    private static boolean selectEqual(PtlAgreementCostRule rule, String value, PtlAgreementUndwrtRulesAttr meta) {
+        if (rule.getMin() == null || value == null) return false;
+        if ("LicenseArea".equals(meta.getAttrCode()) || "LicenseNo".equals(meta.getAttrCode())) return inputTextEqual(rule, value);
+        if ("VehicleAge".equals(meta.getAttrCode())) return inputNumberEqual(rule, value);
+        return rule.getMin().contains(value);
     }
 
-    private static boolean selectEqual(PtlAgreementCostRule ptlAgreementCostRule, String value, Integer dictId,
-                                List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-        if (ptlAgreementCostRule.getMin() == null || value == null) {
-            return false;
-        }
-        // dictId 为空时(无字典):把 min 里的 code 翻成 name,再用实际 value(汉字)与 name 比较
-        if (ptlAgreementCostRule.getOperator().equals("2")) {
-            String [] options = ptlAgreementCostRule.getMin().split(",");
-            for (String opt : options) {
-                String optTrim = opt.trim();
-                if (optTrim.equals(value.trim())) {
-                    return true;
-                }
-                if (dictId == null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                    for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                        if (label.getCode().equals(optTrim) && value.trim().equals(label.getName())) {
-                            return true;
-                        }
-                    }
-                }
-            }
+    private static boolean radioEqual(PtlAgreementCostRule rule, String value) {
+        if ("NewEnergyMark".equals(rule.getAttrCode())) {
+            boolean newEnergy = EnergyTypeCode.isNewEnergy(value);
+            if (newEnergy && "1".equals(rule.getMin())) return true;
+            if (!newEnergy && "0".equals(rule.getMin())) return true;
             return false;
-        } else if (ptlAgreementCostRule.getMin() != null) {
-            if (ptlAgreementCostRule.getMin().contains(value)) {
-                return true;
-            }
-            if (dictId == null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                    if (label.getCode().equals(ptlAgreementCostRule.getMin()) && value.equals(label.getName())) {
-                        return true;
-                    }
-                }
-            }
         }
-
-        return false;
+        return rule.getMin().contains(value);
     }
 
-    private static boolean radioEqual(PtlAgreementCostRule ptlAgreementCostRule, String value, Integer dictId,
-                               List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList) {
-        //新能源判断
-        if ("NewEnergyMark".equals(ptlAgreementCostRule.getAttrCode())) {
-            // 是否是新能源车
-            boolean newEnergy = EnergyTypeCode.isNewEnergy(value);
-            if (newEnergy && ptlAgreementCostRule.getMin().equals("1")) {
-                return true;
-            } else if (!newEnergy && ptlAgreementCostRule.getMin().equals("0")) {
-                return true;
-            }
-        } else {
-            // dictId 为空时(无字典):把 min 里的 code 翻成 name,再用实际 value(汉字)与 name 比较
-            if (dictId == null && CollUtil.isNotEmpty(undwrtRulesDictList)) {
-                for (PtlAgreementUndwrtRulesDictLabal label : undwrtRulesDictList) {
-                    if (label.getCode().equals(ptlAgreementCostRule.getMin()) && value.equals(label.getName())) {
-                        return true;
-                    }
-                }
-            }
-            if (ptlAgreementCostRule.getMin().contains(value)) {
-                return true;
-            }
+    private static boolean inputNumberEqual(PtlAgreementCostRule rule, String value) {
+        if ((rule.getMin() == null && rule.getMax() == null) || value == null) return false;
+        double v = Double.parseDouble(value);
+        double min = rule.getMin() != null ? Double.parseDouble(rule.getMin()) : Double.MIN_VALUE;
+        double max = rule.getMax() != null ? Double.parseDouble(rule.getMax()) : Double.MAX_VALUE;
+        switch (rule.getOperator()) {
+            case "1": return min <= v && v <= max;
+            case "2": return min > v;
+            case "3": return min >= v;
+            case "4": return max < v;
+            case "5": return max <= v;
+            default:  return false;
         }
-        return false;
     }
 
-    public static boolean dateTimeEqual(PtlAgreementCostRule ptlAgreementCostRule, String value){
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-        if(Objects.isNull(value) || value.equals("")){
-            return false;
-        }
-        LocalDateTime v = LocalDateTime.parse(value,formatter);
-        LocalDateTime min = null,max = null;
-        if(!Objects.isNull(ptlAgreementCostRule.getMin())){
-            min = LocalDateTime.parse(ptlAgreementCostRule.getMin(),formatter);
-        }
-        if(!Objects.isNull(ptlAgreementCostRule.getMax())){
-            max = LocalDateTime.parse(ptlAgreementCostRule.getMax(),formatter);
+    private static boolean inputTextEqual(PtlAgreementCostRule rule, String value) {
+        if (rule.getMin() == null || value == null) return false;
+        String[] split = rule.getMin().split(",");
+        List<String> equalsMap = Arrays.asList("CharacterBasedRating", "JqCharacterBasedRating", "SyCharacterBasedRating");
+        if (equalsMap.contains(rule.getAttrCode())) {
+            return Arrays.stream(split).anyMatch(value::equals);
         }
+        boolean contains = Arrays.stream(split).anyMatch(value::contains);
+        boolean notOp = ("BrandandModel".equals(rule.getAttrCode()) || "CarOwnerName".equals(rule.getAttrCode())
+                || "CarOwnersAddress".equals(rule.getAttrCode()) || "ApplicantAddress".equals(rule.getAttrCode())
+                || "InsuredAddress".equals(rule.getAttrCode())) && "2".equals(rule.getOperator());
+        return notOp ? !contains : contains;
+    }
 
-        //统一处理数值
-        if ("1".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isAfter(min) && v.isBefore(max)) {
-                return true;
-            }
-        } else if ("2".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isBefore(min)) {
-                return true;
-            }
-        } else if ("3".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isBefore(min) || v.isEqual(min)) {
-                return true;
-            }
-        } else if ("4".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isAfter(max)) {
-                return true;
-            }
-        } else if ("5".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isAfter(max) || v.isEqual(max)) {
-                return true;
-            }
-        }
-        return false;
+    public static boolean dateTimeEqual(PtlAgreementCostRule rule, String value) {
+        DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        if (StrUtil.isBlank(value)) return false;
+        LocalDateTime v = LocalDateTime.parse(value, f);
+        LocalDateTime min = rule.getMin() != null ? LocalDateTime.parse(rule.getMin(), f) : null;
+        LocalDateTime max = rule.getMax() != null ? LocalDateTime.parse(rule.getMax(), f) : null;
+        return compareDateTime(v, min, max, rule.getOperator());
     }
 
-    public static boolean dateEqual(PtlAgreementCostRule ptlAgreementCostRule, String value){
-//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        if(Objects.isNull(value) || value.equals("")){
-            return false;
-        }
+    public static boolean dateEqual(PtlAgreementCostRule rule, String value) {
+        if (StrUtil.isBlank(value)) return false;
         LocalDateTime v = LocalDate.parse(value).atStartOfDay();
-        LocalDateTime min = null,max = null;
-        if(!Objects.isNull(ptlAgreementCostRule.getMin())){
-            min = LocalDate.parse(ptlAgreementCostRule.getMin()).atStartOfDay();
-        }
-        if(!Objects.isNull(ptlAgreementCostRule.getMax())){
-            max = LocalDate.parse(ptlAgreementCostRule.getMax()).atStartOfDay();
-        }
+        LocalDateTime min = rule.getMin() != null ? LocalDate.parse(rule.getMin()).atStartOfDay() : null;
+        LocalDateTime max = rule.getMax() != null ? LocalDate.parse(rule.getMax()).atStartOfDay() : null;
+        return compareDateTime(v, min, max, rule.getOperator());
+    }
 
-        //统一处理数值
-        if ("1".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isAfter(min) && v.isBefore(max)) {
-                return true;
-            }
-        } else if ("2".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isBefore(min)) {
-                return true;
-            }
-        } else if ("3".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isBefore(min) || v.isEqual(min)) {
-                return true;
-            }
-        } else if ("4".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isAfter(max)) {
-                return true;
-            }
-        } else if ("5".equals(ptlAgreementCostRule.getOperator())) {
-            if (v.isAfter(max) || v.isEqual(max)) {
-                return true;
-            }
+    private static boolean compareDateTime(LocalDateTime v, LocalDateTime min, LocalDateTime max, String op) {
+        switch (op) {
+            case "1": return v.isAfter(min) && v.isBefore(max);
+            case "2": return v.isBefore(min);
+            case "3": return !v.isAfter(min);
+            case "4": return v.isAfter(max);
+            case "5": return !v.isBefore(max);
+            default:  return false;
         }
-        return false;
     }
-}
+}

+ 27 - 16
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/AuditVerificationAspect.java

@@ -64,20 +64,29 @@ public class AuditVerificationAspect {
 
     private final PtlNewAgreementClient ptlNewAgreementClient;
 
-    private static final Map<String, String> plateFourCodeMap = new HashMap<>();
-
+    private static final Map<String, String> PLATE_FOUR_CODE_MAP = new HashMap<>();
     static {
-        plateFourCodeMap.put("晋D", "1404");
-        plateFourCodeMap.put("晋M", "1408");
-        plateFourCodeMap.put("晋J", "1411");
-        plateFourCodeMap.put("晋C", "1403");
-        plateFourCodeMap.put("晋K", "1407");
-        plateFourCodeMap.put("晋L", "1410");
-        plateFourCodeMap.put("晋B", "1402");
-        plateFourCodeMap.put("晋F", "1406");
-        plateFourCodeMap.put("晋A", "1401");
-        plateFourCodeMap.put("晋E", "1405");
-        plateFourCodeMap.put("晋H", "1409");
+        PLATE_FOUR_CODE_MAP.put("晋D", "1404");  PLATE_FOUR_CODE_MAP.put("晋M", "1408");
+        PLATE_FOUR_CODE_MAP.put("晋J", "1411");  PLATE_FOUR_CODE_MAP.put("晋C", "1403");
+        PLATE_FOUR_CODE_MAP.put("晋K", "1407");  PLATE_FOUR_CODE_MAP.put("晋L", "1410");
+        PLATE_FOUR_CODE_MAP.put("晋B", "1402");  PLATE_FOUR_CODE_MAP.put("晋F", "1406");
+        PLATE_FOUR_CODE_MAP.put("晋A", "1401");  PLATE_FOUR_CODE_MAP.put("晋E", "1405");
+        PLATE_FOUR_CODE_MAP.put("晋H", "1409");  PLATE_FOUR_CODE_MAP.put("晋",   "14");
+        PLATE_FOUR_CODE_MAP.put("沪",   "31");   PLATE_FOUR_CODE_MAP.put("云",   "53");
+        PLATE_FOUR_CODE_MAP.put("蒙",   "15");   PLATE_FOUR_CODE_MAP.put("京",   "11");
+        PLATE_FOUR_CODE_MAP.put("吉",   "22");   PLATE_FOUR_CODE_MAP.put("川",   "51");
+        PLATE_FOUR_CODE_MAP.put("津",   "12");   PLATE_FOUR_CODE_MAP.put("宁",   "64");
+        PLATE_FOUR_CODE_MAP.put("皖",   "34");   PLATE_FOUR_CODE_MAP.put("鲁",   "37");
+        PLATE_FOUR_CODE_MAP.put("粤",   "44");   PLATE_FOUR_CODE_MAP.put("桂",   "45");
+        PLATE_FOUR_CODE_MAP.put("新",   "65");   PLATE_FOUR_CODE_MAP.put("苏",   "32");
+        PLATE_FOUR_CODE_MAP.put("赣",   "36");   PLATE_FOUR_CODE_MAP.put("冀",   "13");
+        PLATE_FOUR_CODE_MAP.put("豫",   "41");   PLATE_FOUR_CODE_MAP.put("浙",   "33");
+        PLATE_FOUR_CODE_MAP.put("琼",   "46");   PLATE_FOUR_CODE_MAP.put("鄂",   "42");
+        PLATE_FOUR_CODE_MAP.put("湘",   "43");   PLATE_FOUR_CODE_MAP.put("甘",   "62");
+        PLATE_FOUR_CODE_MAP.put("闽",   "35");   PLATE_FOUR_CODE_MAP.put("藏",   "54");
+        PLATE_FOUR_CODE_MAP.put("贵",   "52");   PLATE_FOUR_CODE_MAP.put("辽",   "21");
+        PLATE_FOUR_CODE_MAP.put("渝",   "50");   PLATE_FOUR_CODE_MAP.put("陕",   "61");
+        PLATE_FOUR_CODE_MAP.put("青",   "63");   PLATE_FOUR_CODE_MAP.put("黑",   "23");
     }
 
 
@@ -222,8 +231,11 @@ public class AuditVerificationAspect {
         log.info("=== 承保规则校验开始, 规则组数={}, 传入属性数={} ===", ruleGroups == null ? 0 : ruleGroups.size(), ruleAttrMappingVoList.size());
 
         ruleAttrMappingVoList.forEach(ruleAttrMappingVo -> {
-            if ("LicenseNo".equals(ruleAttrMappingVo.getAttrCode()) && ruleAttrMappingVo.getValue().startsWith("晋")) {
-                ruleAttrMappingVo.setValue(plateFourCodeMap.getOrDefault(ruleAttrMappingVo.getValue().substring(0, 2), ruleAttrMappingVo.getValue()));
+            if ("LicenseNo".equals(ruleAttrMappingVo.getAttrCode())) {
+                ruleAttrMappingVo.setValue(PLATE_FOUR_CODE_MAP.getOrDefault(ruleAttrMappingVo.getValue().substring(0, 2), ruleAttrMappingVo.getValue()));
+            }
+            if ("LicenseArea".equals(ruleAttrMappingVo.getAttrCode())) {
+                ruleAttrMappingVo.setValue(PLATE_FOUR_CODE_MAP.getOrDefault(ruleAttrMappingVo.getValue().substring(0, 1), ruleAttrMappingVo.getValue()));
             }
         });
 
@@ -247,7 +259,6 @@ public class AuditVerificationAspect {
             }
 
             // 直接判断该规则组是否匹配,无需循环调用
-            // 有一个匹配上  或者都没匹配上 都返回true
             boolean ruleMatched = FactorMatch.judgementsUnderwrite(ptlAgreementUndwrtRulesNews, ruleAttrMappingVoList, undwrtRulesAttrList, ruleLogs, undwrtRulesDictList);
 
             log.info("规则组[{}]匹配结果: ruleMatched={}, 错误日志=[{}]", groupIndex, ruleMatched, ruleLogs);

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

@@ -73,6 +73,31 @@ public class QuoteVerificationAspect {
     private final BaseController baseController;
     private final PtlNewAgreementClient ptlNewAgreementClient;
 
+    private static final Map<String, String> PLATE_FOUR_CODE_MAP = new HashMap<>();
+    static {
+        PLATE_FOUR_CODE_MAP.put("晋D", "1404");  PLATE_FOUR_CODE_MAP.put("晋M", "1408");
+        PLATE_FOUR_CODE_MAP.put("晋J", "1411");  PLATE_FOUR_CODE_MAP.put("晋C", "1403");
+        PLATE_FOUR_CODE_MAP.put("晋K", "1407");  PLATE_FOUR_CODE_MAP.put("晋L", "1410");
+        PLATE_FOUR_CODE_MAP.put("晋B", "1402");  PLATE_FOUR_CODE_MAP.put("晋F", "1406");
+        PLATE_FOUR_CODE_MAP.put("晋A", "1401");  PLATE_FOUR_CODE_MAP.put("晋E", "1405");
+        PLATE_FOUR_CODE_MAP.put("晋H", "1409");  PLATE_FOUR_CODE_MAP.put("晋",   "14");
+        PLATE_FOUR_CODE_MAP.put("沪",   "31");   PLATE_FOUR_CODE_MAP.put("云",   "53");
+        PLATE_FOUR_CODE_MAP.put("蒙",   "15");   PLATE_FOUR_CODE_MAP.put("京",   "11");
+        PLATE_FOUR_CODE_MAP.put("吉",   "22");   PLATE_FOUR_CODE_MAP.put("川",   "51");
+        PLATE_FOUR_CODE_MAP.put("津",   "12");   PLATE_FOUR_CODE_MAP.put("宁",   "64");
+        PLATE_FOUR_CODE_MAP.put("皖",   "34");   PLATE_FOUR_CODE_MAP.put("鲁",   "37");
+        PLATE_FOUR_CODE_MAP.put("粤",   "44");   PLATE_FOUR_CODE_MAP.put("桂",   "45");
+        PLATE_FOUR_CODE_MAP.put("新",   "65");   PLATE_FOUR_CODE_MAP.put("苏",   "32");
+        PLATE_FOUR_CODE_MAP.put("赣",   "36");   PLATE_FOUR_CODE_MAP.put("冀",   "13");
+        PLATE_FOUR_CODE_MAP.put("豫",   "41");   PLATE_FOUR_CODE_MAP.put("浙",   "33");
+        PLATE_FOUR_CODE_MAP.put("琼",   "46");   PLATE_FOUR_CODE_MAP.put("鄂",   "42");
+        PLATE_FOUR_CODE_MAP.put("湘",   "43");   PLATE_FOUR_CODE_MAP.put("甘",   "62");
+        PLATE_FOUR_CODE_MAP.put("闽",   "35");   PLATE_FOUR_CODE_MAP.put("藏",   "54");
+        PLATE_FOUR_CODE_MAP.put("贵",   "52");   PLATE_FOUR_CODE_MAP.put("辽",   "21");
+        PLATE_FOUR_CODE_MAP.put("渝",   "50");   PLATE_FOUR_CODE_MAP.put("陕",   "61");
+        PLATE_FOUR_CODE_MAP.put("青",   "63");   PLATE_FOUR_CODE_MAP.put("黑",   "23");
+    }
+
     @AfterReturning(pointcut = "@annotation(com.jzg.quotation.summary.aop.QuoteVerification)", returning = "result")
     public void doAfter(HttpResult<QuoteResultsVo> result) {
         String loginUserId = baseController.getUserId();
@@ -130,10 +155,6 @@ public class QuoteVerificationAspect {
             log.info("过滤的费用列表:{}",JSONObject.toJSONString(agreementProductCosts));
             if (CollUtil.isNotEmpty(agreementProductCosts)) {
                 //遍历费用因子
-                HttpResult<String> convertLicense2AreaNumber = orgClient.convertLicense2AreaNumber(insOrdersCarInfo.getLicenseNo().substring(0, 2));
-                if(convertLicense2AreaNumber.isSuccess()){
-                    insOrdersCarInfo.setLicenseNo(convertLicense2AreaNumber.getData());//车牌转code
-                }
                 String costId = verificationCosts(agreementProductCosts, logs, insOrdersOther, insOrdersCarInfo, insOrdersRisks,
                         insOrdersCarUserInfos, kindList, insOrdersCosts, insOrdersAccidentalDriving, insOrders);
                 if (costId != null) {
@@ -249,16 +270,20 @@ public class QuoteVerificationAspect {
                                      InsOrdersAccidentalDriving insOrdersAccidentalDriving, InsOrders insOrders) {
         //获取所有费用属性
         List<PtlAgreementUndwrtRulesAttr> undwrtRulesAttrList = orgClient.list().getData();
-//        HttpResult comparenew = orgClient.compareNewCar(insOrdersCarInfo.getRegisterDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), insOrders.getCompanyId(), insOrdersCarInfo.getVehicleUseCode());
         boolean isNewCar = false;
-//        if(comparenew.getCode()== 200) {
-//            // 新旧车判断
-//             isNewCar = comparenew.getData().equals("true") ? true : false;
-//        }
         //获取所有费用属性关联
         List<RuleAttrMappingVo> ruleAttrMappingVoList = RuleAttrMappingVo.getRuleAttrMappingVoList(insOrdersOther,insOrdersCarInfo,
                 riskList, insOrdersCarUserInfos, kindList, insOrdersCosts, insOrdersAccidentalDriving, isNewCar, insOrders.getCompanyId());
 
+        ruleAttrMappingVoList.forEach(ruleAttrMappingVo -> {
+            if ("LicenseNo".equals(ruleAttrMappingVo.getAttrCode())) {
+                ruleAttrMappingVo.setValue(PLATE_FOUR_CODE_MAP.getOrDefault(ruleAttrMappingVo.getValue().substring(0, 2), ruleAttrMappingVo.getValue()));
+            }
+            if ("LicenseArea".equals(ruleAttrMappingVo.getAttrCode())) {
+                ruleAttrMappingVo.setValue(PLATE_FOUR_CODE_MAP.getOrDefault(ruleAttrMappingVo.getValue().substring(0, 1), ruleAttrMappingVo.getValue()));
+            }
+        });
+
         // 字典数据在一次报价内是只读不变的,提到循环外避免N+1远程调用
         // 修复批量报价时该方法被 organization 服务打爆的问题
         List<PtlAgreementUndwrtRulesDictLabal> undwrtRulesDictList = ptlNewAgreementClient.getUndwrtRulesDictList();
@@ -738,56 +763,72 @@ public class QuoteVerificationAspect {
 
     }
 
-    /**
-     * 计算分销费
-     */
-    private BigDecimal calculateDistributionFee(InsOrdersCosts insOrdersCosts, InsFeeOrders insFeeOrders,InsOrders insOrders){
+    private BigDecimal calculateDistributionFee(InsOrdersCosts insOrdersCosts, InsFeeOrders insFeeOrders, InsOrders insOrders) {
         // 总保费
         BigDecimal totalPremium = insOrdersCosts.getJqPremium().add(insOrdersCosts.getSyPremium()).add(insOrdersCosts.getJyPremium());
+
         // 获取当前租户信息
         HttpResult<SysUserJzgInfo> sysUserJzgInfoResult = orgClient.getUserInfoByMobile(insOrders.getRealQuoteUserId());
         SysUserJzgInfo currentUser = sysUserJzgInfoResult.getData();
+
         // 获取租户分销设置
         HttpResult<SysDistributionSetting> setting = orgClient.getSettingBySystemCode();
         SysDistributionSetting sysDistributionSetting = setting.getData();
+
         if (sysDistributionSetting != null) {
             // 判断业务员所属机构是否被排除
-            // 1.获取业务员所属机构
             String deptId = sysUserJzgInfoResult.getData().getDeptId();
             HttpResult<SysDeptVo> sysDept = orgClient.deptGet(deptId);
+
             if (sysDept.getData() != null && sysDept.getData().getIsDistribution().equals("1")) {
-                // 获取租户分销设置为几级分销
                 String level = sysDistributionSetting.getDistributionMode();
                 BigDecimal diffAmount = BigDecimal.ZERO;
+
                 switch (level) {
-                    case "1":
-                        Map<String,Object> map = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
-                        if(Objects.nonNull(map)){
-                            diffAmount = new BigDecimal(map.get("diffAmount").toString());
+                    case "1" -> {
+                        Map<String, Object> level1Result = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
+                        if (Objects.nonNull(level1Result)) {
+                            diffAmount = diffAmount.add(new BigDecimal(level1Result.get("diffAmount").toString()));
                         }
-                        break;
-                    case "2":
-
-                        Map<String,Object> firstDistributor = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
+                    }
+                    case "2" -> {
+                        // 计算一级分销
+                        Map<String, Object> firstDistributor = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
                         if (firstDistributor != null) {
-                            Map<String,Object> level2map = calculateLevel2Distribution(insFeeOrders, totalPremium, firstDistributor.get("id").toString(), sysDistributionSetting);
-                            if(Objects.nonNull(level2map)){
-                                diffAmount = new BigDecimal(level2map.get("diffAmount").toString());
-                            }
                             diffAmount = diffAmount.add(new BigDecimal(firstDistributor.get("diffAmount").toString()));
+
+                            // 判断一级分销用户是否为团队长,如果是则不再计算二级
+                            if (!isTeamLeader(firstDistributor.get("id").toString())) {
+                                Map<String, Object> level2Result = calculateLevel2Distribution(insFeeOrders, totalPremium, firstDistributor.get("id").toString(), sysDistributionSetting);
+                                if (Objects.nonNull(level2Result)) {
+                                    diffAmount = diffAmount.add(new BigDecimal(level2Result.get("diffAmount").toString()));
+                                }
+                            }
+                            // 如果一级是团队长,二级分销费用已经在calculateLevel1Distribution中设置为0
                         }
-                        break;
-                    case "3":
-                        Map<String,Object> level1 = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getId(), sysDistributionSetting);
+                    }
+                    case "3" -> {
+                        // 计算一级分销
+                        Map<String, Object> level1 = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getId(), sysDistributionSetting);
                         if (level1 != null) {
-                            Map<String,Object> level2 = calculateLevel2Distribution(insFeeOrders, totalPremium, level1.get("id").toString(), sysDistributionSetting);
-                            if (level2 != null) {
-                                diffAmount = calculateLevel3Distribution(insFeeOrders, totalPremium, level2.get("id").toString(), sysDistributionSetting);
-                                diffAmount = diffAmount.add(new BigDecimal(level2.get("diffAmount").toString()));
-                            }
                             diffAmount = diffAmount.add(new BigDecimal(level1.get("diffAmount").toString()));
+
+                            // 判断一级分销用户是否为团队长
+                            if (!isTeamLeader(level1.get("id").toString())) {
+                                // 计算二级分销
+                                Map<String, Object> level2 = calculateLevel2Distribution(insFeeOrders, totalPremium, level1.get("id").toString(), sysDistributionSetting);
+                                if (level2 != null) {
+                                    diffAmount = diffAmount.add(new BigDecimal(level2.get("diffAmount").toString()));
+                                    // 判断二级分销用户是否为团队长
+                                    if (!isTeamLeader(level2.get("id").toString())) {
+                                        // 计算三级分销
+                                        BigDecimal level3Diff = calculateLevel3Distribution(insFeeOrders, totalPremium, level2.get("id").toString(), sysDistributionSetting);
+                                        diffAmount = diffAmount.add(level3Diff);
+                                    }
+                                }
+                            }
                         }
-                        break;
+                    }
                 }
                 return diffAmount;
             }
@@ -796,26 +837,39 @@ public class QuoteVerificationAspect {
     }
 
     /**
-     * 计算一级分销费
-     * @return 一级分销员ID,若不存在则返回null
+     * 计算一级分销,返回结果包含用户ID和差额
+     * 如果该级是团队长,会清空后续所有分销费用
      */
-    private Map<String,Object> calculateLevel1Distribution(InsFeeOrders insFeeOrders, BigDecimal totalPremium,
-                                               String userId, SysDistributionSetting setting) {
+    private Map<String, Object> calculateLevel1Distribution(InsFeeOrders insFeeOrders, BigDecimal totalPremium,
+                                                            String userId, SysDistributionSetting setting) {
         HttpResult<EsmUserReferrer> referrerResult = orgClient.getReferrer(userId);
         if (referrerResult.getData() != null) {
             EsmUserReferrer referrer = referrerResult.getData();
             HttpResult<SysUserJzgInfo> referrerInfoResult = orgClient.getUserInfo(referrer.getReferrerId());
             if (referrerInfoResult.getData() != null && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
                 String distributorId = referrer.getReferrerId();
+
                 BigDecimal commissionRatio1 = setting.getCommissionRatioLevel1().divide(new BigDecimal(100)).setScale(5, RoundingMode.DOWN);
                 insFeeOrders.setFirstDistributorId(distributorId);
-                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio1).setScale(5,RoundingMode.DOWN));
-                insFeeOrders.setFirstDistributionFee(totalPremium.multiply(commissionRatio1).setScale(2,RoundingMode.DOWN));
+                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio1).setScale(5, RoundingMode.DOWN));
+                insFeeOrders.setFirstDistributionFee(totalPremium.multiply(commissionRatio1).setScale(2, RoundingMode.DOWN));
                 insFeeOrders.setFirstDistributionRatio(commissionRatio1.multiply(new BigDecimal(100)));
                 BigDecimal diffAmount = fee_5.subtract(insFeeOrders.getFirstDistributionFee());
-                Map map = new HashMap();
-                map.put("id",distributorId);
-                map.put("diffAmount",diffAmount);
+
+                // 如果一级分销是团队长,清空后续分销费用(二级、三级)
+                if (isTeamLeader(distributorId)) {
+                    insFeeOrders.setSecondDistributionFee(BigDecimal.ZERO);
+                    insFeeOrders.setSecondDistributionRatio(BigDecimal.ZERO);
+                    insFeeOrders.setThirdDistributionFee(BigDecimal.ZERO);
+                    insFeeOrders.setThirdDistributionRatio(BigDecimal.ZERO);
+                    // 清空后续分销人ID
+                    insFeeOrders.setSecondDistributorId(null);
+                    insFeeOrders.setThirdDistributorId(null);
+                }
+
+                Map<String, Object> map = new HashMap<>();
+                map.put("id", distributorId);
+                map.put("diffAmount", diffAmount);
                 return map;
             } else {
                 insFeeOrders.setFirstDistributionFee(BigDecimal.ZERO);
@@ -826,26 +880,35 @@ public class QuoteVerificationAspect {
     }
 
     /**
-     * 计算二级分销费
-     * @return 二级分销员ID,若不存在则返回null
+     * 计算二级分销,返回结果包含用户ID和差额
+     * 如果该级是团队长,会清空后续分销费用(三级)
      */
-    private Map<String,Object> calculateLevel2Distribution(InsFeeOrders insFeeOrders, BigDecimal totalPremium,
-                                               String upperDistributorId, SysDistributionSetting setting) {
+    private Map<String, Object> calculateLevel2Distribution(InsFeeOrders insFeeOrders, BigDecimal totalPremium,
+                                                            String upperDistributorId, SysDistributionSetting setting) {
         HttpResult<EsmUserReferrer> referrerResult = orgClient.getReferrer(upperDistributorId);
         if (referrerResult.getData() != null) {
             EsmUserReferrer referrer = referrerResult.getData();
             HttpResult<SysUserJzgInfo> referrerInfoResult = orgClient.getUserInfo(referrer.getReferrerId());
             if (referrerInfoResult.getData() != null && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
                 String distributorId = referrer.getReferrerId();
+
                 BigDecimal commissionRatio2 = setting.getCommissionRatioLevel2().divide(new BigDecimal(100)).setScale(5, RoundingMode.DOWN);
                 insFeeOrders.setSecondDistributorId(distributorId);
-                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio2).setScale(5,RoundingMode.DOWN));
-                insFeeOrders.setSecondDistributionFee(totalPremium.multiply(commissionRatio2).setScale(2,RoundingMode.DOWN));
+                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio2).setScale(5, RoundingMode.DOWN));
+                insFeeOrders.setSecondDistributionFee(totalPremium.multiply(commissionRatio2).setScale(2, RoundingMode.DOWN));
                 insFeeOrders.setSecondDistributionRatio(commissionRatio2.multiply(new BigDecimal(100)));
                 BigDecimal diffAmount = fee_5.subtract(insFeeOrders.getSecondDistributionFee());
-                Map map = new HashMap();
-                map.put("id",distributorId);
-                map.put("diffAmount",diffAmount);
+
+                // 如果二级分销是团队长,清空后续分销费用(三级)
+                if (isTeamLeader(distributorId)) {
+                    insFeeOrders.setThirdDistributionFee(BigDecimal.ZERO);
+                    insFeeOrders.setThirdDistributionRatio(BigDecimal.ZERO);
+                    insFeeOrders.setThirdDistributorId(null);
+                }
+
+                Map<String, Object> map = new HashMap<>();
+                map.put("id", distributorId);
+                map.put("diffAmount", diffAmount);
                 return map;
             } else {
                 insFeeOrders.setSecondDistributionFee(BigDecimal.ZERO);
@@ -856,21 +919,24 @@ public class QuoteVerificationAspect {
     }
 
     /**
-     * 计算三级分销费
+     * 计算三级分销,返回差额
      */
     private BigDecimal calculateLevel3Distribution(InsFeeOrders insFeeOrders, BigDecimal totalPremium,
-                                             String upperDistributorId, SysDistributionSetting setting) {
+                                                   String upperDistributorId, SysDistributionSetting setting) {
         HttpResult<EsmUserReferrer> referrerResult = orgClient.getReferrer(upperDistributorId);
         if (referrerResult.getData() != null) {
             EsmUserReferrer referrer = referrerResult.getData();
             HttpResult<SysUserJzgInfo> referrerInfoResult = orgClient.getUserInfo(referrer.getReferrerId());
             if (referrerInfoResult.getData() != null && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
-                insFeeOrders.setThirdDistributorId(referrer.getReferrerId());
+                String distributorId = referrer.getReferrerId();
+                insFeeOrders.setThirdDistributorId(distributorId);
                 BigDecimal commissionRatio3 = setting.getCommissionRatioLevel3().divide(new BigDecimal(100)).setScale(5, RoundingMode.DOWN);
-                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio3).setScale(5,RoundingMode.DOWN));
-                insFeeOrders.setThirdDistributionFee(totalPremium.multiply(commissionRatio3).setScale(2,RoundingMode.DOWN));
+                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio3).setScale(5, RoundingMode.DOWN));
+                insFeeOrders.setThirdDistributionFee(totalPremium.multiply(commissionRatio3).setScale(2, RoundingMode.DOWN));
                 insFeeOrders.setThirdDistributionRatio(commissionRatio3.multiply(new BigDecimal(100)));
                 BigDecimal diffAmount = fee_5.subtract(insFeeOrders.getThirdDistributionFee());
+
+                // 三级分销如果是团队长,无需清空后续(已经是最后一级)
                 return diffAmount;
             } else {
                 insFeeOrders.setThirdDistributionFee(BigDecimal.ZERO);
@@ -880,6 +946,20 @@ public class QuoteVerificationAspect {
         return BigDecimal.ZERO;
     }
 
+
+    /**
+     * 判断用户是否为团队长
+     */
+    private boolean isTeamLeader(String userId) {
+        try {
+            HttpResult<List<SysOrganization>> organizations = orgClient.queryOrganizationByManagerId(userId);
+            return organizations.getData() != null && !organizations.getData().isEmpty();
+        } catch (Exception e) {
+            // 异常处理,默认不是团队长
+            return false;
+        }
+    }
+
     @Before("@annotation(com.jzg.quotation.summary.aop.QuoteVerification)")
     public void doBefore(JoinPoint point) {
         Object[] args = point.getArgs();

+ 13 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeOrderController.java

@@ -5,6 +5,7 @@ import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.dto.InsFeeOrdersParam;
 import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.po.InsFeeOrdersSummary;
 import com.jzg.commons.entity.report.dto.ReportOperatingProfitDataDto;
 import com.jzg.quotation.summary.entity.dto.RightsAmountUpdateDto;
 import com.jzg.quotation.summary.service.InsFeeOrdersService;
@@ -57,6 +58,18 @@ public class InsFeeOrderController {
         return insFeeOrdersService.getInsFeeOrderListByUserId(insFeeOrdersParam);
     }
 
+    /**
+     * 针对getInsFeeOrderByUserId 方法的优化,当订单很多的时候,提升性能
+     *
+     * @author lipf
+     * @date 2026/9/1 10:25
+     */
+    @PostMapping(value = "/getInsFeeOrderSummaryByUserId")
+    InsFeeOrdersSummary getInsFeeOrderSummaryByUserId(@RequestBody InsFeeOrdersParam param){
+        return insFeeOrdersService.getInsFeeOrderSummaryByUserId(param);
+    }
+
+
     @GetMapping("/getInsFeeOrderListByTopReferrerIdAndUserId")
     @Operation(summary = "订单费用列表通过上下级分销员id查询")
     public List<InsFeeOrders> getInsFeeOrder(String userId,String topReferrerId){

+ 7 - 2
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/mapper/InsFeeOrdersMapper.java

@@ -3,6 +3,7 @@ package com.jzg.quotation.summary.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.jzg.commons.entity.dto.InsFeeOrdersParam;
 import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.po.InsFeeOrdersSummary;
 import com.jzg.commons.entity.report.dto.ReportOperatingProfitDataDto;
 import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Mapper;
@@ -76,6 +77,10 @@ public interface InsFeeOrdersMapper extends BaseMapper<InsFeeOrders> {
                                                                   @Param("signTimeEnd") LocalDateTime signTimeEnd,
                                                                   @Param("systemCode") String systemCode);
 
-
-
+    /**
+     *
+     * @author lipf
+     * @date 2026/9/1 10:30
+     */
+    InsFeeOrdersSummary getInsFeeOrderSummaryByUserId(@Param("insFeeOrdersParam") InsFeeOrdersParam param);
 }

+ 8 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeOrdersService.java

@@ -5,6 +5,7 @@ import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.dto.CostCalculateRespVO;
 import com.jzg.commons.entity.dto.InsFeeOrdersParam;
 import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.po.InsFeeOrdersSummary;
 import com.jzg.commons.entity.report.dto.ReportOperatingProfitDataDto;
 import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
 
@@ -69,4 +70,11 @@ public interface InsFeeOrdersService extends IService<InsFeeOrders> {
      * @date 2026/7/25 11:22
      */
     Map<String,ReportOperatingProfitDataDto> queryOperatingProfits(Integer year, String systemCode, String sqlType);
+
+    /**
+     * 查询订单数和这些订单的汇总信息
+     * @author lipf
+     * @date 2026/9/1 10:27
+     */
+    InsFeeOrdersSummary getInsFeeOrderSummaryByUserId(InsFeeOrdersParam param);
 }

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

@@ -13,6 +13,7 @@ import com.jzg.commons.entity.orders.po.InsFeeAudit;
 import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.orders.po.InsOrdersCosts;
 import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.po.InsFeeOrdersSummary;
 import com.jzg.commons.entity.po.PtlAgreement;
 import com.jzg.commons.entity.report.dto.ReportOperatingProfitDataDto;
 import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
@@ -469,6 +470,25 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
         return insFeeOrdersMapper.getInsFeeOrdersList(param);
     }
 
+
+    /**
+     * 查询订单数和这些订单的汇总信息
+     *
+     * @param param
+     * @author lipf
+     * @date 2026/9/1 10:27
+     */
+    @Override
+    public InsFeeOrdersSummary getInsFeeOrderSummaryByUserId(InsFeeOrdersParam param) {
+        log.info("查询订单数和这些订单的汇总信息: param=[{}]", JSONUtil.toJsonStr(param));
+        // 在报价哪里, userId 保存的是用户的手机号
+        String userName = baseController.getUserName();
+        param.setUserId(userName);
+        InsFeeOrdersSummary summary = insFeeOrdersMapper.getInsFeeOrderSummaryByUserId(param);
+        log.info("查询订单数和这些订单的汇总信息: param=[{}]. summary=[{}]", JSONUtil.toJsonStr(param), JSONUtil.toJsonStr(summary));
+        return summary;
+    }
+
     @Override
     public List<InsFeeOrders> getInsFeeOrderListByUserId(InsFeeOrdersParam param) {
         log.info("getInsFeeOrderListByUserId的查询条件:param=[{}]", JSONUtil.toJsonStr(param));

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

@@ -2185,60 +2185,99 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
     }
 
     private Map<String, Object> calcDistLevel1(InsFeeOrders o, BigDecimal totalPremium, String userId, SysDistributionSetting setting) {
-        HttpResult<EsmUserReferrer> ref = orgClient.getReferrer(userId);
-        if (ref == null || ref.getData() == null) return null;
-        EsmUserReferrer referrer = ref.getData();
-        HttpResult<SysUserJzgInfo> info = orgClient.getUserInfo(referrer.getReferrerId());
-        if (info == null || info.getData() == null || !"1".equals(info.getData().getIsDistribution())) {
-            o.setFirstDistributionFee(BigDecimal.ZERO);
-            o.setFirstDistributionRatio(BigDecimal.ZERO);
-            return null;
-        }
-        o.setFirstDistributorId(referrer.getReferrerId());
-        BigDecimal fee5 = totalPremium.multiply(setting.getCommissionRatioLevel1()).setScale(5, RoundingMode.DOWN);
-        o.setFirstDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel1()).setScale(2, RoundingMode.DOWN));
-        o.setFirstDistributionRatio(setting.getCommissionRatioLevel1());
-        Map<String, Object> map = new HashMap<>();
-        map.put("id", referrer.getReferrerId());
-        map.put("diffAmount", fee5.subtract(o.getFirstDistributionFee()));
-        return map;
+        HttpResult<EsmUserReferrer> referrerResult = orgClient.getReferrer(userId);
+        if (referrerResult.getData() != null) {
+            EsmUserReferrer referrer = referrerResult.getData();
+            HttpResult<SysUserJzgInfo> referrerInfoResult = orgClient.getUserInfo(referrer.getReferrerId());
+            if (referrerInfoResult.getData() != null && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
+                String distributorId = referrer.getReferrerId();
+
+                BigDecimal commissionRatio1 = setting.getCommissionRatioLevel1().divide(new BigDecimal(100)).setScale(5, RoundingMode.DOWN);
+                o.setFirstDistributorId(distributorId);
+                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio1).setScale(5, RoundingMode.DOWN));
+                o.setFirstDistributionFee(totalPremium.multiply(commissionRatio1).setScale(2, RoundingMode.DOWN));
+                o.setFirstDistributionRatio(commissionRatio1.multiply(new BigDecimal(100)));
+                BigDecimal diffAmount = fee_5.subtract(o.getFirstDistributionFee());
+
+                // 如果一级分销是团队长,清空后续分销费用(二级、三级)
+                if (isTeamLeader(distributorId)) {
+                    o.setSecondDistributionFee(BigDecimal.ZERO);
+                    o.setSecondDistributionRatio(BigDecimal.ZERO);
+                    o.setThirdDistributionFee(BigDecimal.ZERO);
+                    o.setThirdDistributionRatio(BigDecimal.ZERO);
+                    // 清空后续分销人ID
+                    o.setSecondDistributorId(null);
+                    o.setThirdDistributorId(null);
+                }
+
+                Map<String, Object> map = new HashMap<>();
+                map.put("id", distributorId);
+                map.put("diffAmount", diffAmount);
+                return map;
+            } else {
+                o.setFirstDistributionFee(BigDecimal.ZERO);
+                o.setFirstDistributionRatio(BigDecimal.ZERO);
+            }
+        }
+        return null;
     }
 
     private Map<String, Object> calcDistLevel2(InsFeeOrders o, BigDecimal totalPremium, String upperId, SysDistributionSetting setting) {
-        HttpResult<EsmUserReferrer> ref = orgClient.getReferrer(upperId);
-        if (ref == null || ref.getData() == null) return null;
-        EsmUserReferrer referrer = ref.getData();
-        HttpResult<SysUserJzgInfo> info = orgClient.getUserInfo(referrer.getReferrerId());
-        if (info == null || info.getData() == null || !"1".equals(info.getData().getIsDistribution())) {
-            o.setSecondDistributionFee(BigDecimal.ZERO);
-            o.setSecondDistributionRatio(BigDecimal.ZERO);
-            return null;
-        }
-        o.setSecondDistributorId(referrer.getReferrerId());
-        BigDecimal fee5 = totalPremium.multiply(setting.getCommissionRatioLevel2()).setScale(5, RoundingMode.DOWN);
-        o.setSecondDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel2()).setScale(2, RoundingMode.DOWN));
-        o.setSecondDistributionRatio(setting.getCommissionRatioLevel2());
-        Map<String, Object> map = new HashMap<>();
-        map.put("id", referrer.getReferrerId());
-        map.put("diffAmount", fee5.subtract(o.getSecondDistributionFee()));
-        return map;
+        HttpResult<EsmUserReferrer> referrerResult = orgClient.getReferrer(upperId);
+        if (referrerResult.getData() != null) {
+            EsmUserReferrer referrer = referrerResult.getData();
+            HttpResult<SysUserJzgInfo> referrerInfoResult = orgClient.getUserInfo(referrer.getReferrerId());
+            if (referrerInfoResult.getData() != null && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
+                String distributorId = referrer.getReferrerId();
+
+                BigDecimal commissionRatio2 = setting.getCommissionRatioLevel2().divide(new BigDecimal(100)).setScale(5, RoundingMode.DOWN);
+                o.setSecondDistributorId(distributorId);
+                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio2).setScale(5, RoundingMode.DOWN));
+                o.setSecondDistributionFee(totalPremium.multiply(commissionRatio2).setScale(2, RoundingMode.DOWN));
+                o.setSecondDistributionRatio(commissionRatio2.multiply(new BigDecimal(100)));
+                BigDecimal diffAmount = fee_5.subtract(o.getSecondDistributionFee());
+
+                // 如果二级分销是团队长,清空后续分销费用(三级)
+                if (isTeamLeader(distributorId)) {
+                    o.setThirdDistributionFee(BigDecimal.ZERO);
+                    o.setThirdDistributionRatio(BigDecimal.ZERO);
+                    o.setThirdDistributorId(null);
+                }
+
+                Map<String, Object> map = new HashMap<>();
+                map.put("id", distributorId);
+                map.put("diffAmount", diffAmount);
+                return map;
+            } else {
+                o.setSecondDistributionFee(BigDecimal.ZERO);
+                o.setSecondDistributionRatio(BigDecimal.ZERO);
+            }
+        }
+        return null;
     }
 
     private BigDecimal calcDistLevel3(InsFeeOrders o, BigDecimal totalPremium, String upperId, SysDistributionSetting setting) {
-        HttpResult<EsmUserReferrer> ref = orgClient.getReferrer(upperId);
-        if (ref == null || ref.getData() == null) return BigDecimal.ZERO;
-        EsmUserReferrer referrer = ref.getData();
-        HttpResult<SysUserJzgInfo> info = orgClient.getUserInfo(referrer.getReferrerId());
-        if (info == null || info.getData() == null || !"1".equals(info.getData().getIsDistribution())) {
-            o.setThirdDistributionFee(BigDecimal.ZERO);
-            o.setThirdDistributionRatio(BigDecimal.ZERO);
-            return BigDecimal.ZERO;
-        }
-        o.setThirdDistributorId(referrer.getReferrerId());
-        BigDecimal fee5 = totalPremium.multiply(setting.getCommissionRatioLevel3()).setScale(5, RoundingMode.DOWN);
-        o.setThirdDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel3()).setScale(2, RoundingMode.DOWN));
-        o.setThirdDistributionRatio(setting.getCommissionRatioLevel3());
-        return fee5.subtract(o.getThirdDistributionFee());
+        HttpResult<EsmUserReferrer> referrerResult = orgClient.getReferrer(upperId);
+        if (referrerResult.getData() != null) {
+            EsmUserReferrer referrer = referrerResult.getData();
+            HttpResult<SysUserJzgInfo> referrerInfoResult = orgClient.getUserInfo(referrer.getReferrerId());
+            if (referrerInfoResult.getData() != null && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
+                String distributorId = referrer.getReferrerId();
+                o.setThirdDistributorId(distributorId);
+                BigDecimal commissionRatio3 = setting.getCommissionRatioLevel3().divide(new BigDecimal(100)).setScale(5, RoundingMode.DOWN);
+                BigDecimal fee_5 = (totalPremium.multiply(commissionRatio3).setScale(5, RoundingMode.DOWN));
+                o.setThirdDistributionFee(totalPremium.multiply(commissionRatio3).setScale(2, RoundingMode.DOWN));
+                o.setThirdDistributionRatio(commissionRatio3.multiply(new BigDecimal(100)));
+                BigDecimal diffAmount = fee_5.subtract(o.getThirdDistributionFee());
+
+                // 三级分销如果是团队长,无需清空后续(已经是最后一级)
+                return diffAmount;
+            } else {
+                o.setThirdDistributionFee(BigDecimal.ZERO);
+                o.setThirdDistributionRatio(BigDecimal.ZERO);
+            }
+        }
+        return BigDecimal.ZERO;
     }
 
     // ===== 费用计算辅助方法 =====
@@ -2468,59 +2507,99 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
      * 区别:userId 取自当前登录用户 baseController.getUserId(),而非订单。
      *
      * @param totalPremium 总保费
-     * @param feeOrders    费用订单对象(用于设置分销字段)
+     * @param insFeeOrders    费用订单对象(用于设置分销字段)
      * @param mobile       业务员手机号
      * @return 分销精度差值(scale=5 - scale=2)
      */
-    private BigDecimal calcDistributionFee(BigDecimal totalPremium, InsFeeOrders feeOrders, String mobile) {
-
-        HttpResult<SysUserJzgInfo> userResult = orgClient.getUserInfoByMobile(mobile);
-        if (userResult == null || userResult.getData() == null) {
-            return BigDecimal.ZERO;
-        }
-        String userId = userResult.getData().getUserId();
+    private BigDecimal calcDistributionFee(BigDecimal totalPremium, InsFeeOrders insFeeOrders, String mobile) {
+        // 获取当前租户信息
+        HttpResult<SysUserJzgInfo> sysUserJzgInfoResult = orgClient.getUserInfoByMobile(mobile);
+        SysUserJzgInfo currentUser = sysUserJzgInfoResult.getData();
 
         // 获取租户分销设置
-        HttpResult<SysDistributionSetting> settingResult = orgClient.getSettingBySystemCode();
-        if (settingResult == null || settingResult.getData() == null) {
-            return BigDecimal.ZERO;
-        }
-        SysDistributionSetting sysDistributionSetting = settingResult.getData();
-        // 判断业务员所属机构是否开启分销
-        String deptId = userResult.getData().getDeptId();
-        HttpResult<SysDeptVo> deptResult = orgClient.deptGet(deptId);
-        if (deptResult == null || deptResult.getData() == null || !"1".equals(deptResult.getData().getIsDistribution())) {
-            return BigDecimal.ZERO;
-        }
-        String level = sysDistributionSetting.getDistributionMode();
-        BigDecimal diffAmount = BigDecimal.ZERO;
-        switch (level) {
-            case "1":
-                Map<String, Object> lv1 = calcDistLevel1(feeOrders, totalPremium, userId, sysDistributionSetting);
-                if (lv1 != null) diffAmount = new BigDecimal(lv1.get("diffAmount").toString());
-                break;
-            case "2":
-                Map<String, Object> first = calcDistLevel1(feeOrders, totalPremium, userId, sysDistributionSetting);
-                if (first != null) {
-                    Map<String, Object> second = calcDistLevel2(feeOrders, totalPremium, first.get("id").toString(), sysDistributionSetting);
-                    if (second != null) diffAmount = new BigDecimal(second.get("diffAmount").toString());
-                    diffAmount = diffAmount.add(new BigDecimal(first.get("diffAmount").toString()));
-                }
-                break;
-            case "3":
-                Map<String, Object> l1 = calcDistLevel1(feeOrders, totalPremium, userId, sysDistributionSetting);
-                if (l1 != null) {
-                    Map<String, Object> l2 = calcDistLevel2(feeOrders, totalPremium, l1.get("id").toString(), sysDistributionSetting);
-                    if (l2 != null) {
-                        BigDecimal l3Diff = calcDistLevel3(feeOrders, totalPremium, l2.get("id").toString(), sysDistributionSetting);
-                        diffAmount = diffAmount.add(l3Diff);
-                        diffAmount = diffAmount.add(new BigDecimal(l2.get("diffAmount").toString()));
-                    }
-                    diffAmount = diffAmount.add(new BigDecimal(l1.get("diffAmount").toString()));
+        HttpResult<SysDistributionSetting> setting = orgClient.getSettingBySystemCode();
+        SysDistributionSetting sysDistributionSetting = setting.getData();
+
+        if (sysDistributionSetting != null) {
+            // 判断业务员所属机构是否被排除
+            String deptId = sysUserJzgInfoResult.getData().getDeptId();
+            HttpResult<SysDeptVo> sysDept = orgClient.deptGet(deptId);
+
+            if (sysDept.getData() != null && sysDept.getData().getIsDistribution().equals("1")) {
+                String level = sysDistributionSetting.getDistributionMode();
+                BigDecimal diffAmount = BigDecimal.ZERO;
+
+                switch (level) {
+                    case "1":
+                        Map<String, Object> level1Result = calcDistLevel1(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
+                        if (Objects.nonNull(level1Result)) {
+                            diffAmount = diffAmount.add(new BigDecimal(level1Result.get("diffAmount").toString()));
+                        }
+                        break;
+
+                    case "2":
+                        // 计算一级分销
+                        Map<String, Object> firstDistributor = calcDistLevel1(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
+                        if (firstDistributor != null) {
+                            diffAmount = diffAmount.add(new BigDecimal(firstDistributor.get("diffAmount").toString()));
+
+                            // 判断一级分销用户是否为团队长,如果不是则继续计算二级
+                            if (!isTeamLeader(firstDistributor.get("id").toString())) {
+                                Map<String, Object> level2Result = calcDistLevel2(insFeeOrders, totalPremium, firstDistributor.get("id").toString(), sysDistributionSetting);
+                                if (Objects.nonNull(level2Result)) {
+                                    diffAmount = diffAmount.add(new BigDecimal(level2Result.get("diffAmount").toString()));
+                                }
+                            }
+                            // 如果一级是团队长,二级分销费用已经在calculateLevel1Distribution中设置为0
+                        }
+                        break;
+
+                    case "3":
+                        // 计算一级分销
+                        Map<String, Object> level1 = calcDistLevel1(insFeeOrders, totalPremium, currentUser.getId(), sysDistributionSetting);
+                        if (level1 != null) {
+                            diffAmount = diffAmount.add(new BigDecimal(level1.get("diffAmount").toString()));
+
+                            // 判断一级分销用户是否为团队长
+                            if (!isTeamLeader(level1.get("id").toString())) {
+                                // 计算二级分销
+                                Map<String, Object> level2 = calcDistLevel2(insFeeOrders, totalPremium, level1.get("id").toString(), sysDistributionSetting);
+                                if (level2 != null) {
+                                    diffAmount = diffAmount.add(new BigDecimal(level2.get("diffAmount").toString()));
+
+                                    // 判断二级分销用户是否为团队长
+                                    if (!isTeamLeader(level2.get("id").toString())) {
+                                        // 计算三级分销
+                                        BigDecimal level3Diff = calcDistLevel3(insFeeOrders, totalPremium, level2.get("id").toString(), sysDistributionSetting);
+                                        diffAmount = diffAmount.add(level3Diff);
+                                    }
+                                    // 如果二级是团队长,三级分销费用已经在calculateLevel2Distribution中设置为0
+                                }
+                            }
+                            // 如果一级是团队长,二级和三级分销费用已经在calculateLevel1Distribution中设置为0
+                        }
+                        break;
                 }
-                break;
+                return diffAmount;
+            }
+        }
+        return BigDecimal.ZERO;
+    }
+
+    /**
+     * 判断用户是否为团队长
+     */
+    /**
+     * 判断用户是否为团队长
+     */
+    private boolean isTeamLeader(String userId) {
+        try {
+            HttpResult<List<SysOrganization>> organizations = orgClient.queryOrganizationByManagerId(userId);
+            return organizations.getData() != null && !organizations.getData().isEmpty();
+        } catch (Exception e) {
+            // 异常处理,默认不是团队长
+            return false;
         }
-        return diffAmount;
     }
 
     /**

+ 8 - 2
tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeOrdersMapper.xml

@@ -198,6 +198,12 @@
         group by
         ym
     </select>
-
-
+    <!-- 查询订单的汇总信息 lipf 2026年9月1日10:34:17  -->
+    <select id="getInsFeeOrderSummaryByUserId" resultType="com.jzg.commons.entity.po.InsFeeOrdersSummary">
+        select
+            sum(ifo.total_premium) as totalPremium,
+            count(*) as orderCount
+        from ins_fee_orders ifo
+        where ifo.user_id = #{insFeeOrdersParam.userId} and ifo.is_delete = 0
+    </select>
 </mapper>

+ 8 - 29
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/build/ZhongAnCrawlerQuoteResultsVoBuild.java

@@ -119,37 +119,16 @@ public class ZhongAnCrawlerQuoteResultsVoBuild {
         QuoteResultsVo.ScoreVo scoreVo = new QuoteResultsVo.ScoreVo();
         scoreVo.setJqAdjustRate(dataDTO.getCompelDiscount());
         scoreVo.setSyAdjustRate(dataDTO.getBusinessDiscount());
-        String forceRenewalFlag = dataDTO.getForceRenewalFlag();
-        String bizRenewalFlag = dataDTO.getBizRenewalFlag();
-        if (forceRenewalFlag == null) {
+        Integer renewalFlag = dataDTO.getInsureFlag();
+        if (renewalFlag != null && renewalFlag == 2) {
+            scoreVo.setJqRenewal(String.valueOf(RenewalEnum.Renewal.getCode()));
+            scoreVo.setSyRenewal(String.valueOf(RenewalEnum.Renewal.getCode()));
+        } else if (renewalFlag != null && renewalFlag == 3) {
             scoreVo.setJqRenewal(String.valueOf(RenewalEnum.Transfer.getCode()));
-        } else {
-            switch (forceRenewalFlag) {
-                case "PA":
-                    scoreVo.setJqRenewal(String.valueOf(RenewalEnum.Transfer.getCode()));
-                    break;
-                case "ZA":
-                    scoreVo.setJqRenewal(String.valueOf(RenewalEnum.Renewal.getCode()));
-                    break;
-                default:
-                    scoreVo.setJqRenewal(String.valueOf(RenewalEnum.New.getCode()));
-                    break;
-            }
-        }
-        if (bizRenewalFlag == null) {
             scoreVo.setSyRenewal(String.valueOf(RenewalEnum.Transfer.getCode()));
-        } else {
-            switch (bizRenewalFlag) {
-                case "PA":
-                    scoreVo.setSyRenewal(String.valueOf(RenewalEnum.Transfer.getCode()));
-                    break;
-                case "ZA":
-                    scoreVo.setSyRenewal(String.valueOf(RenewalEnum.Renewal.getCode()));
-                    break;
-                default:
-                    scoreVo.setSyRenewal(String.valueOf(RenewalEnum.New.getCode()));
-                    break;
-            }
+        } else if (renewalFlag != null && renewalFlag == 1) {
+            scoreVo.setJqRenewal(String.valueOf(RenewalEnum.New.getCode()));
+            scoreVo.setSyRenewal(String.valueOf(RenewalEnum.New.getCode()));
         }
         JSONArray scoreJson = new JSONArray();
         scoreJson.add(new JSONObject()

+ 3 - 3
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/request/ZhongAnCrawlerQuoteRequest.java

@@ -132,13 +132,13 @@ public class ZhongAnCrawlerQuoteRequest{
                 nonAutoInfoDtos.add(nonAutoInfoDto);
             });
             boolean hasKpNhjcb = nonAutoInfoDtos.stream()
-                    .anyMatch(dto -> "kp_nhjcb_v1".equals(dto.getProductCode()));
+                    .anyMatch(dto -> "kp_nhjcb_v2".equals(dto.getProductCode()));
             if (!hasKpNhjcb) {
-                NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_nhjcb_v1", "0", null);
+                NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_nhjcb_v2", "0", null);
                 nonAutoInfoDtos.add(jtywxV24);
             }
         } else {
-            NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_nhjcb_v1", "0", null);
+            NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_nhjcb_v2", "0", null);
             NonAutoInfoDto wjsGabV6 = new NonAutoInfoDto("wjs_gab_v10", "0", null);
             NonAutoInfoDto wjs_cwyjtywx_v1 = new NonAutoInfoDto("wjs_cwyjtywx_v1", "0", null);
             NonAutoInfoDto kp_czwyjcx_v1 = new NonAutoInfoDto("kp_czwyjcx_v1", "0", null);

+ 108 - 0
tenant/organization/src/main/java/com/jzg/organization/aop/OrderOperationLogAspect.java

@@ -1,18 +1,24 @@
 package com.jzg.organization.aop;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONConfig;
 import cn.hutool.json.JSONUtil;
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.finance.vo.BatchModifyVo;
+import com.jzg.commons.entity.finance.vo.importbatchmodify.InsPlyIncomeExportVo;
 import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.orders.po.InsOrdersCarInfo;
+import com.jzg.commons.entity.orders.po.InsOrdersPolicy;
 import com.jzg.commons.entity.orders.po.InsOrdersTrack;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
 import com.jzg.commons.entity.vo.QuestionOrder;
 import com.jzg.commons.util.JsonDiffUtil;
 import com.jzg.commons.util.SchemaDescriptionParser;
 import com.jzg.organization.client.summary.InsOrdersClient;
+import com.jzg.organization.mapper.InsOrdersPolicyMapper;
 import com.jzg.quotation.summary.aop.aspect.OrderOperationLog;
 import org.aspectj.lang.ProceedingJoinPoint;
 import org.aspectj.lang.annotation.Around;
@@ -27,8 +33,11 @@ import org.springframework.expression.ExpressionParser;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.expression.spel.support.StandardEvaluationContext;
 import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.InputStream;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Aspect
 @Component
@@ -40,6 +49,10 @@ public class OrderOperationLogAspect {
     @Lazy
     private InsOrdersClient insOrdersClient;
 
+    @Autowired
+    @Lazy
+    private InsOrdersPolicyMapper insOrdersPolicyMapper;
+
 
 
     /**
@@ -101,10 +114,105 @@ public class OrderOperationLogAspect {
                 result = joinPoint.proceed();
                 this.updateToQuestionOrder(result,log, questionOrder);
                 break;
+            // 导入批量修改比例
+            case 18:
+                logger.info("导入批量修改比例.log.orderSpEl()=[{}]",log.orderSpEl());
+                // 1. 通过 SpEL 取出 MultipartFile 文件对象
+                MultipartFile file = parser.parseExpression(log.orderSpEl()).getValue(context, MultipartFile.class);
+                if (file == null || file.isEmpty()) {
+                    throw new RuntimeException("导入文件为空,无法记录操作轨迹");
+                }
+                // 2. 解析 Excel,提取保单号列表,换算为 orderNo(与 Service fillExcelConte 逻辑一致)
+                List<String> importOrderNos = resolveOrderNosFromFile(file);
+                if (CollUtil.isEmpty(importOrderNos)) {
+                    logger.warn("导入批量修改比例:解析后未获取到任何有效 orderNo,跳过轨迹记录");
+                    result = joinPoint.proceed();
+                    break;
+                }
+                // 3. 批量修改前快照
+                Map<String, QuoteEchoVo> importOldOrders = new HashMap<>();
+                for (String orderNo : importOrderNos) {
+                    HttpResult<QuoteEchoVo> echoRes = insOrdersClient.auditInfo(orderNo);
+                    importOldOrders.put(orderNo, echoRes.getData());
+                }
+                // 4. 执行实际导入修改业务
+                result = joinPoint.proceed();
+                // 5. 批量修改后快照
+                Map<String, QuoteEchoVo> importNewOrders = new HashMap<>();
+                for (String orderNo : importOrderNos) {
+                    HttpResult<QuoteEchoVo> echoRes = insOrdersClient.auditInfo(orderNo);
+                    importNewOrders.put(orderNo, echoRes.getData());
+                }
+                // 6. 构造 BatchModifyVo 以便复用 batchModify 轨迹落库方法
+                BatchModifyVo importVo = new BatchModifyVo();
+                importVo.setOrderNos(importOrderNos);
+                this.batchModify(result, log, importVo, importOldOrders, importNewOrders);
+                break;
         }
         return result;
     }
 
+    /**
+     * 从导入的 Excel 文件中解析出所有行的保单号,再通过 InsOrdersPolicy 表转换为 orderNo 列表
+     * 逻辑与 ReceivableServiceImpl.fillExcelConte 保持一致,按交强 → 商业 → 驾意 的优先级匹配保单号
+     *
+     * @return 去重后的 orderNo 列表
+     * @author lipf / trae
+     * @date 2026/8/31
+     */
+    private List<String> resolveOrderNosFromFile(MultipartFile file) {
+        Set<String> orderNoSet = new LinkedHashSet<>();
+        try (InputStream is = file.getInputStream()) {
+            // 使用 EasyExcel 同步读取,头类为 InsPlyIncomeExportVo(与 Service 解析一致)
+            List<InsPlyIncomeExportVo> rows = EasyExcel.read(is)
+                    .head(InsPlyIncomeExportVo.class)
+                    .sheet()
+                    .doReadSync();
+            if (CollUtil.isEmpty(rows)) {
+                logger.warn("resolveOrderNosFromFile:Excel 为空或无有效数据行");
+                return Collections.emptyList();
+            }
+            for (InsPlyIncomeExportVo row : rows) {
+                String orderNo = resolveOneOrderNo(row);
+                if (StrUtil.isNotBlank(orderNo)) {
+                    orderNoSet.add(orderNo);
+                }
+            }
+            logger.info("resolveOrderNosFromFile:解析 Excel 行数={}, 去重后 orderNo 数={}", rows.size(), orderNoSet.size());
+        } catch (Exception e) {
+            logger.error("resolveOrderNosFromFile 解析导入文件异常:{}", e.getMessage(), e);
+        }
+        return new ArrayList<>(orderNoSet);
+    }
+
+    /**
+     * 单行数据:按 交强 → 商业 → 驾意 优先级查询订单号
+     */
+    private String resolveOneOrderNo(InsPlyIncomeExportVo row) {
+        if (StrUtil.isNotBlank(row.getJqPolicyNo())) {
+            List<InsOrdersPolicy> list = insOrdersPolicyMapper.selectList(
+                    new LambdaQueryWrapper<InsOrdersPolicy>().eq(InsOrdersPolicy::getJqPolicyNo, row.getJqPolicyNo()));
+            if (CollUtil.isNotEmpty(list)) {
+                return list.get(0).getOrderNo();
+            }
+        }
+        if (StrUtil.isNotBlank(row.getSyPolicyNo())) {
+            List<InsOrdersPolicy> list = insOrdersPolicyMapper.selectList(
+                    new LambdaQueryWrapper<InsOrdersPolicy>().eq(InsOrdersPolicy::getSyPolicyNo, row.getSyPolicyNo()));
+            if (CollUtil.isNotEmpty(list)) {
+                return list.get(0).getOrderNo();
+            }
+        }
+        if (StrUtil.isNotBlank(row.getJyPolicyNo())) {
+            List<InsOrdersPolicy> list = insOrdersPolicyMapper.selectList(
+                    new LambdaQueryWrapper<InsOrdersPolicy>().eq(InsOrdersPolicy::getJyPolicyNo, row.getJyPolicyNo()));
+            if (CollUtil.isNotEmpty(list)) {
+                return list.get(0).getOrderNo();
+            }
+        }
+        return null;
+    }
+
     /**
      * 设置为疑问订单
      *

+ 10 - 0
tenant/organization/src/main/java/com/jzg/organization/client/summary/QuoteClient.java

@@ -3,6 +3,7 @@ package com.jzg.organization.client.summary;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.dto.InsFeeOrdersParam;
 import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.po.InsFeeOrdersSummary;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -23,6 +24,15 @@ public interface QuoteClient {
     @PostMapping(value = "/insFeeOrder/getInsFeeOrderByUserId")
     List<InsFeeOrders> getInsFeeOrderByUserId(@RequestBody InsFeeOrdersParam param);
 
+    /**
+     * 针对getInsFeeOrderByUserId 方法的优化,当订单很多的时候,提升性能
+     *
+     * @author lipf
+     * @date 2026/9/1 10:25
+     */
+    @PostMapping(value = "/insFeeOrder/getInsFeeOrderSummaryByUserId")
+    InsFeeOrdersSummary getInsFeeOrderSummaryByUserId(@RequestBody InsFeeOrdersParam param);
+
     @GetMapping(value = "/insFeeOrder/getInsFeeOrderListByTopReferrerIdAndUserId")
     List<InsFeeOrders> getInsFeeOrderListByTopReferrerIdAndUserId(@RequestParam("userId") String userId, @RequestParam("topReferrerId") String topReferrerId);
 

+ 23 - 30
tenant/organization/src/main/java/com/jzg/organization/component/BuildDescUtils.java

@@ -40,22 +40,15 @@ public class BuildDescUtils {
             } else if ("radio".equals(attrType)) {
                 desc.append(radioIdentifying(ptlAgreementUndwrtRulesAttr, link)).append(";\t\t");
             } else if ("checkbox".equals(attrType) || "select".equals(attrType)) {
-                if(link.getMinArray() != null && link.getMinArray().length > 0){
-                    desc.append(ptlAgreementUndwrtRulesAttr.getAttrName()).append("包含");
-                    for (int k=0 ; k<link.getMinArray().length; k++){
-                        PtlAgreementUndwrtRulesDictLabal ptlAgreementUndwrtRulesDictLabal = null;
-                        for (PtlAgreementUndwrtRulesDictLabal x : link.getDictLabal()) {
-                            if (Arrays.asList(link.getMinArray()).contains(x.getCode())) {
-                                ptlAgreementUndwrtRulesDictLabal = x;
-                                link.getMinArray()[k] = null;
-                                break;
-                            }
-                        }
-                        desc.append(null != ptlAgreementUndwrtRulesDictLabal ? ptlAgreementUndwrtRulesDictLabal.getName() : "").append(",");
-                    }
-                    // 条件描述后补充一个分号
-                    desc.append(",");
-                }else {
+                if (link.getMinArray() != null && link.getMinArray().length > 0) {
+                    // minArray 转 Set,避免循环内反复创建 List 做 contains 查找
+                    Set<String> minCodes = Arrays.stream(link.getMinArray()).collect(Collectors.toSet());
+                    String names = Optional.ofNullable(link.getDictLabal()).orElse(Collections.emptyList()).stream()
+                            .filter(labal -> minCodes.contains(labal.getCode()))
+                            .map(PtlAgreementUndwrtRulesDictLabal::getName)
+                            .collect(Collectors.joining(","));
+                    desc.append(ptlAgreementUndwrtRulesAttr.getAttrName()).append("包含").append(names).append(";\t\t");
+                } else {
                     desc.append(ptlAgreementUndwrtRulesAttr.getAttrName()).append("包含").append(link.getMin()).append(";\t\t");
                 }
             } else if ("inputTag".equals(attrType)) {
@@ -148,29 +141,29 @@ public class BuildDescUtils {
         return ptlAgreementUndwrtRulesAttr.getAttrName() + "为" + ptlAgreementUndwrtRulesDictLabal.getName();
     }
 
-    public static String selectIdentifying(PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr, PtlAgreementUndwrtRulesAttrLink ptlAgreementProductCostsAttrLink) {
+    public static String selectIdentifying(PtlAgreementUndwrtRulesAttr undwrtRulesAttr, PtlAgreementUndwrtRulesAttrLink link) {
         StringBuilder returnMsg = new StringBuilder();
-        returnMsg.append(ptlAgreementUndwrtRulesAttr.getAttrName()).append("为");
         // 兼容 min 逗号分隔存储,保证 minArray 有值
-        if (ptlAgreementProductCostsAttrLink.getMinArray() == null) {
-            String minStr = ptlAgreementProductCostsAttrLink.getMin();
+        if (link.getMinArray() == null) {
+            String minStr = link.getMin();
             if (minStr != null && !minStr.isEmpty()) {
-                ptlAgreementProductCostsAttrLink.setMinArray(minStr.split(","));
+                link.setMinArray(minStr.split(","));
             }
         }
 
         // 优先取 link 上的字典标签列表(JSONArray -> List),为空时回退到属性自带字典
-        List<PtlAgreementUndwrtRulesDictLabal> dictLabalList = getDictLabalList(ptlAgreementUndwrtRulesAttr, ptlAgreementProductCostsAttrLink);
+        List<PtlAgreementUndwrtRulesDictLabal> dictLabalList = getDictLabalList(undwrtRulesAttr, link);
 
         // 用字典标签的 code 匹配 minArray 中的每一项
-        if (ptlAgreementProductCostsAttrLink.getMinArray() != null) {
-            for (String item : ptlAgreementProductCostsAttrLink.getMinArray()) {
-                PtlAgreementUndwrtRulesDictLabal ptlAgreementUndwrtRulesDictLabal = dictLabalList.stream()
-                        .filter(x -> x.getCode() != null && x.getCode().equals(item)).findAny().orElse(null);
-                if (ptlAgreementUndwrtRulesDictLabal != null) {
-                    returnMsg.append(ptlAgreementUndwrtRulesDictLabal.getName()).append(",");
-                }
-            }
+        if (link.getMinArray() != null && link.getMinArray().length > 0) {
+            // minArray 转 Set,避免循环内反复创建 List 做 contains 查找
+            Set<String> minCodes = Arrays.stream(link.getMinArray()).collect(Collectors.toSet());
+            String names = Optional.ofNullable(dictLabalList).orElse(Collections.emptyList()).stream()
+                    .filter(labal -> minCodes.contains(labal.getCode()))
+                    .map(PtlAgreementUndwrtRulesDictLabal::getName)
+                    .collect(Collectors.joining(","));
+            returnMsg.append(undwrtRulesAttr.getAttrName()).append("包含").append(names).append(",");
+
         }
         return returnMsg.toString();
     }

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

@@ -1,34 +1,16 @@
 package com.jzg.organization.controller;
 
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.jzg.commons.constants.OperationTypeEnum;
 import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.page.HttpResult;
-import com.jzg.commons.entity.dto.*;
-import com.jzg.commons.entity.enums.YesNoEnum;
-import com.jzg.commons.entity.po.OperatorTrajectory;
-import com.jzg.commons.entity.po.PtlAgreement;
 import com.jzg.commons.entity.po.PtlNewCarJudgeRules;
-import com.jzg.commons.entity.vo.AgreementVo;
 import com.jzg.commons.entity.vo.NewCarQuery;
-import com.jzg.commons.entity.vo.UpAndDownVo;
-import com.jzg.commons.service.OperatorTrajectoryService;
-import com.jzg.commons.util.AssertionUtils;
-import com.jzg.commons.util.spring.SpringUtils;
-import com.jzg.organization.mapper.PtlAgreementMapper;
 import com.jzg.organization.service.NewCarJudgeRulesService;
-import com.jzg.organization.service.PtlAgreementDeptService;
-import com.jzg.organization.service.PtlAgreementService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Objects;
 
 /**
  * 协议管理接口
@@ -60,12 +42,14 @@ public class NewCarJudgeRulesController extends BaseController {
     @PostMapping("addNewCar")
     public HttpResult addNewCar(@RequestBody PtlNewCarJudgeRules newCarJudgeRules){
         newCarJudgeRules.setSystemCode(getUserSystemCode());
+        newCarJudgeRules.setSaveDate(LocalDateTime.now());
         return newCarJudgeRulesService.addNewCar(newCarJudgeRules) ? HttpResult.ok("添加新旧车规则成功") : HttpResult.error("添加新旧车规则失败");
     }
 
     @Operation(summary = "修改新旧车规则")
     @PostMapping("updateNewCar")
     public HttpResult updateNewCar(@RequestBody PtlNewCarJudgeRules newCarJudgeRules){
+        newCarJudgeRules.setSaveDate(LocalDateTime.now());
         return newCarJudgeRulesService.updateNewCar(newCarJudgeRules) ? HttpResult.ok("修改新旧车规则成功") : HttpResult.error("修改新旧车规则失败");
     }
 

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

@@ -143,6 +143,13 @@ public class ReceivableController {
         return HttpResult.ok(receivablePageIds);
     }
 
+    @OrderOperationLog(
+            module = "私有/平台协议应收",
+            subModule = "订单审核",
+            optType = QuoteNumberConstant.QuoteOptType.OPT_TYPE_18,
+            description = "导入批量修改比例",
+            orderSpEl = "#file"
+    )
     @PostMapping("/importReceivableListUpdate")
     @Operation(summary = "导入私有协议/平台协议比例修改")
     public HttpResult<ImportUpdateExcelResultVo> importReceivableListUpdate(@RequestParam("file") MultipartFile file){

+ 8 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/SysOrganizationController.java

@@ -21,6 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.List;
+
 @RestController
 @RequestMapping("/sysOrganization")
 public class SysOrganizationController {
@@ -163,4 +165,10 @@ public class SysOrganizationController {
         Page page = sysOrganizationUserLinkQueryVo.getPage();
         return HttpResult.ok(sysOrganizationService.getTeamUserPage(page,sysOrganizationUserLinkQueryVo));
     }
+
+    @Operation(summary = "根据用户id查询团队")
+    @GetMapping("queryOrganizationByManagerId")
+    public HttpResult<List<SysOrganization>> queryOrganizationByManagerId(@RequestParam("userId") String userId){
+        return HttpResult.ok(sysOrganizationService.queryOrganizationByManagerId(userId));
+    }
 }

+ 8 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/UserController.java

@@ -58,6 +58,14 @@ public class UserController extends BaseController {
         return HttpResult.ok(userInfoList);
     }
 
+    @Operation(summary = "报价页面的获取业务员列表", description = "报价页面的获取业务员列表")
+    @PostMapping(value = "/getBaojiaUserInfoList")
+    public HttpResult<Page<SysUserJzgInfoDto>> getBaojiaUserInfoList(@RequestBody SysUserInfoListVo sysUserInfoListVo) {
+        Page page = sysUserInfoListVo.getPage();
+        Page<SysUserJzgInfoDto> userInfoList = sysUserService.getBaojiaUserInfoList(page, sysUserInfoListVo);
+        return HttpResult.ok(userInfoList);
+    }
+
     /**
      * 查询所有成员和业务员的身份
      *

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

@@ -37,6 +37,15 @@ public interface SysUserJzgInfoMapper extends BaseMapper<SysUserJzgInfo> {
     Page<SysUserJzgInfoDto> queryYwy(Page page, @Param("sysUserInfoListVo") SysUserInfoListVo sysUserInfoListVo,
                                      @Param("systemCode") String systemCode,@Param("leaderId") String leaderId);
 
+    /**
+     * 查询报价业务员
+     *
+     * @author lipf
+     * @date 2026/4/24 11:08
+     */
+    Page<SysUserJzgInfoDto> queryBJYwy(Page page, @Param("sysUserInfoListVo") SysUserInfoListVo sysUserInfoListVo,
+                                     @Param("systemCode") String systemCode,@Param("leaderId") String leaderId);
+
     /**
      * 查询成员
      *

+ 4 - 0
tenant/organization/src/main/java/com/jzg/organization/service/SysOrganizationService.java

@@ -9,6 +9,7 @@ import com.jzg.commons.entity.po.SysOrganizationVO;
 import com.jzg.commons.entity.vo.SysOrganizationUserLinkQueryVo;
 import com.jzg.commons.entity.vo.SysOrganizationUserLinkVo;
 
+import java.util.List;
 import java.util.Map;
 
 public interface SysOrganizationService extends IService<SysOrganization> {
@@ -60,4 +61,7 @@ public interface SysOrganizationService extends IService<SysOrganization> {
      * @date 2026年4月10日10:09:12
      */
     Page<SysOrganizationUserLinkVo> getTeamUserPage(Page page,SysOrganizationUserLinkQueryVo sysOrganizationUserLinkQueryVo);
+
+    List<SysOrganization> queryOrganizationByManagerId(String userId);
+
 }

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

@@ -96,6 +96,7 @@ public interface SysUserService extends IService<SysUser> {
      * @date 2026/4/10 10:01
      */
     Page<SysUserJzgInfoDto> getUserInfoList(Page page, SysUserInfoListVo sysUserInfoListVo);
+    Page<SysUserJzgInfoDto> getBaojiaUserInfoList(Page page, SysUserInfoListVo sysUserInfoListVo);
 
     /**
      * 获取成员转移资源信息

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

@@ -995,7 +995,7 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
     @Autowired
     PtlSchemeService ptlSchemeService;
 
-    @GlobalTransactional
+    @Transactional
     @Override
     public Boolean copyScheme(String schemeInfoId, String productCode) {
 

+ 9 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysOrganizationServiceImpl.java

@@ -204,4 +204,13 @@ public class SysOrganizationServiceImpl extends ServiceImpl<SysOrganizationMappe
         log.debug("获取团队下的人员列表分页.查询出[{}]个业务员。 sysOrganizationUserLinkQueryVo=[{}], page=[{}]", CollUtil.size(teamUserPage.getRecords()), JSONUtil.toJsonStr(sysOrganizationUserLinkQueryVo), JSONUtil.toJsonStr(page));
         return teamUserPage;
     }
+
+    @Override
+    public List<SysOrganization> queryOrganizationByManagerId(String managerId) {
+        LambdaQueryWrapper<SysOrganization> lambdaQueryWrapper = new LambdaQueryWrapper<SysOrganization>()
+                .eq(SysOrganization::getManagerId, managerId)
+                .eq(SysOrganization::getIsDelete, 0);
+        return sysOrganizationMapper.selectList(lambdaQueryWrapper);
+    }
+
 }

+ 12 - 7
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserAccountServiceImpl.java

@@ -172,13 +172,18 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
         sysUserWalletVo.setIntegral(sysUserAccount.getIntegral());
         InsFeeOrdersParam param = new InsFeeOrdersParam();
         param.setUserId(sysUserJzgInfo.getUserId());
-        List<InsFeeOrders> insFeeOrdersList = quoteClient.getInsFeeOrderByUserId(param);
+        //List<InsFeeOrders> insFeeOrdersList = quoteClient.getInsFeeOrderByUserId(param);
+        InsFeeOrdersSummary feeSummary = quoteClient.getInsFeeOrderSummaryByUserId(param);
         BigDecimal premium = BigDecimal.ZERO;
         BigDecimal orderAmount = BigDecimal.ZERO;
-        for (InsFeeOrders insFeeOrders : insFeeOrdersList) {
-            premium = premium.add(insFeeOrders.getTotalPremium());
-            orderAmount = orderAmount.add(insFeeOrders.getTotalReceivablePremium());
+        if(feeSummary != null){
+            premium = BigDecimalUtil.add(BigDecimal.ZERO,feeSummary.getTotalPremium()) ;
+//            orderAmount = feeSummary.getOrderCount();
         }
+//        for (InsFeeOrders insFeeOrders : insFeeOrdersList) {
+//            premium = premium.add(insFeeOrders.getTotalPremium());
+//            orderAmount = orderAmount.add(insFeeOrders.getTotalReceivablePremium());
+//        }
         InsFeeOrdersParam distributionParam = new InsFeeOrdersParam();
         distributionParam.setDistributorId(sysUserJzgInfo.getId());
 //        List<InsFeeOrders> distribuitonList = quoteClient.getInsFeeOrdersList(distributionParam);
@@ -198,7 +203,7 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
         sysUserWalletVo.setTotalIncome(sysUserAccount.getSumAmount());
         //sysUserWalletVo.setTotalIncome(orderAmount.add(distributionPremium));
         sysUserWalletVo.setSignPremium(premium);
-        sysUserWalletVo.setOrderCount(String.valueOf(insFeeOrdersList.size()));
+        sysUserWalletVo.setOrderCount(String.valueOf(feeSummary.getOrderCount()));
         List<SysUserJzgInfo> sysUserJzgInfoList = sysUserJzgInfoService.list(new LambdaQueryWrapper<SysUserJzgInfo>().eq(SysUserJzgInfo::getReferrerId, sysUserJzgInfo.getId()));
         sysUserWalletVo.setTotalInviteCount(String.valueOf(sysUserJzgInfoList.size()));
         // 获取累计收入
@@ -454,8 +459,8 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
                     if("0".equals(action.getIncomeAndExpense())){
                         // 保费收入
                         stepList.add(new ChangeLogDetail("费用审核通过",action.getCreateTime(),true, null));
-                        stepList.add(new ChangeLogDetail());
-                        stepList.add(new ChangeLogDetail());
+//                        stepList.add(new ChangeLogDetail());
+//                        stepList.add(new ChangeLogDetail());
                     }
                 }else if("2".equals(action.getStatus())){
                     stepList.add(new ChangeLogDetail("提交提现申请",action.getCreateTime(),true, null));

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

@@ -122,7 +122,12 @@ public class SysUserJzgInfoBankCardServiceImpl extends ServiceImpl<SysUserJzgInf
             for (int i = 0; i < size; i++) {
                 SysUserJzgInfoBankCardRecord action = sysUserJzgInfoBankCardRecordList.get(i);
                 // 只有最后一条记录按实际状态设置,前面的记录默认展示为成功
-                boolean show = i < size - 1 || action.getStatus().equals("1");
+                Boolean show = i < size - 1 ||  action.getStatus().equals("1");
+                if("添加新卡".equals(action.getDescription()) && "0".equals(sysUserJzgInfoBankCardDto.getAuditStatus())){
+                    // 待审核的时候,显示为空。 不展示对/错
+                    show = null;
+                }
+
                 changeLogDetailList.add(new ChangeLogDetail(action.getDescription(), action.getCreateTime(), show, action.getRemark(), action.getBankCardId(), action.getId()));
             }
             sysUserJzgInfoBankCardDto.setSysUserJzgInfoBankCardRecordList(changeLogDetailList);

+ 111 - 18
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java

@@ -265,6 +265,78 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         log.info("获取业务员/成员列表:查询出[{}]个业务员。 查询参数: sysUserInfoListVo=[{}]", CollUtil.size(userInfoList.getRecords()),JSONUtil.toJsonStr(sysUserInfoListVo));
         return userInfoList;
     }
+    @Override
+    public Page<SysUserJzgInfoDto> getBaojiaUserInfoList(Page page, SysUserInfoListVo sysUserInfoListVo) {
+        log.info("获取业务员列表:查询参数: sysUserInfoListVo=[{}]", JSONUtil.toJsonStr(sysUserInfoListVo));
+        if(Objects.nonNull(sysUserInfoListVo.getStatus()) && sysUserInfoListVo.getStatus() == 0){
+            List<Integer> typeStatus = new ArrayList<>();
+            sysUserInfoListVo.setStatus(null);
+            typeStatus.add(UserState.UserStateEnum.COMPANY_REVIEW_ING.getValue());
+            typeStatus.add(UserState.UserStateEnum.RESIGN_ING.getValue());
+            typeStatus.add(UserState.UserStateEnum.NOT_CERT.getValue());
+            sysUserInfoListVo.setTypeStatus(typeStatus);
+        }
+        // 前端 查询成员和查询业务员的接口,都使用的是这个接口,但是他们区分的时候,差异很大,因此这里将查询成员和查询业务员的接口拆分开来
+        Page<SysUserJzgInfoDto> userInfoList;
+        String systemCode = baseController.getUserSystemCode();
+
+        String loginUserId = baseController.getUserId();
+        // 查询业务员
+        if("2".equals(sysUserInfoListVo.getIsMember())){
+            String jzgInfoId = null;
+            if("10".equals(sysUserInfoListVo.getFromPage())){
+                long startTime = System.currentTimeMillis();
+                SysUserJzgInfo userInfoJzgInfo = sysUserJzgInfoService.getUserByUserId(loginUserId);
+                log.info("查询耗时:[{}]", System.currentTimeMillis() - startTime);
+                jzgInfoId = userInfoJzgInfo.getId();
+            }
+            log.info("查看成员下的业务员信息:成员的序号:jzgInfoId=[{}]", jzgInfoId);
+            // modify by lipf 查询成员下业务员的时候,不进行分页
+//            page.setSize(Long.MAX_VALUE);
+            userInfoList = sysUserJzgInfoMapper.queryBJYwy(page, sysUserInfoListVo, systemCode, jzgInfoId
+            );
+        }else if("1".equals(sysUserInfoListVo.getIsMember())){
+            // 查询成员
+            log.info("查询成员信息:sysUserInfoListVo=[{}]",JSONUtil.toJsonStr(sysUserInfoListVo)  );
+            userInfoList = sysUserJzgInfoMapper.queryMember(page, sysUserInfoListVo);
+        }else{
+            // 其他场景先使用原来的逻辑
+            userInfoList = sysUserJzgInfoMapper.getUserInfoList(page, sysUserInfoListVo);
+        }
+        List<SysUserJzgInfoDto> records = userInfoList.getRecords();
+        if(CollectionUtil.isNotEmpty(records)){
+            // 填充岗位信息
+            Map<String, String> attrTypeMap = sysUserJzgInfoSalesmanService.queryAllTypeAttrMap();
+            Map<String, SysOrganizationVO> stringSysOrganizationVOMap = sysOrganizationService.queryUserBindOrganization(baseController.getSystemCode());
+            records = records.stream().peek(action->{
+                if(loginUserId.equals(action.getUserId())){
+                    action.setDefaultSelected(true);
+                }
+                String typeAttr = attrTypeMap.getOrDefault(action.getId(),null);
+                // 在【业务员管理页面】 要求类型中,不展示1,2,3,4 对应的类型
+                if(StrUtil.isNotEmpty(typeAttr)){
+                    Set<String> set = Set.of("1","2","3");
+                    typeAttr = Arrays.stream(typeAttr.split(",")).filter(action1-> !set.contains(action1)).collect(Collectors.joining(","));
+                    action.setTypeAttr(typeAttr);
+                }
+                List<SysRole> userRole = sysUserRoleService.getUserRole(action.getUserId());
+                if(CollectionUtil.isNotEmpty(userRole)){
+                    String roleNames = userRole.stream().map(SysRole::getName).distinct().collect(Collectors.joining(","));
+                    action.setRoleName(roleNames);
+                }
+                SysOrganizationVO sysOrganizationVO = stringSysOrganizationVOMap.get(action.getUserId());
+                if(sysOrganizationVO != null){
+                    action.setOrganizationId(sysOrganizationVO.getOrganizationId());
+                    action.setOrganizationName(sysOrganizationVO.getName());
+                }
+
+            }).toList();
+            userInfoList.setRecords(records);
+        }
+        //Page<SysUserJzgInfoDto> userInfoList = sysUserJzgInfoMapper.getUserInfoList(page, sysUserInfoListVo);
+        log.info("获取业务员/成员列表:查询出[{}]个业务员。 查询参数: sysUserInfoListVo=[{}]", CollUtil.size(userInfoList.getRecords()),JSONUtil.toJsonStr(sysUserInfoListVo));
+        return userInfoList;
+    }
 
     @Override
     public UserTransferInfoVo getTransferInfo(String userId) {
@@ -866,20 +938,21 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     }
 
     @Override
-    public HttpResult addBankCard(SysUserJzgInfoBankCardVo sysUserJzgInfoBankCardVo) {
-        SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getById(sysUserJzgInfoBankCardVo.getUserJzgInfoId());
+    public HttpResult addBankCard(SysUserJzgInfoBankCardVo param) {
+        log.info("添加银行卡信息:param=[{}]", JSONUtil.toJsonStr(param));
+        SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getById(param.getUserJzgInfoId());
         if (sysUserJzgInfo == null) {
             throw new SystemException("该业务员不存在");
         }
-        if (sysUserJzgInfoBankCardVo.getBankCardNumber() == null) {
-            HttpResult.error("银行卡号不能为空");
+        if (param.getBankCardNumber() == null) {
+            return HttpResult.error("银行卡号不能为空");
         }
-        String fileId = IdGenerate.nextId();
-        if (sysUserJzgInfoBankCardVo.getAttachment() != null) {
+        String id = IdGenerate.nextId();
+        if (param.getAttachment() != null) {
             SysUploadFiles sysUploadFiles = sysUploadFilesMapper.selectOne
-                    (new LambdaQueryWrapper<SysUploadFiles>().eq(SysUploadFiles::getId, sysUserJzgInfoBankCardVo.getAttachment()));
-            SysUserJzgInfoFile sysUserJzgInfoFile = new SysUserJzgInfoFile(sysUserJzgInfoBankCardVo.getAttachment(), sysUserJzgInfoBankCardVo.getUserJzgInfoId(), sysUploadFiles.getFileName());
-            sysUserJzgInfoFile.setId(fileId);
+                    (new LambdaQueryWrapper<SysUploadFiles>().eq(SysUploadFiles::getId, param.getAttachment()));
+            SysUserJzgInfoFile sysUserJzgInfoFile = new SysUserJzgInfoFile(param.getAttachment(), param.getUserJzgInfoId(), sysUploadFiles.getFileName());
+            sysUserJzgInfoFile.setId(id);
             sysUserJzgInfoFile.setFileUrl(MinioUtils.getPresignedObjectUrl("jzg", sysUploadFiles.getFileName()));
             sysUserJzgInfoFile.setFileType("bankcard");
             sysUserJzgInfoFileService.save(sysUserJzgInfoFile);
@@ -893,24 +966,26 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         // 提交卡号为驳回状态 重新提交
         SysUserJzgInfoBankCard rejectBankCard = sysUserJzgInfoBankCardService
                 .getOne(new LambdaQueryWrapper<SysUserJzgInfoBankCard>()
-                        .eq(SysUserJzgInfoBankCard::getBankCardNumber, sysUserJzgInfoBankCardVo.getBankCardNumber())
+                        .eq(SysUserJzgInfoBankCard::getBankCardNumber, param.getBankCardNumber())
                         .eq(SysUserJzgInfoBankCard::getUserInfoId, sysUserJzgInfo.getId())
                         .eq(SysUserJzgInfoBankCard::getSystemCode, systemCode)
                         .eq(SysUserJzgInfoBankCard::getAuditStatus, 2));
         // 重新提交需要再多加一条数据,不能修改原来那条数据的状态,原来那条数据不能动
         if (rejectBankCard != null) {
             SysUserJzgInfoBankCard sysUserJzgInfoBankCard = BeanUtil.copyProperties(rejectBankCard, SysUserJzgInfoBankCard.class);
-
             sysUserJzgInfoBankCard.setId(IdGenerate.nextId());
-            sysUserJzgInfoBankCard.setFileId(fileId);
+            sysUserJzgInfoBankCard.setFileId(id);
             sysUserJzgInfoBankCard.setAuditStatus(0);
             sysUserJzgInfoBankCard.setSystemCode(systemCode);
+            // 解决重新提交的时候,新持卡人姓名没生效的问题 add by lipf 2026年9月1日10:13:25
+            sysUserJzgInfoBankCard.setCardHolderMobile(param.getCardHolderMobile());
+            sysUserJzgInfoBankCard.setCardHolderName(param.getCardHolderName());
             // 审核时间、审核人要设置为空
             sysUserJzgInfoBankCard.setRemark(null);
             sysUserJzgInfoBankCard.setAuditBy(null);
             sysUserJzgInfoBankCard.setAuditTime(null);
             // 设置为默认卡
-            if (sysUserJzgInfoBankCardVo.isDefault()) {
+            if (param.isDefault()) {
                 sysUserJzgInfoBankCardService.lambdaUpdate()
                         .eq(SysUserJzgInfoBankCard::getUserInfoId, sysUserJzgInfo.getId())
                         .setSql("is_default = 0")
@@ -923,23 +998,23 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
             // 添加重新提交记录
             SysUserJzgInfoBankCardRecord record = new SysUserJzgInfoBankCardRecord(rejectBankCard.getId(), "驳回后重新提交");
             record.setStatus("0");
-            record.setBankCardId(sysUserJzgInfoBankCardVo.getBankCardNumber());
+            record.setBankCardId(param.getBankCardNumber());
             sysUserJzgInfoBankCardRecordService.save(record);
 
             return HttpResult.ok("重新提交银行卡成功,等待审核");
         }
         SysUserJzgInfoBankCard verifyBankCard = sysUserJzgInfoBankCardService
-                .getOne(new LambdaQueryWrapper<SysUserJzgInfoBankCard>().eq(SysUserJzgInfoBankCard::getBankCardNumber, sysUserJzgInfoBankCardVo.getBankCardNumber())
+                .getOne(new LambdaQueryWrapper<SysUserJzgInfoBankCard>().eq(SysUserJzgInfoBankCard::getBankCardNumber, param.getBankCardNumber())
                         .eq(SysUserJzgInfoBankCard::getSystemCode, systemCode));
         if (verifyBankCard != null) {
             return HttpResult.error("该租户下银行卡已存在");
         }
         SysUserJzgInfoBankCard sysUserJzgInfoBankCard = new SysUserJzgInfoBankCard();
-        BeanUtils.copyProperties(sysUserJzgInfoBankCardVo, sysUserJzgInfoBankCard);
-        sysUserJzgInfoBankCard.setFileId(fileId);
+        BeanUtils.copyProperties(param, sysUserJzgInfoBankCard);
+        sysUserJzgInfoBankCard.setFileId(id);
         sysUserJzgInfoBankCard.setUserInfoId(sysUserJzgInfo.getId());
         sysUserJzgInfoBankCard.setSystemCode(systemCode);
-        if (sysUserJzgInfoBankCardVo.isDefault()) {
+        if (param.isDefault()) {
             sysUserJzgInfoBankCardService.lambdaUpdate()
                     .eq(SysUserJzgInfoBankCard::getUserInfoId, sysUserJzgInfo.getUserId())
                     .setSql("is_default = 0")
@@ -1533,6 +1608,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
            }
            // 关联用户角色
            saveRole(userByUserId);
+            // 合伙人添加业务员    app内也要新增一条数据
+           saveUserApp(userByUserId, userByUserId.getSystemCode());
            return HttpResult.ok("添加业务员成功");
        }catch (Exception e){
            log.error("添加业务员异常",e);
@@ -1540,6 +1617,16 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
        }
     }
 
+    private void saveUserApp(SysUserJzgInfo userByUserId, String systemCode) {
+        boolean exists = sysUserJzgAppMapper.exists(new LambdaQueryWrapper<>(SysUserJzgApp.class).eq(SysUserJzgApp::getUserId, userByUserId.getUserId()));
+        if (!exists){
+            SysUserJzgApp sysUserJzgApp = BeanUtil.copyProperties(userByUserId, SysUserJzgApp.class);
+            sysUserJzgApp.setId(IdGenerate.nextId());
+            sysUserJzgApp.setSystemCode(systemCode);
+            sysUserJzgAppMapper.insert(sysUserJzgApp);
+        }
+    }
+
     @Override
     public HttpResult<SysUserJzgInfo> getUserInfoUserId(String userId) {
         return HttpResult.ok(sysUserJzgInfoMapper.getUserJzgInfoByUserId(userId));
@@ -1569,6 +1656,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
 
     public void addPartner(SysUserVo sysUserVo){
         String referrerId = sysUserVo.getReferrerId();
+        if (StringUtils.isEmpty(referrerId)){
+            throw new SystemException("推荐人不能为空");
+        }
         SysUser sysUser = baseMapper.getUserByMobile(sysUserVo.getMobile());
         if (sysUserVo.isCodeInvitation()){
             SysUserJzgInfo userJzgInfo = sysUserJzgInfoMapper.selectByUserIdInfo(sysUserVo.getReferrerId());
@@ -1613,6 +1703,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
             }
             sysUserVo.setUserId(sysUserJzgInfo.getId());
         }
+        if (sysUserVo.getGrade() > 3){
+            saveUserApp(sysUserJzgInfo, baseController.getSystemCode());
+        }
         partnerAddsSalespersonIdentity(sysUserJzgInfo.getId(),"3");
         if ((!Objects.isNull(sysUserVo.getGrade()) && 4 == sysUserVo.getGrade())){
             SysOrganizationAdd organizationAdd = new SysOrganizationAdd();

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

@@ -103,7 +103,7 @@ tenant:
 
   ignoreLoginNames:
   ignoreFunction:
-
+# 过滤部门数据权限(下面的方法名是Mapper中的方法名)
 data-scope:
   tables:
     - sys_user_jzg_info
@@ -116,6 +116,8 @@ data-scope:
     - getTeamUserPage
     - getOrganizationUser
     - deleteOrganizationUser
+    - queryBJYwy
+
 
 
 logging:

+ 1 - 0
tenant/organization/src/main/resources/mapper/PtlAgreementCostMapper.xml

@@ -205,6 +205,7 @@
             t.is_delete = 0
             AND t.id IN (${costId})
         </where>
+        order by t.create_time desc
     </select>
 
 

+ 68 - 0
tenant/organization/src/main/resources/mapper/SysUserJzgInfoMapper.xml

@@ -125,6 +125,74 @@
         </where>
         order by suji.create_time desc
     </select>
+    <select id="queryBJYwy" resultMap="BaseResultMap">
+        select
+        suji.id,
+        suji.user_id,
+        suji.work_number,
+        su.username,
+        su.mobile ,
+        suji.name,
+        suji.dept_id,
+        sd.name AS dept_name,
+        suji.status,
+        suji.is_enable,
+        lsu.name AS leader_name,
+        ( select  aa.mobile from sys_user aa
+        where aa.id = lsu.user_id AND aa.is_delete = 0 ) AS leader_id,
+        (select re.name from sys_user_jzg_info re where re.id = suji.referrer_id) referrer_name,
+        suji.referrer_id,
+        suji.create_time AS createTime,
+        suji.create_by AS createBy
+        from
+        sys_user_jzg_info suji
+        left join sys_user su on su.id = suji.user_id AND su.is_delete = 0
+        LEFT JOIN sys_user_jzg_info lsu on lsu.id = suji.leader_id AND lsu.is_delete = 0
+        left join sys_dept sd on sd.id = suji.dept_id AND sd.is_delete = 0
+        LEFT JOIN sys_dept d ON suji.dept_id = d.id AND d.is_delete = 0
+        <where>
+            suji.is_delete = 0
+            and suji.id  in (
+            select sujis.sys_user_jzg_info_id  from sys_user_jzg_info_salesman sujis  where  sujis.type_attr != 2 AND sujis.type_attr != 3
+            )
+            <if test="leaderId != null and leaderId != ''">
+                and suji.leader_id = #{leaderId}
+            </if>
+            <if test="sysUserInfoListVo.deptId != null and sysUserInfoListVo.deptId != ''">
+                and d.route LIKE CONCAT('%', #{sysUserInfoListVo.deptId}, '%')
+            </if>
+            <if test="sysUserInfoListVo.typeAttr != null and sysUserInfoListVo.typeAttr != ''">
+                and suji.type_attr = #{sysUserInfoListVo.typeAttr}
+            </if>
+            <if test="sysUserInfoListVo.status != null and sysUserInfoListVo.status != '-1'">
+                and suji.status = #{sysUserInfoListVo.status}
+            </if>
+            <if test="sysUserInfoListVo.typeStatus != null and sysUserInfoListVo.typeStatus.size() > 0">
+                AND suji.status IN
+                <foreach item="status" collection="sysUserInfoListVo.typeStatus"
+                         open="(" separator="," close=")">
+                    #{status}
+                </foreach>
+            </if>
+            <if test="sysUserInfoListVo.isEnable != null and sysUserInfoListVo.isEnable != ''">
+                and suji.is_enable = #{sysUserInfoListVo.isEnable}
+            </if>
+            <if test="sysUserInfoListVo.sysOrganizationId != null and sysUserInfoListVo.sysOrganizationId != ''">
+                and so.id = #{sysUserInfoListVo.sysOrganizationId}
+            </if>
+            <if test="sysUserInfoListVo.leaderId != null and sysUserInfoListVo.leaderId != ''">
+                and (suji.leader_id = #{sysUserInfoListVo.leaderId}
+                or  lsu.name = #{sysUserInfoListVo.leaderId})
+            </if>
+            <if test="sysUserInfoListVo.salesman != null and sysUserInfoListVo.salesman != ''">
+                and (suji.name like concat('%',#{sysUserInfoListVo.salesman},'%')
+                or  su.mobile = #{sysUserInfoListVo.salesman}
+                or  suji.work_number = #{sysUserInfoListVo.salesman}
+                or  su.id = #{sysUserInfoListVo.salesman})
+            </if>
+        </where>
+        order by suji.create_time desc
+    </select>
 
     <!-- 查询成员 lipf 2026年4月24日11:10:15 -->
     <select id="queryMember" resultMap="BaseResultMap">