java关于三级分类功能实现

1、技术前提

1.1、后端采用的技术是SpringBoot+MybatisPlus+人人代码生成器实现的

1.2、前端采用的技术是VUE +ElementUI+人人开源实现的

2、后端实现

2.1、pom依赖

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.8.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.2.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>

2.2 application.yml配置文件

spring:
  application:
    name: mall-product
  datasource:
    url: jdbc:mysql://localhost:3306/mall_pms?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml

2.3、实体类

@Data
public class CategoryDTO implements Serializable {

    /**
     * 分类id
     */
    @TableId
    private Long catId;
    /**
     * 分类名称
     */
    private String name;
    /**
     * 父分类id
     */
    private Long parentCid;
    /**
     * 层级
     */
    private Integer catLevel;
    /**
     * 是否显示[0-不显示,1显示]
     */
    private Integer showStatus;
    /**
     * 排序
     */
    private Integer sort;
    /**
     * 图标地址
     */
    private String icon;
    /**
     * 计量单位
     */
    private String productUnit;
    /**
     * 商品数量
     */
    private Integer productCount;

    private List<CategoryDTO> children;
}

2.4 dao层

@Mapper
public interface CategoryDao extends BaseMapper<CategoryEntity> {
    
}

2.5、service

public interface CategoryService extends IService<CategoryEntity> {
    /**
     * 查询三级分类
     * @return
     */
    List<CategoryDTO> listWithTree();

}

2.6、service实现类具体功能实现

@Override
    public List<CategoryDTO> listWithTree() {
        //查出所有分类
        List<CategoryEntity> categoryList = baseMapper.selectList(null);

        List<CategoryDTO> categoryDTOList = new ArrayList<>();
        //查询所有父类目录
        for(CategoryEntity categoryEntity :  categoryList) {
            if(categoryEntity.getParentCid() == 0) {
                CategoryDTO categoryDTO = categoryEntity2CategoryDTO(categoryEntity);
                categoryDTOList.add(categoryDTO);
            }

            categoryDTOList.sort(Comparator.comparing(CategoryDTO::getSort));
        }

        //查询子目录
        findSubCategory(categoryDTOList, categoryList);

        return categoryDTOList;
    }

    /**
     * 查询子目录
     * @param categoryDTOList
     * @param categoryEntityList
     */
    private void findSubCategory(List<CategoryDTO> categoryDTOList, List<CategoryEntity> categoryEntityList) {

        //遍历所有父类分类
        for(CategoryDTO categoryDTO : categoryDTOList) {
            List<CategoryDTO> subCategoryVoList = new ArrayList<>();
            //遍历父类下的cat_id与子类parent_cid相匹配的分类
            for(CategoryEntity category : categoryEntityList) {
                if(categoryDTO.getCatId().equals(category.getParentCid())) {
                    CategoryDTO subCategoryVo = categoryEntity2CategoryDTO(category);
                    subCategoryVoList.add(subCategoryVo);
                }
                //升序排序
                subCategoryVoList.sort(Comparator.comparing(CategoryDTO::getSort));
                //设置subCategories
                categoryDTO.setChildren(subCategoryVoList);
                
            }
            //递归调用
            findSubCategory(subCategoryVoList, categoryEntityList);
        }
    }

    /**
     * 分类对象转换
     * @param categoryEntity
     * @return
     */
    private CategoryDTO categoryEntity2CategoryDTO(CategoryEntity categoryEntity) {
        CategoryDTO categoryDTO = new CategoryDTO();
        BeanUtils.copyProperties(categoryEntity, categoryDTO);
        return categoryDTO;
    }

2.7controller层

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

        List<CategoryDTO> entityList =  categoryService.listWithTree();

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

3、前端实现

详细的我就不一一给出来了,要是看不懂可以参照人人开源或者ElementUi文档实现其他功能!!!
category.vue

<template>
  <el-tree
    show-checkbox
    node-key="catId"
    :data="menus"
    :props="defaultProps"
    @node-click="handleNodeClick"
    :expand-on-click-node="false"
    :default-expanded-keys="expandedKey">
    >
    <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button
            v-if="node.level <= 2"
            type="text"
            size="mini"
            @click="() => append(data)">
            Append
          </el-button>
          <el-button
            v-if="node.childNodes.length == 0"
            type="text"
            size="mini"
            @click="() => remove(node, data)">
            Delete
          </el-button>
        </span>
      </span>
  </el-tree>
</template>

<script>
    export default {
        name: "category",
      data() {
        return {
          menus: [],
          expandedKey: [],
          defaultProps: {
            children: 'children',
            label: 'name'
          }
        };
      },
      methods: {
        handleNodeClick(data) {
          console.log(data);
        },
        getMenus() {
          this.$http({
            url: this.$http.adornUrl('/product/category/list/tree'),
            method: 'get'
          }).then(({data}) => {
            this.menus = data.data;
          })
        },
        append(data) {
          console.log("append", data)
        },
        remove(node, data) {
          let ids = [data.catId]
          this.$confirm(`是否删除【${data.name}】菜单?`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            console.log("remove", node, data)
            this.$http({
              url: this.$http.adornUrl('/product/category/delete'),
              method: 'post',
              data: this.$http.adornData(ids, false)
            }).then(({data}) => {
              this.$message({
                message: '菜单删除成功',
                type: 'success'
              });
              //删除成功,重新加载菜单
              this.getMenus()
              //展开删除节点的父节点
             this.expandedKey = [node.parent.data.catId]
            })
          }).catch(() => {

          });
        }
      },
      created() {
          this.getMenus()
      }
    }
</script>

<style scoped>

</style>

4、启动项目

@SpringBootApplication
//包扫描
@MapperScan("com.cluck.mall.product.dao")
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }
}

效果图:
一级分类

一级分类.png

二级分类

二级分类.png

三级分类

三级分类.png

人人开源git地址:https://gitee.com/renrenio

ElementUi地址:https://element.eleme.cn/#/zh-CN

主要功能实现代码都是在categoryServiceImpl实现类里面,要是前端不太会的话,其实只要把后端功能跑起来就行了,你们肯定是有更好的思路和更简洁的代码也是欢迎推荐推荐的~~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352