【Java项目实战】瑞吉外卖-06 套餐管理业务开发(包含修改套餐和单个/批量停售和启售方法)
套餐管理业务开发
一、新增套餐
需求分析
套餐就是菜品的集合。后台系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐。
数据模型
新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表,还需要向setmeal_dish表中插入套餐和菜品关联数据,所以在新增套餐时,涉及到两个表:
setmeal(套餐表) setmeal_dish(套餐菜品关系表)
代码开发
所需要的类和接口:实体类SetmealDish、SetmealDto;Mapper接口SetmealDishMapper;业务层接口SetmealDishService;业务层实现类SetmealDishServiceImpl;控制层StemealController
前端页面和服务端的交互过程:
1.页面(backend/page/combo/add.html)发送ajax请求,请求服务端获取套餐分类数据并展示到下拉框中;
2.页面发送ajax请求,请求服务端获取菜品分类数据并展示到添加菜品窗口中;
3.页面发送ajax请求,请求服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中;
4.页面发送请求并进行图片上传,请求服务端将图片保存到服务器;
5.页面发送请求进行图片下载,将上传的图片进行回显;
6.点击保存按钮,发送ajax请求,将套餐相关数据以json形式提交到服务端。
开发新增套餐功能,其实就是在服务端编写代码去处理前端页面发送的这6次请求。
点击新增套餐,前端页面发送的请求:
请求路径category/list?type=2 获得套餐分类数据 之前已经写过
请求路径category/list/?type=1 获得菜品分类数据
点击添加菜品,发送的请求:
请求路径dish/list
/**
* 新增套餐中,根据条件查询菜品分类下对应的菜品数据
* @param dish
* @return
*/
@GetMapping("/list")
public R<List<Dish>> list(Dish dish){
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
//查询条件
queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());
queryWrapper.eq(Dish::getStatus,1); //查询在售的菜品
//添加排序条件
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
List<Dish> list = dishService.list(queryWrapper);
return R.success(list);
}
使用SetmealDto封装stemeal和stemealdish信息,返回给页面。
SetmealService实现类重写方法来保存两部分内容
SetmealController方法
/**
* 套餐管理业务开发
*/
@RestController
@RequestMapping("/setmeal")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
/**
* 新增套餐
* @param setmealDto
* @return
*/
@PostMapping
public R<String> save(@RequestBody SetmealDto setmealDto){
log.info("套餐信息:{}",setmealDto);
setmealService.saveWithDish(setmealDto);//Service实现类重写的方法
return R.success("新增套餐成功");
}
}
二、套餐信息分页查询
需求分析
系统中的套餐数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般系统中都会以分页的方式来展示列表数据。
代码开发
前端页面和服务端的交互过程:
1.页面(backend/page/combo/list.html)发送ajax请求,将分页查询参数(page、pageSize、name)提交到服务端,获取分页数据;
2.页面发送请求,请求服务端进行图片下载,用于页面图片展示。
开发套餐信息分页查询功能,其实就是在服务端编写代码去处理前端页面发送的这2次请求。
查询套餐名称时,发送的请求
/**
* 套餐信息分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
Page<Setmeal> pageInfo = new Page<>(page,pageSize);
Page<SetmealDto> setmealdtoPage = new Page<>();
LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
//查询条件
queryWrapper.like(name != null,Setmeal::getName,name);
//排序条件
queryWrapper.orderByDesc(Setmeal::getUpdateTime);
setmealService.page(pageInfo,queryWrapper);
//对象拷贝
BeanUtils.copyProperties(pageInfo,setmealdtoPage,"records");
List<Setmeal> records = pageInfo.getRecords();
List<SetmealDto> list = records.stream().map(item ->{
SetmealDto setmealDto = new SetmealDto(); //new出来的setmealDto没有封装信息
Long categoryId = item.getCategoryId();
BeanUtils.copyProperties(item,setmealDto);//把item中除了categoryName属性的信息都赋值给setmealDto
Category category = categoryService.getById(categoryId);
if(category != null){
String categoryName = category.getName();
setmealDto.setCategoryName(categoryName); //把categoryName属性赋值给setmealDto
}
return setmealDto;
}).collect(Collectors.toList());
setmealdtoPage.setRecords(list);
return R.success(setmealdtoPage);
}
当没有拷贝套餐分类名称的时候
使用对象拷贝,显示套餐分类名称
三、删除套餐
需求分析
在套餐管理列表页面点击删除按钮,可以删除对应的套餐信息,也可以通过复选框选择多个套餐,点击批量删除按钮异常删除多个套餐。注意:对应状态为售卖中的套餐不能删除,需要先停售,然后才能删除。
代码开发
前端页面和服务端的交互过程:
删除单个/批量删除套餐时,页面发送ajax请求
删除单个、批量删除套餐的请求信息可以发现,两种请求的地址和请求方式都是相同的,不同的是传递id的个数,所以在服务端可以提供一个方法来统一处理。
要删除套餐和套餐菜品表中的内容,在SetmealService中重写删除方法
/**
* 删除套餐
* @param ids
* @return
*/
@DeleteMapping
public R<String> remove(@RequestParam List<Long> ids){
log.info("ids:{}",ids);
setmealService.removeWithDish(ids);
return R.success("删除套餐成功");
}
四、套餐单个/批量起售或者停售
代码开发
前端页面发送的请求
单个请求
批量请求
SetmealDishService实现类重写实现方法
/**
* 套餐单个/批量停售或者起售
* @param status
* @param ids
*/
public void updateSetmealStatus(Integer status, List<Long> ids) {
LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ids != null,Setmeal::getId,ids);
List<Setmeal> list = this.list(queryWrapper);
for (Setmeal setmeal : list) {
if(setmeal != null){
setmeal.setStatus(status);
this.updateById(setmeal);
}
}
}
SetmealController方法
五、修改套餐信息
代码开发
修改套餐信息,需要分两步完成,首先进行数据回显,然后再修改信息
数据回显
前端页面发送的请求
SetmealDishService实现类重写实现方法
/**
* 修改套餐信息:数据回显 根据id查询套餐信息和对应的菜品信息
* @param id
* @return
*/
public SetmealDto getByIdWithDish(Long id) {
//从setmeal表中查setmeal信息,并将信息赋值给SetmealDto
Setmeal setmeal = this.getById(id);
SetmealDto setmealDto = new SetmealDto();
BeanUtils.copyProperties(setmeal,setmealDto);
//从setmealdish表中查菜品信息,并将信息赋值给SetmealDto
LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SetmealDish::getSetmealId,setmeal.getId());
List<SetmealDish> dishes = setmealDishService.list(queryWrapper);
setmealDto.setSetmealDishes(dishes); //设置菜品信息
return setmealDto;
}
SetmealController方法
修改信息
前端页面发送的请求
SetmealDishService实现类重写实现方法
/**
* 修改套餐信息
* @param setmealDto
*/
public void updateWithDish(SetmealDto setmealDto) {
//修改除菜品外的其他基本信息
this.updateById(setmealDto);
//修改套餐中的菜品信息,采用的方法是首先删除数据表中的原来的菜品信息,然后再添加新的菜品信息
LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SetmealDish::getSetmealId,setmealDto.getId());
setmealDishService.remove(queryWrapper);
List<SetmealDish> dishes = setmealDto.getSetmealDishes();
dishes = dishes.stream().map((item) ->{
item.setSetmealId(setmealDto.getId());
return item;
}).collect(Collectors.toList());
setmealDishService.saveBatch(dishes);
}
SetmealController方法
tao87118: 你好,想请教一下,这个小根堆只是对于单个数据排序没有问题,那比如说我{0,1}, {1,1}, {0,2}, {1,2}, {0,3},,这样入队后,可能出来顺序就是{0,1}, {0,3} {0,2}, {1,2},, {1,1},因为它只是对比优先级了,没有考虑顺序了,那这种怎么解决了
CSDNCR: 感谢 分享!!!必须点赞!!!!!
watershed1993: 找了半天,楼主这篇是讲PriorityQueue 最为详细的! 感谢!
zhpzhp321: 非常不错
正在学习的浅语: 大佬,这怎么知道前端需要那些数据呀