使用效果
初始化加载顶层节点,点击各层的>加载该节点的子节点,加载后>标识去除不再重复加载。
前端代码
vue ant-design组件
- tree-data,树节点,children方式或id、pid方式
- load-data,展开节点事件,响应该事件加载子节点
<a-tree-select v-model:value="sample" :tree-data="sampleTreeData" :load-data="onLoadSampleTreeData" style="width: 100%" allowClear treeDataSimpleMode :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" placeholder="请选择测试计划/样品" > </a-tree-select>
定义interface
- 异步加载通过id和pid匹配,因此没有children属性,替换为id何pid
- 添加level便于后端识别,如果后端为一个表内的数据且通过id和pid或parentid关联则不需要
export interface TreeDataItem { id: string | number; pId: string | number; value: string; title: string; isLeaf?: boolean; level: string; }
加载(跟节点)数据
调用后端查询数据并赋值给treeData,treeData绑定控件的treeData属性。
async function loadSampleTreeRootData() { // loading.value = true let params = {"level":"0"}; sampleTreeNode(params).then(result => { console.log(result) sampleTreeData.value = sampleTreeData.value.concat(result); }).finally(() => { }); // loading.value = false } loadSampleTreeRootData()
加载(节点的子节点)数据
响应控件的load-data事件,查询要展开节点的子节点数据,并合并到treeData中,控件会根据id和pid显示层级关系。
const onLoadSampleTreeData = (treeNode: any) => { return new Promise((resolve: (value?: unknown) => void) => { // console.log("node:"); // console.log(treeNode.dataRef) const { id,level,value } = treeNode.dataRef; // console.log("id:"+id); // console.log("level:"+level); // console.log("value:"+value); setTimeout(() => { let nextLevel = "1"; if(level=="1")nextLevel="2"; let params = {"level":nextLevel, "id":id}; sampleTreeNode(params).then(result => { // console.log("result:"); // console.log(result); sampleTreeData.value = sampleTreeData.value.concat(result); }).finally(() => { }); resolve(); }, 300); }); };
后端代码
定义treeNodeVO
pId和isLeaf注解下,避免springMVC默认的序列化。
(默认序列化为pid/leaf)
@Data public class PlantSampleTreeNodeVO { //key private String id; // private long id; @JsonProperty("pId") private String pId; // private long pId; //树节点显示的内容 private String title; //默认根据此属性值进行筛选(其值在整个树范围内唯一) private Object value; //是否是叶子节点 @JsonProperty("isLeaf") private boolean isLeaf; //节点层级 private String level; }
controller提供数据
因为是异步加载,三个表的查询可在一个service中实现,或直接使用各自的treeNode的service。
@Override public List<PlantSampleTreeNodeVO> getPlantSampleTreeNodeVO(String level, String id) { List<PlantSampleTreeNodeVO> plantSampleTreeVONodeList = new ArrayList<>(); switch (level) {//顶级节点 case "0": //查询所在班组,plant member List<Plant> plantList = plantService.list(); for (Plant plant : plantList) { //创建顶层树/节点 PlantSampleTreeNodeVO plantNode = new PlantSampleTreeNodeVO(); // System.out.println(plant.getId()); // System.out.println(Long.parseLong(plant.getId())); // System.out.println(Long.valueOf(plant.getId()).longValue()); // plantNode.setId(Long.parseLong(plant.getId())); plantNode.setId(plant.getId()); plantNode.setPId("0");//and-design tree指定的值 plantNode.setValue(plant.getId()); plantNode.setTitle(plant.getPlantName()); plantNode.setLeaf(false);//需根据业务逻辑判断是否有子节点,省略处理 plantNode.setLevel("0"); plantSampleTreeVONodeList.add(plantNode); } break; case "1": //查询班组相关的样品组模板 QueryWrapper<SampleGroupTemplate> sampleGroupTemplateQueryWrapper = new QueryWrapper<>(); sampleGroupTemplateQueryWrapper.eq("plantid",id); List<SampleGroupTemplate> sampleGroupTemplateList = sampleGroupTemplateService.list(sampleGroupTemplateQueryWrapper); //循环各样品组模板显示其下的测试计划/样品 for(SampleGroupTemplate sampleGroupTemplate: sampleGroupTemplateList){ //添加到树上 PlantSampleTreeNodeVO sampleGroupNode = new PlantSampleTreeNodeVO(); // sampleGroupNode.setId(Long.parseLong(sampleGroupTemplate.getId())); sampleGroupNode.setId(sampleGroupTemplate.getId()); // sampleGroupNode.setPId(Long.parseLong(id)); sampleGroupNode.setPId(id); sampleGroupNode.setValue(sampleGroupTemplate.getId()); sampleGroupNode.setTitle(sampleGroupTemplate.getSampleGroupName()); sampleGroupNode.setLeaf(false); sampleGroupNode.setLevel("1"); plantSampleTreeVONodeList.add(sampleGroupNode); } break; case "2": //查询样品组模板显示其下的测试计划/样品 QueryWrapper<SgtSample> sampleQueryWrapper = new QueryWrapper<>(); sampleQueryWrapper.eq("templateid",id); List<SgtSample> sampleList = this.list(sampleQueryWrapper); //循环各样品 for(SgtSample sample: sampleList) { PlantSampleTreeNodeVO sampleNode = new PlantSampleTreeNodeVO(); // sampleNode.setId(Long.parseLong(sample.getId())); sampleNode.setId(sample.getId()); // sampleNode.setPId(Long.parseLong(id)); sampleNode.setPId(id); sampleNode.setValue(sample.getId()); sampleNode.setTitle(sample.getSampleName()); sampleNode.setLeaf(true);//叶子节点 sampleNode.setLevel("2"); plantSampleTreeVONodeList.add(sampleNode); } break; } return plantSampleTreeVONodeList; }