在开发过程中我们总是遇到一些具有层次结构的数据,这些数据在前端也总是需要以树形结构进行显示,那么后端接口如何高效的去将这些数据封装成树形结构呢?下面来进行解析讲解。
-
最终实现的一个结果图
-
设计返回的实体VO
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
@Schema(description = "知识库管理- 知识字典 - Response VO")
@Data
@EqualsAndHashCode(callSuper = false)
public class KnowledgeBaseDictTreeResVO implements Serializable {
@Schema(description = "主键id")
private Long id;
@Schema(description = "父级菜单id")
private Long parentId;
@Schema(description = "父级菜单名称")
private String parentMenuName;
@Schema(description = "菜单名称")
private String menuName;
@Schema(description = "菜单层级:1:一级菜单;2:二级菜单;3:三级菜单;4:四级菜单;")
private Integer menuLevel;
@Schema(description = "归属系统")
private String belongingSystem;
@Schema(description = "排序序号")
private Integer sort;
@Schema(description = "创建时间")
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) //jsonstring
@DateTimeFormat(pattern =FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND ) //querystri
private LocalDateTime createTime;
@Schema(description = "子集")
List<KnowledgeBaseDictTreeResVO> children;
}
-
Controller层代码
@PostMapping("/getKnowledgeBaseDictTreeList")
@Operation(summary = "获取知识字典树形列表")
@PreAuthorize("@ss.hasPermission('knowledgebase:problem:knowledgeBaseDict:list')")
public CommonResult<List<KnowledgeBaseDictTreeResVO>> getKnowledgeBaseDictTreeList(@Valid @RequestBody KnowledgeBaseDictQueryReqVO reqVO) {
return CommonResult.success(knowledgeBaseDictService.getKnowledgeBaseDictTreeList(reqVO));
}
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "知识字典树形列表查询参数 - Request Search VO")
@Data
public class KnowledgeBaseDictQueryReqVO {
@Schema(description = "菜单名称")
private String menuName;
@Schema(description = "归属系统名称")
private String belongingSystemName;
@Schema(description = "归属系统id")
private Long belongingSystemId;
}
-
Service层代码
@Override
public List<KnowledgeBaseDictTreeResVO> getKnowledgeBaseDictTreeList(KnowledgeBaseDictQueryReqVO reqVO) {
// 先查询所有顶层级结构
List<KnowledgeBaseDictDO> kbddoTopList = knowledgeBaseDictMapper.getKnowledgeBaseDictTopLevel(reqVO);
List<KnowledgeBaseDictTreeResVO> kbdtrvList = KnowledgeBaseDictConvert.INSTANCE.convert(kbddoTopList);
// 查询所有知识字典数据
List<KnowledgeBaseDictDO> allList = knowledgeBaseDictMapper.getKnowledgeBaseDictAllList(reqVO);
List<KnowledgeBaseDictTreeResVO> allkbdtrvList = KnowledgeBaseDictConvert.INSTANCE.convert(allList);
List<KnowledgeBaseDictTreeResVO> result = new ArrayList<>();
for (KnowledgeBaseDictTreeResVO kbddoTop : kbdtrvList) {
result.add(getTreeChildren(kbddoTop,allkbdtrvList));
}
return result;
}
核心实现如下:
/**
* 递归获取子级菜单
* @param vo 父级菜单
* @param list 所有菜单
* @return
*/
private KnowledgeBaseDictTreeResVO getTreeChildren(KnowledgeBaseDictTreeResVO vo,List<KnowledgeBaseDictTreeResVO> list){
List<KnowledgeBaseDictTreeResVO> childrenList = new ArrayList<>();
for(KnowledgeBaseDictTreeResVO otv : list){
if (vo.getId().equals(otv.getParentId())) {
childrenList.add(getTreeChildren(otv,list));
}
}
vo.setChildren(childrenList);
return vo;
}