element ul+VUE+Spring boot + MybatisPlus实现三级菜单分类

效果图:

element ul+VUE+Spring boot + MybatisPlus实现三级菜单分类_第1张图片

 

前端代码:



 

 

 

后端代码

 

控制层

package com.atguigu.gulimall.product.controller;

import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;


/**
 * 商品三级分类
 *
 * @author leifengyang
 * @email [email protected]
 * @date 2019-10-01 22:50:32
 */
@RestController
@RequestMapping("product/category")
public class CategoryController {
    @Autowired
    private CategoryService categoryService;

    /**
     * 查出所有分类以及子分类,以树形结构组装起来
     */
    @RequestMapping("/list/tree")
    public R list(){

        List entities = categoryService.listWithTree();


        return R.ok().put("data", entities);
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{catId}")
    //@RequiresPermissions("product:category:info")
    public R info(@PathVariable("catId") Long catId){
      CategoryEntity category = categoryService.getById(catId);

        return R.ok().put("data", category);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("product:category:save")
    public R save(@RequestBody CategoryEntity category){
      categoryService.save(category);

        return R.ok();
    }

    @RequestMapping("/update/sort")
    //@RequiresPermissions("product:category:update")
    public R updateSort(@RequestBody CategoryEntity[] category){
        //maibeitisi-pulasi 的updateBatchById 就是批量修改
        categoryService.updateBatchById(Arrays.asList(category));
        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:category:update")
    public R update(@RequestBody CategoryEntity category){
      categoryService.updateCascade(category);
        return R.ok();
    }


    /**
     * 删除
     * @RequestBody:获取请求体,必须发送POST请求
     * SpringMVC自动将请求体的数据(json),转为对应的对象
     */
    @RequestMapping("/delete")
    //@RequiresPermissions("product:category:delete")
    public R delete(@RequestBody Long[] catIds){


      //categoryService.removeByIds(Arrays.asList(catIds));

        categoryService.removeMenuByIds(Arrays.asList(catIds));

        return R.ok();
    }

}

 

服务层

 

服务层接口:

package com.atguigu.gulimall.product.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.gulimall.product.entity.CategoryEntity;

import java.util.List;
import java.util.Map;

/**
* 商品三级分类
*
* @author leifengyang
* @email [email protected]
* @date 2019-10-01 21:08:48
*/
public interface CategoryService extends IService {

    PageUtils queryPage(Map params);

    List listWithTree();

    void removeMenuByIds(List asList);

    /**
     * 找到catelogId的完整路径;
     * [父/子/孙]
     * @param catelogId
     * @return
     */
    Long[] findCatelogPath(Long catelogId);

    void updateCascade(CategoryEntity category);

}

服务层接口实现类:

package com.atguigu.gulimall.product.service.impl;

import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;
import com.atguigu.gulimall.product.dao.CategoryDao;
import com.atguigu.gulimall.product.entity.CategoryEntity;
import com.atguigu.gulimall.product.service.CategoryBrandRelationService;
import com.atguigu.gulimall.product.service.CategoryService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl implements CategoryService {

//    @Autowired
//    CategoryDao categoryDao;

    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map params) {
        IPage page = this.page(
                new Query().getPage(params),
                new QueryWrapper()
        );

        return new PageUtils(page);
    }

    @Override
    public List listWithTree() {
        //1、查出所有分类
        List entities = baseMapper.selectList(null);

        //2、组装成父子的树形结构

        //2.1)、找到所有的一级分类
        List level1Menus = entities.stream().filter((categoryEntity) ->   //filter 过滤掉不满足条件的所有数据
                categoryEntity.getParentCid() == 0
        ).map((menu)->{  //map 对当前filter过滤后的每个元素进行处理
            menu.setChildren(getChildrens(menu,entities));
            return menu;
        }).sorted((menu1,menu2)->{ //进行排序
            //2、菜单的排序
            return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
        }).collect(Collectors.toList()); // collect 集合 返回


        //sorted排序
        //map 影响
        //stream api       collect 收集

//        List 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());

//        List  resultList = bulidPermission(entities);

        return level1Menus;
    }

    //把返回所有菜单list集合进行封装的方法
    public static List bulidPermission(List permissionList) {

        //创建list集合,用于数据最终封装
        List finalNode = new ArrayList<>();
        //把所有菜单list集合遍历,得到顶层菜单 pid=0菜单,设置level是1
        for(CategoryEntity permissionNode : permissionList) {
            //得到顶层菜单 pid=0菜单
            if(permissionNode.getCatLevel() == 1) {
                //设置顶层菜单的level是1
                permissionNode.setCatLevel(1);
                //根据顶层菜单,向里面进行查询子菜单,封装到finalNode里面
                finalNode.add(selectChildren(permissionNode,permissionList));
            }
        }
        return finalNode;
    }

    private static CategoryEntity selectChildren(CategoryEntity permissionNode, List permissionList) {
        //1 因为向一层菜单里面放二层菜单,二层里面还要放三层,把对象初始化
        permissionNode.setChildren(new ArrayList());

        //2 遍历所有菜单list集合,进行判断比较,比较id和pid值是否相同
        for(CategoryEntity it : permissionList) {
            //判断 id和pid值是否相同
            if(permissionNode.getCatId().equals(it.getParentCid())) {
                //把父菜单的level值+1
                int level = permissionNode.getCatLevel()+1;
                it.setCatLevel(level);
                //如果children为空,进行初始化操作
                if(permissionNode.getChildren() == null) {
                    permissionNode.setChildren(new ArrayList());
                }
                //把查询出来的子菜单放到父菜单里面
                permissionNode.getChildren().add(selectChildren(it,permissionList));
            }
        }
        return permissionNode;
    }

    @Override
    public void removeMenuByIds(List asList) {
        //TODO  1、检查当前删除的菜单,是否被别的地方引用

        //逻辑删除
        baseMapper.deleteBatchIds(asList);
    }

    //[2,25,225]
    @Override
    public Long[] findCatelogPath(Long catelogId) {
        List paths = new ArrayList<>();
        List parentPath = findParentPath(catelogId, paths);

        Collections.reverse(parentPath);


        return parentPath.toArray(new Long[parentPath.size()]);
    }

    /**
     * 级联更新所有关联的数据
     * @param category
     */
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }

    //225,25,2
    private List findParentPath(Long catelogId,List paths){
        //1、收集当前节点id
        paths.add(catelogId);
        CategoryEntity byId = this.getById(catelogId);
        if(byId.getParentCid()!=0){
            findParentPath(byId.getParentCid(),paths);
        }
        return paths;

    }


    //递归查找所有菜单的子菜单
    private List getChildrens(CategoryEntity root,List all){

        List 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;
    }



}




数据访问层

均使用MybatisPlus自带的baseMapper里面的功能来实现

 

你可能感兴趣的:(前后端,后端,java,前端,spring,vue)