注:本文章基于黑马程序员相关视频及资料进行编写,代码简单,较容易理解,若有问题或者源码资料获取可以在评论区留言或者联系作者!
开篇
一、新增套餐
(1)需求分析:
套餐就是菜品的集合,后台系统中可以管理套餐信息,通过新增套餐功能来添加一个新的套餐,在添加套餐的时候需要选择当前套餐所属的套餐分类和包含的菜品,并且需要上传套餐对应的图片,在移动端会按照套餐分类来展示对应的套餐;
新增套餐,其实就是将新增页面录入的套餐信息插入到setmeal表(套餐表),还需要向Setmeal_dish(套餐菜品关联表)表中插入套餐和菜品关联的数据,所以在新增套餐的时候,涉及到两个表;
(2)代码开发-准备工作:
- 实体类Setmeal和Setmeal_dish类
- DTO类 SetmealDto
@Data
public class SetmealDto extends Setmeal {
private List<SetmealDish> setmealDishes;
private String categoryName;
}
- Mapper接口SetmealDishMapper
- 业务层接口SetmealDishService
public interface SetmealDishService extends IService<SetmealDish> {
}
- 业务层实现类SetmealDishServiceImpl
@Service
public class SetmealDishServiceImpl extends ServiceImpl<SetmealDishMapper, SetmealDish> implements SetmealDishService {
}
- 控制层 SetmealController
@RestController
@RequestMapping("/setmeal")
@Slf4j
public class SetmealController {
@Autowired
private SetmealService setmealService;
@Autowired
private SetmealDishService setmealDishService;
}
(3)代码开发-交互过程
- 页面发送ajax请求,获取套餐分类数据并展示到下拉框中(前面已实现)
- 页面发送ajax请求,请求服务端获取菜品分类中数据并展示到添加菜品的窗口中(前面已实现);
- 页面发送ajax请求,请去服务端,根据菜品分类查询对应的菜品数据并展示到添加菜品的窗口中
- 页面进行图片的上传与下载请求(前面已实现)
- 点击保存按钮,页面发送ajax请求,套餐相关数据以json数据的格式提交到服务端;
首先根据菜品分类查询对应的菜品数据,将前端传来的CategoryId封装成一个Dish对象,然后进行数据库查询,根据查询条件返回一个Dish的列表数据,
/*根据条件来查询对应的菜品*/
@GetMapping("/list")
public R<List<Dish>> list(Dish dish){
LambdaQueryWrapper<Dish> queryWrapper=new LambdaQueryWrapper<>();
queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
//查询起售状态为1的
queryWrapper.eq(Dish::getStatus,1);
//添加一个排序条件
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
List<Dish> list = dishService.list(queryWrapper);
return R.success(list);
}
然后是服务端接受页面提交的数据,将套餐数据分别保存到Setmeal和SetmealDish表中,可以在SetmealServiseImpl类中编写具体实现方法:
/*新增套餐同时保存套餐和菜品的关联关系*/
@Override
@Transactional
public void savewithDish(SetmealDto setmealDto) {
//保存套餐的基本信息 执行inset操作
this.save(setmealDto);
//保存套餐和菜品的关联信息,操作setmeal_dish 执行insert操作
List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
setmealDishes.stream().map((item)->{
item.setSetmealId(setmealDto.getId());
return item;
}).collect(Collectors.toList());
setmealDishService.saveBatch(setmealDishes);
}
最后编写接口调用此方法,并返回响应结果:
/*新增套餐*/
@PostMapping
public R<String> save(@RequestBody SetmealDto setmealDto){
log.info("套餐信息{}",setmealDto);
setmealService.savewithDish(setmealDto);
return R.success("新增套餐成功");
}
二、套餐信息分页查询
(1)需求分析:系统中的套餐数据很多的时候,如果在一个页面中全部展示出来会显得比较乱,不便于查看,所以一般系统中都会以分页的方式来展示列表数据;
(2) 代码开发-梳理交互过程
- 页面发送ajax请求,将分页查询参数(page,pageSize,name)提交到服务端,获取分页数据
- 页面发送请求,请求服务端进行图片下载,用于图片展示
具体代码实现和之前一样,首先需要构造两个page对象,Page < Setmeal> 和Page < SetmealDto>,然后将Page < Setmeal>对象中的除records数据赋值到Page < SetmealDto>中,也就是page,pageSIze等数据;
然后将records中的数据进行提取,将records中的列表数据Setmeal拷贝到SetmealDto中,再查询categoryName值对SetmealDto进行封装。最后将所有的SetmealDto返回成一个列表赋值给Page < SetmealDto>的records数据;
/*套餐分页查询*/
@GetMapping("/page")
public R<Page> page(int page,int pageSize,String name){
//分页构造器
Page<Setmeal> pageInfo=new Page<>(page,pageSize);
Page<SetmealDto> pageDto=new Page<>();
//对象拷贝
BeanUtils.copyProperties(pageInfo,pageDto,"records");
LambdaQueryWrapper<Setmeal> queryWrapper =new LambdaQueryWrapper<>();
queryWrapper.like(name!=null,Setmeal::getName,name);
//根据更新时间降序排列
queryWrapper.orderByDesc(Setmeal::getUpdateTime);
setmealService.page(pageInfo, queryWrapper);
List<Setmeal> records = pageInfo.getRecords();
List<SetmealDto> list=records.stream().map((item)->{
SetmealDto setmealDto=new SetmealDto();
BeanUtils.copyProperties(item,setmealDto);
//根据分类的id查询分类的对象
Category category = categoryService.getById(item.getCategoryId());
if (category!=null){
//分类名称
String categoryName = category.getName();
setmealDto.setCategoryName(categoryName);
}
return setmealDto;
}).collect(Collectors.toList());
pageDto.setRecords(list);
return R.success(pageDto);
}
运行结果如下图所示:
三、删除套餐
(1)需求分析:
在套餐管理列表页面,点击删除按钮,可以删除对应的套餐信息,也可以通过复选框选择多个套餐,点击批量删除按钮一次删除多个套餐,注意,对弈状态为售卖中的套餐不能删除,需要首先停售,然后才能删除;
(2) 代码开发-梳理交互流程
- 删除单个套餐时,页面发送AJAX请求,根据套餐id删除对应套餐
- 删除多个套餐时,页面发送AJAX请求,根据提交的多个套餐id删除对应套餐
开发删除功能时,其实就是在服务端编写代码去处理前端页面发送的这2此请求即可,观察删除单个套餐和批量删除套餐的请求信息可以发现,两种请求的地址和请求的方式都是相同的,不同的是传递的id的个数,所有在服务端可以提供一个方法来统一处理。
(3)代码开发-具体编码
由于删除功能设计到Setmeal表和Setmealdish表,所以可以在SetmealService中新编写一个方法,用于实现删除功能
/*删除套餐,同时删除套餐和菜品的关联数据*/
@Override
@Transactional
public void removeWithDish(List<Long> ids) {
//查询套餐状态,确定可以删除
LambdaQueryWrapper<Setmeal> queryWrapper =new LambdaQueryWrapper<>();
queryWrapper.in(Setmeal::getId,ids);
queryWrapper.eq(Setmeal::getStatus,1);
int count=this.count(queryWrapper);
if (count>0){
//如果不能删除,则抛出一个异常
throw new CustomException("套餐正在售卖中,不能删除");
}
//如果可以删除,先删除套餐表中的数据,根据主键id批量删除
this.removeByIds(ids);
//删除关系表中的数据,根据条件批量删除
LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper =new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(SetmealDish::getSetmealId,ids);
setmealDishService.remove(lambdaQueryWrapper);
}
运行项目,删除一个菜品,可以正常删除;
如果感觉内容写的还不错的话,一键三连不迷路!!!!
后面将会更新更多学习内容,一起学习吧!!!!!!