一 数据库表结构
DROP TABLE IF EXISTS `pms_category`;
CREATE TABLE `pms_category` (
`cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
`name` char(50) DEFAULT NULL COMMENT '分类名称',
`parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
`cat_level` int(11) DEFAULT NULL COMMENT '层级',
`show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示],用于逻辑删除',
`sort` int(11) DEFAULT NULL COMMENT '排序',
`icon` char(255) DEFAULT NULL COMMENT '图标地址',
`product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
`product_count` int(11) DEFAULT NULL COMMENT '商品数量',
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1433 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';
二 控制器实现
/**
* @className: CategoryController
* @description: 商品三级分类
* @date: 2020/10/25
* @author: cakin
*/
@RestController
@RequestMapping("product/category")
public class CategoryController {
@Autowired
private CategoryService categoryService;
/**
* 功能描述:查出所有分类以及子分类,以树形结构组装起来
*
* @author cakin
* @date 2020/10/25
* @return R 返回给前端数据
* @description:
*/
@RequestMapping("/list/tree")
public R list() {
List<CategoryEntity> entities = categoryService.listWithTree();
return R.ok().put("data", entities);
}
}
三 服务实现
/**
* 功能描述:查出所有分类以及子分类,以树形结构组装起来
*
* @author cakin
* @date 2020/10/25
* @return List<CategoryEntity>:树形结构列表返回父子结构
* @description:
*/
@Override
public List<CategoryEntity> listWithTree() {
// 1 查出所有分类
List<CategoryEntity> entities = baseMapper.selectList(null);
// 2 组装成父子的树形结构
// 2.1 找到所有的一级分类
List<CategoryEntity> level1Menus = entities.stream()
.filter(categoryEntity -> categoryEntity.getParentCid() == 0) // 过滤一级分类
.map((menu) -> {
menu.setChildren(getChildrens(menu, entities));
return menu;
}) // 设置一级二类的孩子
.sorted((menu1, menu2) -> {
return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
}) // 给一级分类排序
.collect(Collectors.toList());
// 2.2 返回一级分类列表
return level1Menus;
}
/**
* 功能描述:递归查找某个菜单的子菜单
*
* @param root 当前菜单
* @param all 所有分类
* @return List<CategoryEntity> 当前菜单的子菜单列表
* @author cakin
* @date 2020/10/23
*/
private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {
// 当前菜单的子菜单列表
List<CategoryEntity> children = all.stream()
.filter(categoryEntity -> {
return categoryEntity.getParentCid() == root.getCatId();
}) // 找出了二级菜单
.map(categoryEntity -> {
// 1 找到子菜单
categoryEntity.setChildren(getChildrens(categoryEntity, all));
return categoryEntity;
}) // 为二级菜单找到它的三级子菜单列表
.sorted((menu1, menu2) -> {
// 2 菜单的排序
return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
}) // 二级菜单排序
.collect(Collectors.toList());
return children;
}
四 测试
1 请求 http://127.0.0.1:10000/product/category/list/tree
2 以树形结构返回
{
"msg": "success",
"code": 0,
"data": [
{
"catId": 1,
"name": "图书、音像、电子书刊",
"parentCid": 0,
"catLevel": 1,
"showStatus": 1,
"sort": 0,
"icon": null,
"productUnit": null,
"productCount": 0,
"children": [
{
"catId": 22,
"name": "电子书刊",
"parentCid": 1,
"catLevel": 2,
"showStatus": 1,
"sort": 0,
"icon": null,
"productUnit": null,
"productCount": 0,
"children": [
{
"catId": 165,
"name": "电子书",
"parentCid": 22,
"catLevel": 3,
"showStatus": 1,
"sort": 0,
"icon": null,
"productUnit": null,
"productCount": 0
},
{
"catId": 166,
"name": "网络原创",
"parentCid": 22,
"catLevel": 3,
"showStatus": 1,
"sort": 0,
"icon": null,
"productUnit": null,
"productCount": 0
},
{
"catId": 167,
"name": "数字杂志",
"parentCid": 22,
"catLevel": 3,
"showStatus": 1,
"sort": 0,
"icon": null,
"productUnit": null,
"productCount": 0
},
{
"catId": 168,
"name": "多媒体图书",
"parentCid": 22,
"catLevel": 3,
"showStatus": 1,
"sort": 0,
"icon": null,
"productUnit": null,
"productCount": 0
}
]
},
......