文章目录
- 后端
- AttrGroupEntity.java
- CategoryEntity.java
- AttrGroupController.java
- CategoryServiceImpl.java
- 前端
- attrgroup-add-or-update.vue
https://element.eleme.cn/#/zh-CN/component/cascader
后端
AttrGroupEntity.java
package com.xd.cubemall.product.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* 属性分组表
*
* @author xuedong
* @email email@gmail.com
* @date 2024-08-13 01:36:04
*/
@Data
@TableName("tb_attr_group")
public class AttrGroupEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 自增ID
*/
@TableId
private Long id;
/**
* 名称
*/
private String name;
/**
* 排序
*/
private Integer sort;
/**
* 描述
*/
private String descript;
/**
* 图表
*/
private String icon;
/**
* 分类ID
*/
private Integer categoryId;
/**
* 完整的categoryID的路径
*/
@TableField(exist = false)
private Long[] categoryPath;
}
CategoryEntity.java
package com.xd.cubemall.product.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* 商品类目
*
* @author xuedong
* @email email@gmail.com
* @date 2024-08-13 01:36:04
*/
@Data
@TableName("tb_category")
public class CategoryEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 子分类
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private List<CategoryEntity> childrens;
/**
* 分类ID
*/
@TableId
private Integer id;
/**
* 分类名称
*/
private String name;
/**
* 商品数量
*/
private Integer goodsNum;
/**
* 是否显示
*/
@TableLogic(value = "1",delval = "0")
private String isShow;
/**
* 是否导航
*/
private String isMenu;
/**
* 排序
*/
private Integer seq;
/**
* 上级ID
*/
private Integer parentId;
/**
* 模板ID
*/
private Integer templateId;
}
AttrGroupController.java
package com.xd.cubemall.product.controller;
import java.util.Arrays;
import java.util.Map;
import com.xd.cubemall.common.utils.PageUtils;
import com.xd.cubemall.common.utils.R;
import com.xd.cubemall.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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.xd.cubemall.product.entity.AttrGroupEntity;
import com.xd.cubemall.product.service.AttrGroupService;
/**
* 属性分组表
*
* @author xuedong
* @email email@gmail.com
* @date 2024-08-13 07:57:20
*/
@RestController
@RequestMapping("product/attrgroup")
public class AttrGroupController {
@Autowired
private AttrGroupService attrGroupService;
@Autowired
private CategoryService categoryService;
/**
* 列表
*/
@RequestMapping("/list/{categoryId}")
//@RequiresPermissions("product:attrgroup:list")
public R list(@RequestParam Map<String, Object> params, @PathVariable("categoryId") Long categoryId){
//PageUtils page = attrGroupService.queryPage(params);
PageUtils page = attrGroupService.queryPage(params, categoryId);
return R.ok().put("page", page);
}
/**
* 信息
*/
@RequestMapping("/info/{id}")
//@RequiresPermissions("product:attrgroup:info")
public R info(@PathVariable("id") Long id){
AttrGroupEntity attrGroup = attrGroupService.getById(id);
//查询出categoryPath的路径
//当前分类ID
Integer categoryId = attrGroup.getCategoryId();
//查询出当前分类ID的 祖宗ID
Long[] path = categoryService.findCategoryPath(categoryId);
attrGroup.setCategoryPath(path);
return R.ok().put("attrGroup", attrGroup);
}
/**
* 保存
*/
@RequestMapping("/save")
//@RequiresPermissions("product:attrgroup:save")
public R save(@RequestBody AttrGroupEntity attrGroup){
attrGroupService.save(attrGroup);
return R.ok();
}
/**
* 修改
*/
@RequestMapping("/update")
//@RequiresPermissions("product:attrgroup:update")
public R update(@RequestBody AttrGroupEntity attrGroup){
attrGroupService.updateById(attrGroup);
return R.ok();
}
/**
* 删除
*/
@RequestMapping("/delete")
//@RequiresPermissions("product:attrgroup:delete")
public R delete(@RequestBody Long[] ids){
attrGroupService.removeByIds(Arrays.asList(ids));
return R.ok();
}
}
CategoryServiceImpl.java
package com.xd.cubemall.product.service.impl;
import com.xd.cubemall.common.utils.PageUtils;
import com.xd.cubemall.common.utils.Query;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xd.cubemall.product.dao.CategoryDao;
import com.xd.cubemall.product.entity.CategoryEntity;
import com.xd.cubemall.product.service.CategoryService;
@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
IPage<CategoryEntity> page = this.page(
new Query<CategoryEntity>().getPage(params),
new QueryWrapper<CategoryEntity>()
);
return new PageUtils(page);
}
/**
* 查询所有分类
* @return
*/
@Override
public List<CategoryEntity> listWithTree() {
//1.查询所有分类
List<CategoryEntity> entities = baseMapper.selectList(null);
//2.组装成父子的树形结构
//2.1 找到所有的一级分类
List<CategoryEntity> levelOneMenus = entities.stream().filter(
//过滤出一级分类,parentId==0,根据这个条件构建出所有一级分类的数据
categoryEntity -> categoryEntity.getParentId() == 0
).map((menu)->{
//出现递归操作,关联出子分类(2,3级分类)
menu.setChildrens(getChildrens(menu,entities));
return menu;
}).collect(Collectors.toList());
return levelOneMenus;
}
/**
* 递归查找指定分类的所有子分类(所有菜单的子菜单)
* @param currentMenu
* @param entities
* @return
*/
private List<CategoryEntity> getChildrens(CategoryEntity currentMenu, List<CategoryEntity> entities) {
List<CategoryEntity> childrens = entities.stream().filter(
//过滤出 当前菜单的所有匹配的子菜单 currentMenu.id == categoryEntity.parentId
categoryEntity -> currentMenu.getId().equals(categoryEntity.getParentId())
).map((menu)->{
//找到子分类
menu.setChildrens(getChildrens(menu,entities));
return menu;
}).collect(Collectors.toList());
return childrens;
}
/**
* 逻辑删除菜单
* @param asList
*/
@Override
public void removeMenuByIds(List<Integer> asList) {
//TODO 检查当前要删除的菜单是否被别的地方引用
//逻辑删除
baseMapper.deleteBatchIds(asList);
}
/**
* 收集三级菜单id
* @param categoryId
* @return [558, 559, 560]
*/
@Override
public Long[] findCategoryPath(Integer categoryId) {
List<Long> paths = new ArrayList<>();
//通过递归查询到 把当前分类id与父分类id 添加到paths集合中
List<Long> parentPath = findParentPath(categoryId, paths);
Collections.reverse(parentPath);
return parentPath.toArray(new Long[parentPath.size()]);
}
/**
* 递归收集菜单id
* @param categoryId
* @param paths
* @return [560, 559, 558]
*/
private List<Long> findParentPath(Integer categoryId, List<Long> paths) {
//收集当前分类id到集合中
paths.add(categoryId.longValue());
CategoryEntity categoryEntity = this.getById(categoryId);
if (categoryEntity.getParentId() != 0){
findParentPath(categoryEntity.getParentId(), paths);
}
return paths;
}
}
前端
attrgroup-add-or-update.vue
<template>
<el-dialog
:title="!dataForm.id ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible"
>
<el-form
:model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-width="130px"
>
<el-form-item label="名称" prop="name">
<el-input v-model="dataForm.name" placeholder="名称"></el-input>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="dataForm.sort" placeholder="排序"></el-input>
</el-form-item>
<el-form-item label="描述" prop="descript">
<el-input v-model="dataForm.descript" placeholder="描述"></el-input>
</el-form-item>
<el-form-item label="图表" prop="icon">
<el-input v-model="dataForm.icon" placeholder="图表"></el-input>
</el-form-item>
<el-form-item label="分类ID" prop="categoryId">
<!-- <el-input v-model="dataForm.categoryId" placeholder="分类ID"></el-input> -->
<el-cascader
v-model="dataForm.categoryPath"
:options="categorys"
:props="props"
></el-cascader>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit()">确定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
data() {
return {
props:{
value: "id",
label: "name",
children: "childrens"
},
categorys: [],
visible: false,
dataForm: {
id: 0,
name: "",
sort: "",
descript: "",
icon: "",
categoryPath: [],
categoryId: 0,
},
dataRule: {
name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
sort: [{ required: true, message: "排序不能为空", trigger: "blur" }],
descript: [
{ required: true, message: "描述不能为空", trigger: "blur" },
],
icon: [{ required: true, message: "图表不能为空", trigger: "blur" }],
categoryId: [
{ required: true, message: "分类ID不能为空", trigger: "blur" },
],
},
};
},
created(){
this.getCategorys()
},
methods: {
// 查询分类菜单
getCategorys() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get",
}).then(({ data }) => {
console.log("成功获取到了菜单数据...", data);
this.categorys = data.data;
});
},
init(id) {
this.dataForm.id = id || 0;
this.visible = true;
this.$nextTick(() => {
this.$refs["dataForm"].resetFields();
if (this.dataForm.id) {
this.$http({
url: this.$http.adornUrl(
`/product/attrgroup/info/${this.dataForm.id}`
),
method: "get",
params: this.$http.adornParams(),
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataForm.name = data.attrGroup.name;
this.dataForm.sort = data.attrGroup.sort;
this.dataForm.descript = data.attrGroup.descript;
this.dataForm.icon = data.attrGroup.icon;
this.dataForm.categoryId = data.attrGroup.categoryId;
//查询categoryID的完整菜单
this.dataForm.categoryPath = data.attrGroup.categoryPath
}
});
}
});
},
// 表单提交
dataFormSubmit() {
this.$refs["dataForm"].validate((valid) => {
if (valid) {
this.$http({
url: this.$http.adornUrl(
`/product/attrgroup/${!this.dataForm.id ? "save" : "update"}`
),
method: "post",
data: this.$http.adornData({
id: this.dataForm.id || undefined,
name: this.dataForm.name,
sort: this.dataForm.sort,
descript: this.dataForm.descript,
icon: this.dataForm.icon,
categoryId: this.dataForm.categoryPath[this.dataForm.categoryPath.length-1],
}),
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.visible = false;
this.$emit("refreshDataList");
},
});
} else {
this.$message.error(data.msg);
}
});
}
});
},
},
};
</script>