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);
}
}
效果图:
一级分类
二级分类
三级分类
人人开源git地址:https://gitee.com/renrenio
ElementUi地址:https://element.eleme.cn/#/zh-CN
主要功能实现代码都是在categoryServiceImpl实现类里面,要是前端不太会的话,其实只要把后端功能跑起来就行了,你们肯定是有更好的思路和更简洁的代码也是欢迎推荐推荐的~~~~