1. 商品分类实现
1.1 关于商品分类的概述
说明:商品分类信息一般采用3级商品分类的形式
思考: 3级商品分类信息 一般采用什么样的结构进行关联! 一般采用parent_id的方式进行关联
1.2 表结构
说明: 在表中通过parent_id 进行关联
查询一级商品分类信息:
SELECT * FROM item_cat WHERE parent_id=0
SELECT * FROM item_cat WHERE parent_id=1
SELECT * FROM item_cat WHERE parent_id=2
1.3 编辑ItemCat POJO对象
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@TableName("item_cat")
@Data
@Accessors(chain = true)
public class ItemCat extends BasePojo{
@TableId(type = IdType.AUTO)
private Integer id; //定义主键
private Integer parentId; //定义父级菜单
private String name; //分类名称
private Boolean status; //分类状态 0 停用 1 正常
private Integer level; //商品分类等级 1 2 3
@TableField(exist = false)
private List<ItemCat> children;
}
1.4 搭建商品分类层级代码
1.5 实现商品分类页面跳转
import ItemCat from '../components/items/ItemCat.vue'
import ItemCatParam from '../components/items/ItemCatParam.vue'
Vue.use(VueRouter)
const routes = [
{path: '/', redirect: '/login'},
{path: '/login', component: Login},
{path: '/home', component: Home,
redirect: 'welcome' ,children:[
{path: '/welcome' , component: Welcome},
{path: '/user', component: User},
{path: '/itemCat',component: ItemCat},
{path: '/itemCatParam',component: ItemCatParam}
]},]
2. 商品分类开发
2.1 实现商品分类列表展现
2.1.1 发起ajax请求
1).利用钩子函数(created()/mounted() )实现数据获取
//定义初始化函数
created() {
//默认获取商品分类列表数据
this.findItemCatList()
},
2).定义商品分类属性
data() {
return {
//定义商品分类数据
itemCatList: [],
//控制分类对话框的显示
addItemCatDialogVisible: false,
//定义商品分类新增对象
itemCatForm: {
name: '', //定义商品分类名称
parentId: 0, //默认父级ID=0
level: 1 //默认是一级菜单
},
3).发起ajax请求,获取商品分类信息
methods: {
async findItemCatList() {
const {
data: result
} = await this.$http.get("/itemCat/findItemCatList/3")
if (result.status !== 200) return this.$message.error("获取商品分类列表失败!!")
this.itemCatList = result.data
},
2.1.2 业务接口文档
2.1.3 查询实现策略
1).左外连接 关联条件 p.id = c.parent_id
实现思路,图中没有筛选字段,所以不能正常执行,需要优化 ,该图只是提供了一种解决思路.
2).for循环写法
//如何实现3级商品分类的嵌套
//SELECT * FROM item_cat WHERE parent_id=0
//思考: 1.for循环 2.递归写法 3.尽可能降低数据库查询次数
// 3.张三表左外连接 mysql执行速度快 业务执行的速度快
// 单表查询快 关联查询快??
@Override
public List<ItemCat> findItemCatList(Integer type) {
/*if(type == 1){ //只查询一级商品分类
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", 0 );
List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
return oneList;
}
if(type==2){
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", 0 );
List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
//根据一级查询二级信息
for(ItemCat oneItemCat : oneList){
QueryWrapper<ItemCat> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.eq("parent_id", oneItemCat.getId());
List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper2);
oneItemCat.setChildren(twoList);
}
return oneList;
}*/
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", 0 );
List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
//根据一级查询二级信息
if(oneList == null) return null;
for(ItemCat oneItemCat : oneList){
QueryWrapper<ItemCat> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.eq("parent_id", oneItemCat.getId());
List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper2);
//根据二级查询3级
if(twoList == null) return null;
for(ItemCat twoItemCat : twoList){
QueryWrapper<ItemCat> queryWrapper3 = new QueryWrapper<>();
queryWrapper3.eq("parent_id", twoItemCat.getId());
List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper3);
twoItemCat.setChildren(threeList);
}
oneItemCat.setChildren(twoList);
}
return oneList;
}
2.1.4 编辑ItemCatController
@RestController
@CrossOrigin
@RequestMapping("/itemCat")
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
/**
* 实现商品分类查询
* URL地址: /itemCat/findItemCatList
* 参数: type
* 返回值: SysResult对象
*/
@GetMapping("/findItemCatList/{type}")
public SysResult findItemCatList(@PathVariable Integer type){
List<ItemCat> itemCatList = itemCatService.findItemCatList(type);
return SysResult.success(itemCatList);
}
}
2.1.5 编辑ItemCatService
//问题: 代码与数据库交互频繁必须优化
//思路: 1.只查询一次数据库
// 2.Map<parentId,List<ItemCat>>
public Map<Integer,List<ItemCat>> getMap(){
Map<Integer,List<ItemCat>> map = new HashMap<>();
//1.查询所有的数据
List<ItemCat> itemCatList =
itemCatMapper.selectList(null);
//2.封装Map集合数据
//2.1存储依据: 如果key存在?获取子级之后add操作
//2.2 如果key不存在 则将key存储,同时将自己当做第一个元素保存
for (ItemCat itemCat : itemCatList){
int parentId = itemCat.getParentId();
//判断map集合中是否有父级
if(map.containsKey(parentId)){
//有父级 将自己添加到子级中
map.get(parentId).add(itemCat);
}else{
List<ItemCat> list = new ArrayList<>();
list.add(itemCat);
map.put(parentId,list);
}
}
return map;
}
@Override
public List<ItemCat> findItemCatList(Integer type) {
Map<Integer,List<ItemCat>> map = getMap();
if(type == 1) return map.get(0);
if(type == 2) return findTwoItemCatList(map);
return findThreeItemCatList(map);
}
public List<ItemCat> findTwoItemCatList(Map<Integer,List<ItemCat>> map){
//1.获取一级商品分类
List<ItemCat> oneList = map.get(0);
//2.根据一级查询二级
for(ItemCat itemCat : oneList){
List<ItemCat> twoList = map.get(itemCat.getId());
itemCat.setChildren(twoList);
}
return oneList;
}
private List<ItemCat> findThreeItemCatList(Map<Integer,List<ItemCat>> map) {
List<ItemCat> oneList = findTwoItemCatList(map);
for (ItemCat itemCat : oneList){ //1级菜单
if(itemCat.getChildren() !=null){
for(ItemCat itemCat2 :itemCat.getChildren()){
List<ItemCat> threeList = map.get(itemCat2.getId());
itemCat2.setChildren(threeList);
}
}
}
return oneList;
}
2.1.6 页面结果
2.1.7 表格数据的父子关系
数据结构:
2.2 实现商品分类状态修改
2.2.1 页面HTML
2.2.2 页面JS
2.2.3 编辑业务接口
2.2.4 编辑ItemCatController
/**
* 修改商品分类状态
* 请求路径: /itemCat/status/{id}/{status}
* 请求类型: put
* 请求参数: /{id}/{status}
* 返回值类型: SysResult
*/
@PutMapping("/status/{id}/{status}")
public SysResult updateStatus(ItemCat itemCat){
itemCatService.updateStatus(itemCat);
return SysResult.success();
}
2.2.5 编辑ItemCatService
//id/status
@Override
public void updateStatus(ItemCat itemCat) {
itemCatMapper.updateById(itemCat);
}
2.3 关于SpringMVC注解说明
@RestController 作用范围 类 当前Controller类交给Spring容器管理 同时所有的返回值都是JSON
@CrossOrigin 解决跨域问题的注解 违反了同源策略
@RequestMapping("/itemCat") 作用范围: 类/方法 支持所有的请求类型
-GetMapping("…")
@PathVariable restFul的风格获取数据
1.url地址 /user/{type}
2.方法findItemCatList(@PathVariable Integer type)
3.方法findItemCatList(XX对象) 如果对象的属性与{名称}一致 则可以省略注解.
2.4 商品分类新增
2.4.1 编辑新增页面
2.4.2 级联选择器
属性说明: v-model 用户选中的元素的数据绑定
options: 级联选择器的 数据的来源 如果有children属性,默认解析为父子关系.
props: 设定选择器的运行方式 点击运行,还是触发运行.
2.4.3 编辑页面JS
async addItemCatForm() {
//先将整个表单进行校验
this.$refs.itemCatFormRef.validate(async validate => {
if (!validate) return
const {
data: result
} = await this.$http.post("/itemCat/saveItemCat", this.itemCatForm)
if (result.status !== 200) return this.$message.error("新增商品分类失败")
this.$message.success("新增商品分类成功!!!")
//新增成功,则刷新分类列表信息
this.findItemCatList();
this.addItemCatDialogVisible = false
})
},
2.4.4 业务接口文档
2.4.5 编辑ItemCatController
/**
* 商品分类新增
* 请求路径: /itemCat/saveItemCat
* 请求类型: post ,前端采用post/put的方式进行传参,该数据被解析为JSON
* 所以
* 请求参数: 表单数据 使用ItemCat对象
* 返回值类型: SysResult
*/
@PostMapping("/saveItemCat")
public SysResult saveItemCat(@RequestBody ItemCat itemCat){
itemCatService.saveItemCat(itemCat);
return SysResult.success();
}
2.4.6 编辑ItemCatService
注意事务控制:
//原子性:
@Override
@Transactional //对方法进行事务的控制,确保原子性
public void saveItemCat(ItemCat itemCat) {
//自动填充功能 created/updated
itemCat.setStatus(true); //启用状态
itemCatMapper.insert(itemCat);
}
2.5 商品删除实现
2.5.1 要求
说明: 如果删除的数据有子级,则应该将子级一齐删除.
2.5.2 页面分析
2.5.3 页面JS
2.5.4 删除的接口文档
2.5.5 编辑ItemCatController
/**
* 删除商品分类数据
* URL: http://localhost:8091/itemCat/deleteItemCat?id=1&level=1
* 参数: id/level
* 返回值: SysResult对象
*/
@DeleteMapping("/deleteItemCat")
public SysResult deleteItemCat(ItemCat itemCat){
itemCatService.deleteItemCat(itemCat);
return SysResult.success();
}
2.5.6 编辑ItemCatService
/**
* 实现商品分类删除
* @param itemCat
* 实现思路:
* 根据level 判断层级 之后根据ID删除数据.
* 删除: 1.手写sql delete from item_cat where id in(100,200...)
* 2.利用MP机制实现删除
*/
@Override
public void deleteItemCat(ItemCat itemCat) {
//1.判断等级是否为3级
if(itemCat.getLevel() == 3){
itemCatMapper.deleteById(itemCat.getId());
}
if(itemCat.getLevel() == 2) {
//1.先删除3级信息
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("parent_id", itemCat.getId());
itemCatMapper.delete(queryWrapper);
//2.再删除自己
itemCatMapper.deleteById(itemCat.getId());
}
if(itemCat.getLevel() == 1){
//1.查询所有的二级菜单
QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", itemCat.getId());
List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
for(ItemCat itemCat2 : twoList){
//parent_id=二级的Id
QueryWrapper queryWrapper2 = new QueryWrapper();
queryWrapper2.eq("parent_id", itemCat2.getId());
itemCatMapper.delete(queryWrapper2);//删除3级
itemCatMapper.deleteById(itemCat2.getId());//删除2级
}
itemCatMapper.deleteById(itemCat.getId());
}
}
2.6 商品分类修改
2.6.1 页面HTML分析
2.6.2 编辑页面JS
//由于有层级关系,所有修改只能修改名称
updateItemCatBtn(itemCat) {
this.updateItemCatForm = itemCat
this.updateItemCatDialogVisible = true
},
async updateItemCat() {
//修改商品分类信息
const {
data: result
} = await this.$http.put('/itemCat/updateItemCat', this.updateItemCatForm)
if (result.status !== 200) return this.$message.error("更新商品分类失败")
this.$message.success("更新商品分类成功")
this.findItemCatList();
this.updateItemCatDialogVisible = false;
},
2.6.3 编辑ItemCatController
// 参数id ,status
@Override
@Transactional //对方法进行事务的控制,确保原子性
public void updateStatus(ItemCat itemCat) {
itemCatMapper.updateById(itemCat);
}
2.6.4 编辑ItemCatService
@Override
public void updateItemCat(ItemCat itemCat) {
itemCatMapper.updateById(itemCat);
}