欢迎访问个人博客德鲁大叔撸代码
在前台页面很常见的一种需求是,以树形结构展示具有层级关系的数据。比如企业的部门信息、大部分管理系统的菜单、省市区信息等等。
具体如下图所示
一、表创建以及数据导入
执行下面创建表sql,创建sys_region存具体信息,表信息下载地址sys_region 行政区域表
CREATE TABLE `sys_region` (
`id` int(11) NOT NULL COMMENT '区域主键',
`name` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '区域名称',
`pid` int(11) NULL DEFAULT NULL COMMENT '区域上级标识',
`sname` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地名简称',
`level` int(11) NULL DEFAULT NULL COMMENT '区域等级',
`citycode` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '区域编码',
`postcode` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮政编码',
`mername` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组合名称',
`lng` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '经度',
`lat` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '纬度',
`pinyin` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '拼音',
`gmt_create` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '创建时间',
`gmt_modified` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态 0正常 1停用',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
二、编写Region实体类(mybatis generator自动生成后增加子区域属性)
@Data
public class Region {
private Integer id;
private String name;
private Integer pid;
private String sname;
private Integer level;
private String citycode;
private String postcode;
private String mername;
private String lng;
private String lat;
private String pinyin;
private Date gmtCreate;
private Date gmtModified;
private String status;
/**
* 子区域
*/
private Listchildren = new ArrayList<>();
}
三、查询接口和mybatis映射文件(省略,只展示查询sql)
select
from sys_region
AND name like concat('%', #{name}, '%')
AND citycode = #{citycode}
order by id
四、组装树形菜单(根据步骤三查到的列表)
1、控制转发层
@RestController
@RequestMapping("/region")
public class RegionController {
@Autowired
private RegionService regionService;
@GetMapping("/list")
public AjaxResult list(Region region){
ListregionList = regionService.selectRegionList(region); // 根据步骤三查到的集合(region表的全部数据)
Listtree = regionService.buildAreaTree(regionList); // 组装一个菜单树
return AjaxResult.success(tree); // 响应返回给前端页面的数据
}
}
2、组装树形菜单入口
@Override
public ListbuildAreaTree(Listregions) {
Listtree = new ArrayList<>();
for(Iteratorit = regions.iterator();it.hasNext();){
Region region = (Region) it.next();
if(region.getPid() == 0){
recursionFn(regions, region); //递归列表
tree.add(region);
}
}
return tree;
3、递归列表
/**
* 递归列表
* @param list
* @param region
*/
private void recursionFn(Listlist, Region region){
// 得到子节点列表
ListchildList = getChildList(list, region);
region.setChildren(childList);
for(Region child : childList){
if(hasChild(list,child)){
//判断是否有子节点
Iteratorit = childList.iterator();
while (it.hasNext()){
Region n = (Region) it.next();
recursionFn(list, n);
}
}
}
}
4、得到子节点列表(得到下级区域)
/**
* 得到子节点列表
* @param list
* @param region
* @return
*/
private ListgetChildList(Listlist, Region region){
Listtlist = new ArrayList();
Iteratorit = list.iterator();
while (it.hasNext()){
Region region1 = (Region) it.next();
if(region1.getPid().longValue() == region.getId().longValue()){
tlist.add(region1);
}
}
return tlist;
}
5、判断是否有下级区域
/**
* 判断是否有子节点
* @param list
* @param region
* @return
*/
private boolean hasChild(Listlist, Region region)
{
return getChildList(list, region).size() > 0 ? true : false;
}
五、postman测试
以省/直辖市为根节点,组装结果35
以陕西省为例,展示具体的市级信息