黑马瑞吉外卖之套餐信息的修改
基本上在前后端都进行了说明,这个流程,基本很细节的说明了。
在上一篇我们完成了套餐的新建,现在我们来完成一下对套餐信息的修改。
也就是说,我们需要完成下面这个按钮的功能。
现在我们还是去看前端页面,对前后端进行一个整体的理解后然后去开发响应的功能。
下面这里,这是我们修改的按钮,然后这里也同样按钮绑定到了的、方法,所以我们去查看这个方法,进行一步一步的跟进。
所以我们需要去跟进这个方法,叫做addSetMeal这个方法,可以看到这个方法这里其实传递了数据。scope.row那就取这一行的数据对象,然后后面加上了一个id,那么就是去这个数据对象的id,这里是套餐,所以取得就是这个套餐的id。下面这里就是这个具体的跟进的方法,这个方法其实就是包含了两个操作,是根据传参来决定的,我们修改这里传入的参数不是add,所以会定位到下面的修改套餐这里,
然后就定位到add.html,然后就是这样的一个页面。
其实这个页面我们之前都用过的,但是其实这两个页面还是有一点点不一样,就是在页面的展示上面。也就是说这里,在我们的修改套餐这里其实是没有保存并继续添加的,如何针对不同的操作对这里进行选择性的展示呢?原理就是这里的actionType,ok,一个小细节。
然后我们需要注意的就是前端传来的这个套餐的id究竟是干什么用的?其实这里修改的话应该是要进行一个数据的回显。在开发之前其实我们可以试一下能不能进行正常的数据回显。
看这里其实是没有回显成功的,那么我们其实可以先在浏览器中看一下这个404请求到底是什么样的请求。
来看这里,可以看到这里发起了一个get请求
而且这个必然就是我们前面提到的id,所以前端必然有一个包含id的请求方法。
所以我们回去看前端。其实这个方法在这里,我们可以看一下这个方法。
首先这里是一个自动调用的挂载的,然后挂载这里就是有一个this.id尝试获取url定向来的id这个字段参数,我们前面已经看过了,这个字段其实已经传递过来了,那就是套餐的id。所以后面有一个判断this.id的,这里是有值的,所以这里其实是true,那么下面this.init()这里init()方法是可以成功执行的。
然后我们就走到下面这里这个方法,首先给这个方法传入了id,然后发起请求,将id传递进去,然后获取到数据对象,后面进行了一个判断,如果成功返回的话,后面其实就进行了一个赋值,其实本质上就是赋值。所以后面这里就是数据的回显。那么前面传入了id就是给到这个方法,器查询具体的套餐。然后后面就是将这个套餐包含的这些数据返回出去。
那么现在我们就去看这个方法。所以就是这样的一个方法,这和我们在浏览器哪里获取到的请求是相符合的。
那么要回显哪些数据,只回显套餐这个数据肯定是不行的,我们还需要回显到套餐下面关联的菜品。
那么光靠setmeal这个实体类肯定是不够用的,道理还是和之前一样,我们还是用扩展的实体类中扩展的字段接收到数据库返回的数据,然后返回给前端,就是这么一个逻辑。ok。
现在我们开始写这个后端这里回显数据的功能。
我们可以在setmealservice里面定义一个方法,然后在实现去具体实现,然后在controller里面具体调用一下。
接口方法
impl
@Override
public SetmealDto getData(Long id) {
//因为前端给到我们的字段就是id,我们先根据这个id去查询具体的套餐
Setmeal setmeal =this.getById(id);//根据id查询到套餐
//构造扩展出来的setmealDto对象
//最后我们会将所有的数据封装到setmealDto当中
SetmealDto setmealDto = new SetmealDto();
//构造菜品套餐关联的条件查询
LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
//根据套餐来查询菜品
queryWrapper.eq(id!=null,SetmealDish::getSetmealId,id);//这里根据套餐id查询关联的菜品
if (setmeal!=null)//查询到的套餐不是空
{
// 拷贝一下数据
BeanUtils.copyProperties(setmeal,setmealDto);//先将套餐的的数据字段拷贝到扩展的实体类
//这里具体对关联的菜品进行了查询
List<SetmealDish> list = setmealDishService.list(queryWrapper);//这是查询到的菜品数据
setmealDto.setSetmealDishes(list);//将菜品数据传过去
return setmealDto;
}
return null;
}
然后在controller里面这样调用就可以了
}
/*这里主要做一个数据回显*/
@GetMapping("/{id}")
public R_<SetmealDto> getData(@PathVariable Long id)
{
SetmealDto setmealDto = setMealService.getData(id);
return R_.success(setmealDto);
}
这样这些数据就可以被正常回显了
然后这样我们就可以按照这个回显的数据去正常的进行修改了。
这里的修改除了添加文本框里面就的数据以及上传图片以外,我们还是可以去添加菜品的。
这里这个添加菜品具体的方法就写在这里了。其实这个方法在我们新建套餐的时候也会用到,下面都是。在这里简单提一下,主要是为了明白各个环节是怎么做到的。
然后我们继续往下走,注意看这里,这里会有一个绑定,就是将this.ruleForm的数据赋值给了prams这里,那么这有什么用处呢?
继续往下看,这里就是我们的具体的方法,prams就是我们刚刚赋值给的参数,那么我们修改的数据也会被绑定到这里,这样就成功完成了数据的绑定传递。
接下来我们就可以去看具体的这个保存的方法了。那就是这个方法,修改数据的话就是提交了一个请求,然后里面也携带了数据,请求路径已经写的很明了了,所以我们现在就可以去写它的方法了。
在修改的时候我们需要做两点,一个是保存修改套餐的数据,一个是保存套餐关联的菜品。其实在修改关联菜品这里,我们可以选择现将这些数据都溢出掉,然后给它多一个批量保存的操作,套餐这边我们还是正常的更新。
在关联菜品修改这里我们还是和之前一样需要主语到setmealId,这个说明请看新建套餐那里,因为我们需要关联菜品表下的套餐id和具体的关联的菜品相对应。
现在我们来看这个代码,代码是直接写在了controller里面
@PutMapping
public R_<String> edit(@RequestBody SetmealDto setmealDto)
{
//先判断是否接收到数据
if(setmealDto==null)
{
return R_.error("请求异常");
}
//判断套餐下面是否还有关联菜品
if(setmealDto.getSetmealDishes()==null)
{
return R_.error("套餐没有菜品,请添加");
}
//获取到关联的菜品列表,注意关联菜品的列表使我们提交过来的
List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
//获取到套餐的id
Long setmealId = setmealDto.getId();
//构造关联菜品的条件查询
LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
//根据套餐id在关联菜品中查询数据,注意这里所做的查询是在数据库中进行查询的
queryWrapper.eq(SetmealDish::getSetmealId,setmealId);
//关联菜品先移除掉原始数据库中的数据
setmealDishService.remove(queryWrapper);
//为setmeal_dish表填充相关的属性
//这里我们需要为关联菜品的表前面的字段填充套餐的id
for(SetmealDish setmealDish:setmealDishes)
{
setmealDish.setSetmealId(setmealId);//填充属性值
}
//批量把setmealDish保存到setmeal_dish表
//这里我们保存了我们提交过来的关联菜品数据
setmealDishService.saveBatch(setmealDishes);//保存套餐关联菜品
//这里我们正常更新套餐
setMealService.updateById(setmealDto);//保存套餐
return R_.success("套餐修改成功");
}
注:这里的基本每行代码都添加了注释,有不明白的尽管提问。下期见。