确认

  • [X] 我使用的版本是最新版, 并且使用插件确认过项目里无依赖版本冲突
  • [X] 我已经在 issue 中搜索过, 确认问题没有被提出过
  • [X] 我已经修改标题, 将标题中的 描述 替换为遇到的问题

当前程序版本

3.5.9

问题描述

`package com.fengjun.finance.vo;

import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fengjun.finance.entity.Enterprise; import com.fengjun.finance.utils.SnowflakeIdGenerator; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.util.StringUtils;

import java.time.LocalDate; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors;

/* * @ClassName EnterpriseVO * @Description TODO * @Author ywy * @Date 2024/10/10 17:43 / @Data @Builder @AllArgsConstructor @NoArgsConstructor public class EnterpriseVO {

@JsonSerialize(using = ToStringSerializer.class)
private Long enterpriseId;
private String enterpriseName;
private String enterpriseAbbreviationName;

@JsonSerialize(using = ToStringSerializer.class)
private Long parentId;
private Byte archivingStatus;
private Byte completionStatus;
private Byte enterpriseType;
private String mnemonicCode;
private String taxpayerIdentificationNumber;
private String enterpriseProvince;
private String enterpriseCity;

private Byte businessType;
private String signatureAnnotator;

@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate periodWhichBelongsStart;

@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate periodWhichBelongsEnd;

@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate reportDate;

@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
private String userName;
private String nickName;
private Byte userType;

/**
 * 企业组
 */
@JsonSerialize(using = ToStringSerializer.class)
private Long enterpriseGroup;

private Integer sort;

private Boolean isLowestMerge;

private List<UserVO> users;

/**
 * 子节点
 */
private List<EnterpriseVO> children = new ArrayList<>();

/**
 * 科目余额表导入状态,1导入了,2 没导入
 */
private Integer accountBalanceUploadStatus;

/**
 * 科目余额表匹配状态1全匹配了,2 没全匹配
 */
private Integer accountBalanceMatchStatus;

/**
 * tb的校验状态
 */
private Integer tbCheck;


/**
 * @param
 * @return
 * @author ywy
 * @Description Enterprise 转换成 EnterpriseVO
 * @date 2024/10/15 13:44
 */
public static EnterpriseVO convertToVO(Enterprise enterprise) {
    if (enterprise == null) {
        return null;
    }
    EnterpriseVO vo = new EnterpriseVO();
    vo.setEnterpriseId(enterprise.getId());
    vo.setEnterpriseName(enterprise.getEnterpriseName());
    vo.setEnterpriseAbbreviationName(enterprise.getEnterpriseAbbreviationName());
    vo.setParentId(enterprise.getParentId());
    vo.setArchivingStatus(enterprise.getArchivingStatus());
    vo.setCompletionStatus(enterprise.getCompletionStatus());
    vo.setEnterpriseType(enterprise.getEnterpriseType());
    vo.setMnemonicCode(enterprise.getMnemonicCode());
    vo.setTaxpayerIdentificationNumber(enterprise.getTaxpayerIdentificationNumber());
    vo.setEnterpriseCity(enterprise.getEnterpriseCity());
    vo.setEnterpriseProvince(enterprise.getEnterpriseProvince());
    vo.setReportDate(enterprise.getReportDate());
    vo.setEnterpriseGroup(enterprise.getEnterpriseGroup());
    vo.setPeriodWhichBelongsStart(enterprise.getPeriodWhichBelongsStart());
    vo.setPeriodWhichBelongsEnd(enterprise.getPeriodWhichBelongsEnd());
    vo.setSignatureAnnotator(enterprise.getSignatureAnnotator());
    vo.setReportDate(enterprise.getReportDate());
    vo.setSort(enterprise.getSort());
    return vo;
}

/**
 * @param enterpriseVO
 * @return Enterprise
 * @author ywy
 * @Description EnterpriseVO 转换成 Enterprise
 * @date 2024/10/15 13:44
 */
public static Enterprise convertToVO(EnterpriseVO enterpriseVO) {
    if (enterpriseVO == null) {
        return null;
    }
    Enterprise enterprise = new Enterprise();
    enterprise.setId(enterpriseVO.getEnterpriseId());
    enterprise.setEnterpriseName(enterpriseVO.getEnterpriseName());
    enterprise.setEnterpriseAbbreviationName(enterpriseVO.getEnterpriseAbbreviationName());
    enterprise.setParentId(enterpriseVO.getParentId());
    enterprise.setArchivingStatus(enterpriseVO.getArchivingStatus());
    enterprise.setCompletionStatus(enterpriseVO.getCompletionStatus());
    enterprise.setEnterpriseType(enterpriseVO.getEnterpriseType());
    enterprise.setMnemonicCode(enterpriseVO.getMnemonicCode());
    enterprise.setTaxpayerIdentificationNumber(enterpriseVO.getTaxpayerIdentificationNumber());
    enterprise.setEnterpriseCity(enterpriseVO.getEnterpriseCity());
    enterprise.setEnterpriseProvince(enterpriseVO.getEnterpriseProvince());
    enterprise.setPeriodWhichBelongsStart(enterpriseVO.getPeriodWhichBelongsStart());
    enterprise.setPeriodWhichBelongsEnd(enterpriseVO.getPeriodWhichBelongsEnd());
    enterprise.setSignatureAnnotator(enterpriseVO.getSignatureAnnotator());
    enterprise.setReportDate(enterpriseVO.getReportDate());
    enterprise.setEnterpriseGroup(enterpriseVO.getEnterpriseGroup());
    enterprise.setSort(enterpriseVO.getSort());
    return enterprise;
}


private static void buildChildrenTree(EnterpriseVO parent, Map<String, EnterpriseVO> allEnterprise) {
    if (parent.getChildren() == null) {
        parent.setChildren(new ArrayList<>());
    }
    for (EnterpriseVO enterprise : allEnterprise.values()) {
        if (enterprise.getParentId() != null && enterprise.getParentId().equals(parent.getEnterpriseId())) {
            parent.getChildren().add(enterprise);
            // 递归构建当前子节点的子树
            buildChildrenTree(enterprise, allEnterprise);
        }
    }
}

private static List<EnterpriseVO> getAllChildren(EnterpriseVO parent, Map<String, EnterpriseVO> enterpriseMap) {
    List<EnterpriseVO> children = new ArrayList<>();
    if (parent.getChildren() != null) {
        for (EnterpriseVO child : parent.getChildren()) {
            children.add(child);
            // 递归获取当前子节点的所有子节点
            children.addAll(getAllChildren(child, enterpriseMap));
        }
    }
    return children;
}

/**
 * @param
 * @return
 * @author ywy
 * @Description 获取所有客户的树
 * @date 2024/11/22 18:22
 */
public static Map<Long, EnterpriseVO> buildTreeMap(Map<String, EnterpriseVO> allEnterprise) {
    Map<Long, EnterpriseVO> treeMap = new ConcurrentHashMap<>();
    List<EnterpriseVO> rootCandidates = new ArrayList<>();

    // 首先,将所有企业对象放入treeMap中,以便后续可以通过ID快速查找
    for (EnterpriseVO enterprise : allEnterprise.values()) {
        treeMap.put(enterprise.getEnterpriseId(), enterprise);
    }

    // 遍历映射中的每个企业对象
    for (EnterpriseVO enterprise : allEnterprise.values()) {
        Long parentId = enterprise.getParentId();
        if (parentId == 0 || parentId == null) {
            // 如果parentId为0或者为null,则视为根节点
            rootCandidates.add(enterprise);
        } else {
            // 否则,将当前企业对象添加到其父节点的子节点列表中
            EnterpriseVO parent = treeMap.get(parentId);
            if (parent != null) {
                parent.getChildren().add(enterprise);
            } else {
                rootCandidates.add(enterprise);
            }
        }
    }
    return treeMap;
}

/**
 * @param enterpriseMap
 * @return List<EnterpriseVO>
 * @author ywy
 * @Description 递归构建树方法,只展示最顶层的客户树
 * @date 2024/10/11 11:35
 */
public static List<EnterpriseVO> buildTree(Map<String, EnterpriseVO> enterpriseMap) {
    try {
        List<EnterpriseVO> rootNodes = new ArrayList<>();
        // 遍历映射中的每个企业对象
        for (EnterpriseVO enterprise : enterpriseMap.values()) {
            String parentId = String.valueOf(enterprise.getParentId());
            if (parentId.equals(0) || !StringUtils.hasText(parentId)) {
                // 如果parentId为null或者父节点不存在于映射中(可能是数据不完整),则视为根节点
                rootNodes.add(enterprise);
            } else {
                // 否则,将当前企业对象添加到其父节点的子节点列表中
                EnterpriseVO parent = enterpriseMap.get(parentId);
                if (parent != null) {
                    parent.getChildren().add(enterprise);
                } else {
                    rootNodes.add(enterprise);
                }
            }
        }

        // 对根节点进行排序
        rootNodes.sort(Comparator.comparingInt(EnterpriseVO::getSort));

        // 对每个根节点的子节点进行排序
        for (EnterpriseVO rootNode : rootNodes) {
            sortChildren(rootNode);
        }

        return rootNodes;
    } catch (RuntimeException e) {
        throw e;
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("构建客户树发生异常");
    }
}

/**
 * @param
 * @return
 * @author ywy
 * @Description 构建某个节点下的所有子节点,平铺在同一层级上去
 * @date 2024/12/19 15:20
 */
public static List<EnterpriseVO> buildList(EnterpriseVO enterpriseVO) {
    List<EnterpriseVO> allEnterprises = new ArrayList<>();
    addAllEnterprises(enterpriseVO, allEnterprises);
    return allEnterprises;
}

private static void addAllEnterprises(EnterpriseVO enterpriseVO, List<EnterpriseVO> allEnterprises) {
    // 首先添加当前节点
    allEnterprises.add(enterpriseVO);

    // 然后递归地添加所有子节点
    List<EnterpriseVO> children = enterpriseVO.getChildren();
    if (children != null) {
        for (EnterpriseVO child : children) {
            addAllEnterprises(child, allEnterprises);
        }
    }
}

private static void sortChildren(EnterpriseVO node) {
    if (node.getChildren() != null && !node.getChildren().isEmpty()) {
        node.getChildren().sort(Comparator.comparingInt(EnterpriseVO::getSort));
        // 递归地对每个子节点的子节点进行排序
        for (EnterpriseVO child : node.getChildren()) {
            sortChildren(child);
        }
    }
}

/**
 * @param enterpriseMap
 * @param topId
 * @return
 * @author ywy
 * @Description 从一个企业树结构中复制并生成一个新的企业树结构
 * @date 2024/10/31 13:34
 */
public static List<EnterpriseVO> copyEnterpriseTreeWithNewParentId(Map<String, EnterpriseVO> enterpriseMap, String topId) {
    SnowflakeIdGenerator idWorker = new SnowflakeIdGenerator(0, 0);
    Map<String, String> oldToNewIdMap = new ConcurrentHashMap<>();
    List<EnterpriseVO> copiedTree = new ArrayList<>();

    Long groupId = null;
    // 直接处理顶级客户节点
    EnterpriseVO topEnterprise = enterpriseMap.get(topId);
    if (topEnterprise != null) {
        String newTopId = String.valueOf(idWorker.nextId());
        groupId = Long.valueOf(newTopId);
        oldToNewIdMap.put(topId, newTopId);

        EnterpriseVO copiedTopEnterprise = new EnterpriseVO();
        copiedTopEnterprise.setEnterpriseId(Long.valueOf(newTopId));
        copiedTopEnterprise.setParentId(0L);
        copiedTopEnterprise.setEnterpriseName(topEnterprise.getEnterpriseName());
        copiedTopEnterprise.setTaxpayerIdentificationNumber(topEnterprise.getTaxpayerIdentificationNumber());
        copiedTopEnterprise.setBusinessType(topEnterprise.getBusinessType());
        copiedTopEnterprise.setArchivingStatus(topEnterprise.getArchivingStatus());
        copiedTopEnterprise.setEnterpriseAbbreviationName(topEnterprise.getEnterpriseAbbreviationName());
        copiedTopEnterprise.setSignatureAnnotator(topEnterprise.getSignatureAnnotator());
        copiedTopEnterprise.setReportDate(topEnterprise.getReportDate());
        copiedTopEnterprise.setEnterpriseGroup(groupId);
        copiedTopEnterprise.setSort(topEnterprise.getSort());
        copiedTree.add(copiedTopEnterprise);

        // 使用DFS复制子节点
        Deque<String> stack = new ArrayDeque<>();
        stack.addAll(enterpriseMap.keySet().stream()
                .filter(key -> enterpriseMap.get(key).getParentId().equals(topEnterprise.getEnterpriseId()))
                .collect(Collectors.toList()));

        while (!stack.isEmpty()) {
            String currentOldId = stack.pop();
            if (!oldToNewIdMap.containsKey(currentOldId)) {
                String currentNewId = String.valueOf(idWorker.nextId());
                oldToNewIdMap.put(currentOldId, currentNewId);

                EnterpriseVO currentEnterprise = enterpriseMap.get(currentOldId);
                EnterpriseVO copiedEnterprise = new EnterpriseVO();
                copiedEnterprise.setEnterpriseId(Long.valueOf(currentNewId));
                copiedEnterprise.setParentId(Long.valueOf(oldToNewIdMap.get(String.valueOf(currentEnterprise.getParentId()))));
                copiedEnterprise.setEnterpriseName(currentEnterprise.getEnterpriseName());
                copiedEnterprise.setTaxpayerIdentificationNumber(currentEnterprise.getTaxpayerIdentificationNumber());
                copiedEnterprise.setBusinessType(currentEnterprise.getBusinessType());
                copiedEnterprise.setArchivingStatus(currentEnterprise.getArchivingStatus());
                copiedEnterprise.setEnterpriseAbbreviationName(currentEnterprise.getEnterpriseAbbreviationName());
                copiedEnterprise.setSignatureAnnotator(currentEnterprise.getSignatureAnnotator());
                copiedEnterprise.setReportDate(currentEnterprise.getReportDate());
                copiedEnterprise.setEnterpriseGroup(groupId);
                copiedEnterprise.setSort(currentEnterprise.getSort());
                copiedTree.add(copiedEnterprise);

                stack.addAll(enterpriseMap.keySet().stream()
                        .filter(key -> enterpriseMap.get(key).getParentId().equals(currentEnterprise.getEnterpriseId()))
                        .collect(Collectors.toList()));
            }
        }
    } else {
        // 处理顶级客户节点不存在的情况
        // 可以抛出异常或返回空列表等
        System.out.println("Top enterprise with ID " + topId + " not found.");
    }

    return copiedTree;
}

/**
 * @param
 * @return
 * @author ywy
 * @Description 获取所有 children 不为空的节点列表,并按深度排序(最下层的节点在最前面)
 * @date 2024/11/23 16:58
 */
public static List<EnterpriseNodeWrapper> getAllNonEmptyChildrenNodesSortedByDepth(EnterpriseVO root) {
    List<EnterpriseNodeWrapper> resultWrappers = new ArrayList<>();
    findNonEmptyChildrenNodes(root, 0, resultWrappers);
    // 根据深度对结果进行排序,深度越大的排在越后面
    Collections.sort(resultWrappers, Comparator.comparingInt(EnterpriseNodeWrapper::getDepth).reversed());
    return resultWrappers;
}

private static void findNonEmptyChildrenNodes(EnterpriseVO root, int depth, List<EnterpriseNodeWrapper> result) {
    if (root == null) {
        return;
    }
    // 检查当前节点是否为最低合并节点
    if (root.getChildren().isEmpty()) {
        root.setIsLowestMerge(true);
    } else {
        boolean flag = true;
        for (EnterpriseVO child : root.getChildren()) {
            if (!child.getChildren().isEmpty()) {
                root.setIsLowestMerge(false);
                flag = false;
                break;
            }
        }
        if (flag) {
            root.setIsLowestMerge(flag);
        }
    }


    // 如果当前节点的 children 不为空,则包装并添加到结果列表中
    if (!root.getChildren().isEmpty()) {
        result.add(new EnterpriseNodeWrapper(root, depth));
    }

    // 递归遍历所有子节点,深度加1
    for (EnterpriseVO child : root.getChildren()) {
        findNonEmptyChildrenNodes(child, depth + 1, result);
    }
}

} `

`